V0.9: Back port fixes for putting modpath delays and delay calculations

This commit is contained in:
Cary R 2014-10-27 14:22:49 -07:00
parent bf08fcd5e7
commit b18aedfa80
2 changed files with 56 additions and 29 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005-2011 Stephen Williams <steve@icarus.com> * Copyright (c) 2005-2014 Stephen Williams <steve@icarus.com>
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -505,10 +505,10 @@ static vvp_time64_t delay_from_edge(vvp_bit4_t a, vvp_bit4_t b,
{ {
typedef delay_edge_t bit4_table4[4]; typedef delay_edge_t bit4_table4[4];
const static bit4_table4 edge_table[4] = { const static bit4_table4 edge_table[4] = {
{ DELAY_EDGE_01, DELAY_EDGE_01, DELAY_EDGE_0x, DELAY_EDGE_0z }, { DELAY_EDGE_01, DELAY_EDGE_01, DELAY_EDGE_0z, DELAY_EDGE_0x },
{ DELAY_EDGE_10, DELAY_EDGE_10, DELAY_EDGE_1x, DELAY_EDGE_1z }, { DELAY_EDGE_10, DELAY_EDGE_10, DELAY_EDGE_1z, DELAY_EDGE_1x },
{ DELAY_EDGE_x0, DELAY_EDGE_x1, DELAY_EDGE_x0, DELAY_EDGE_xz }, { DELAY_EDGE_z0, DELAY_EDGE_z1, DELAY_EDGE_z0, DELAY_EDGE_zx },
{ DELAY_EDGE_z0, DELAY_EDGE_z1, DELAY_EDGE_zx, DELAY_EDGE_z0 } { DELAY_EDGE_x0, DELAY_EDGE_x1, DELAY_EDGE_xz, DELAY_EDGE_x0 }
}; };
return array[ edge_table[a][b] ]; return array[ edge_table[a][b] ];
@ -818,14 +818,27 @@ static void modpath_src_put_delays (vpiHandle ref, p_vpi_delay delays)
assert( fun ); assert( fun );
typedef unsigned char map_array_t[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}; // Only the first six entries are used for the less than twelve maps.
static const map_array_t map_1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static const map_array_t map_2 = {0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0};
static const map_array_t map_3 = {0, 1, 2, 0, 2, 1, 0, 0, 0, 0, 0, 0};
static const map_array_t map_6 = {0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0};
static const map_array_t map12 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; 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; const map_array_t*use_map = 0;
switch (delays->no_of_delays) { switch (delays->no_of_delays) {
case 1:
use_map = &map_1;
break;
case 2: case 2:
use_map = &map_2; use_map = &map_2;
break; break;
case 3:
use_map = &map_3;
break;
case 6:
use_map = &map_6;
break;
case 12: case 12:
use_map = &map12; use_map = &map12;
break; break;
@ -845,22 +858,26 @@ static void modpath_src_put_delays (vpiHandle ref, p_vpi_delay delays)
} }
} }
/* Now clean up any to-from-x delays to me the min/max based on /* Now define the to-from-x delays if needed. */
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) { if (delays->no_of_delays <= 6) {
vvp_time64_t t_max = tmp[0]; /* 0->x is the minimum of 0->z and 0->1. */
vvp_time64_t t_min = tmp[1]; tmp[DELAY_EDGE_0x] = tmp[DELAY_EDGE_0z] < tmp[DELAY_EDGE_01] ?
for (idx = 1 ; idx < delays->no_of_delays ; idx += 1) { tmp[DELAY_EDGE_0z] : tmp[DELAY_EDGE_01];
if (tmp[idx] > t_max) t_max = tmp[idx]; /* x->1 is the maximum of z->1 and 0->1. */
if (tmp[idx] < t_min) t_min = tmp[idx]; tmp[DELAY_EDGE_x1] = tmp[DELAY_EDGE_z1] > tmp[DELAY_EDGE_01] ?
} tmp[DELAY_EDGE_z1] : tmp[DELAY_EDGE_01];
tmp[DELAY_EDGE_0x] = t_min; /* 1->x is the minimum of 1->z and 1->0. */
tmp[DELAY_EDGE_x1] = t_max; tmp[DELAY_EDGE_1x] = tmp[DELAY_EDGE_1z] < tmp[DELAY_EDGE_10] ?
tmp[DELAY_EDGE_1x] = t_min; tmp[DELAY_EDGE_1z] : tmp[DELAY_EDGE_10];
tmp[DELAY_EDGE_x0] = t_max; /* x->0 is the maximum of z->0 and 1->0. */
tmp[DELAY_EDGE_xz] = t_max; tmp[DELAY_EDGE_x0] = tmp[DELAY_EDGE_z0] > tmp[DELAY_EDGE_10] ?
tmp[DELAY_EDGE_zx] = t_min; tmp[DELAY_EDGE_z0] : tmp[DELAY_EDGE_10];
/* x->z is the maximum of 1->z and 0->z. */
tmp[DELAY_EDGE_xz] = tmp[DELAY_EDGE_1z] > tmp[DELAY_EDGE_0z] ?
tmp[DELAY_EDGE_1z] : tmp[DELAY_EDGE_0z];
/* z->x is the minimum of z->1 and z->0. */
tmp[DELAY_EDGE_zx] = tmp[DELAY_EDGE_z1] < tmp[DELAY_EDGE_z0] ?
tmp[DELAY_EDGE_z1] : tmp[DELAY_EDGE_z0];
} }
fun->put_delay12(tmp); fun->put_delay12(tmp);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com) * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -67,16 +67,26 @@ double vpip_time_to_scaled_real(vvp_time64_t ti, struct __vpiScope*scope)
vvp_time64_t vpip_scaled_real_to_time64(double val, struct __vpiScope*scope) vvp_time64_t vpip_scaled_real_to_time64(double val, struct __vpiScope*scope)
{ {
int units; int shift = 0;
if (scope) if (scope) shift = scope->time_units - scope->time_precision;
units = scope->time_units; assert(shift >= 0);
else
units = vpi_time_precision;
double scale = pow(10.0L, units - vpi_time_precision); assert(val >= 0);
// Scale to the local precision and then round away from zero.
double scale = pow(10.0L, shift);
val *= scale; val *= scale;
return (vvp_time64_t) val; vvp_time64_t delay = (vvp_time64_t) (val + 0.5);
// If needed now scale the value to the simulator precision.
if (scope) {
shift = scope->time_precision - vpi_time_precision;
assert(shift >= 0);
for (int lp = 0; lp < shift; lp += 1) delay *= 10;
}
return delay;
} }
static int timevar_time_get(int code, vpiHandle ref) static int timevar_time_get(int code, vpiHandle ref)