From b18aedfa80df634bf95a64ebf43d77d455bc577c Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 27 Oct 2014 14:22:49 -0700 Subject: [PATCH] V0.9: Back port fixes for putting modpath delays and delay calculations --- vvp/delay.cc | 59 +++++++++++++++++++++++++++++++------------------ vvp/vpi_time.cc | 26 +++++++++++++++------- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/vvp/delay.cc b/vvp/delay.cc index 3ed6b9f74..21731cd17 100644 --- a/vvp/delay.cc +++ b/vvp/delay.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2011 Stephen Williams + * Copyright (c) 2005-2014 Stephen Williams * * This source code is free software; you can redistribute it * 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]; const static bit4_table4 edge_table[4] = { - { DELAY_EDGE_01, DELAY_EDGE_01, DELAY_EDGE_0x, DELAY_EDGE_0z }, - { DELAY_EDGE_10, DELAY_EDGE_10, DELAY_EDGE_1x, DELAY_EDGE_1z }, - { DELAY_EDGE_x0, DELAY_EDGE_x1, DELAY_EDGE_x0, DELAY_EDGE_xz }, - { DELAY_EDGE_z0, DELAY_EDGE_z1, DELAY_EDGE_zx, DELAY_EDGE_z0 } + { DELAY_EDGE_01, DELAY_EDGE_01, DELAY_EDGE_0z, DELAY_EDGE_0x }, + { DELAY_EDGE_10, DELAY_EDGE_10, DELAY_EDGE_1z, DELAY_EDGE_1x }, + { DELAY_EDGE_z0, DELAY_EDGE_z1, DELAY_EDGE_z0, DELAY_EDGE_zx }, + { DELAY_EDGE_x0, DELAY_EDGE_x1, DELAY_EDGE_xz, DELAY_EDGE_x0 } }; return array[ edge_table[a][b] ]; @@ -818,14 +818,27 @@ static void modpath_src_put_delays (vpiHandle ref, p_vpi_delay delays) assert( fun ); 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}; const map_array_t*use_map = 0; switch (delays->no_of_delays) { + case 1: + use_map = &map_1; + break; case 2: use_map = &map_2; break; + case 3: + use_map = &map_3; + break; + case 6: + use_map = &map_6; + break; case 12: use_map = &map12; 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 - the rules for selecting X delays. This only needs to happen - if the X delays are not already explicitly given. */ + /* Now define the to-from-x delays if needed. */ 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; + /* 0->x is the minimum of 0->z and 0->1. */ + tmp[DELAY_EDGE_0x] = tmp[DELAY_EDGE_0z] < tmp[DELAY_EDGE_01] ? + tmp[DELAY_EDGE_0z] : tmp[DELAY_EDGE_01]; + /* x->1 is the maximum of z->1 and 0->1. */ + tmp[DELAY_EDGE_x1] = tmp[DELAY_EDGE_z1] > tmp[DELAY_EDGE_01] ? + tmp[DELAY_EDGE_z1] : tmp[DELAY_EDGE_01]; + /* 1->x is the minimum of 1->z and 1->0. */ + tmp[DELAY_EDGE_1x] = tmp[DELAY_EDGE_1z] < tmp[DELAY_EDGE_10] ? + tmp[DELAY_EDGE_1z] : tmp[DELAY_EDGE_10]; + /* x->0 is the maximum of z->0 and 1->0. */ + tmp[DELAY_EDGE_x0] = tmp[DELAY_EDGE_z0] > tmp[DELAY_EDGE_10] ? + 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); diff --git a/vvp/vpi_time.cc b/vvp/vpi_time.cc index 015104806..6f5b78bd3 100644 --- a/vvp/vpi_time.cc +++ b/vvp/vpi_time.cc @@ -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 * 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) { - int units; - if (scope) - units = scope->time_units; - else - units = vpi_time_precision; + int shift = 0; + if (scope) shift = scope->time_units - scope->time_precision; + assert(shift >= 0); - 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; - 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)