PDP10: Correct time interpolation when reading the timebase and the interval calculation when setting the clock tick interval. Fixes issue #108 (from Jordi Guillaumes)

This commit is contained in:
Mark Pizzolato 2014-02-11 07:17:42 -08:00
parent 545aa85677
commit 897491deea

View file

@ -207,22 +207,22 @@ DEVICE tim_dev = {
t_bool rdtim (a10 ea, int32 prv) t_bool rdtim (a10 ea, int32 prv)
{ {
d10 tempbase[2]; double fract; /* Fraction of current interval completed */
int32 used; d10 tempbase[2]; /* Local copy of tempbase to interpolate */
d10 incr; int32 used; /* Used part of curr intv, in hw ticks */
d10 incr; /* Interpolated increment for timebase */
tempbase[0] = tim_base[0]; /* copy time base */ tempbase[0] = tim_base[0]; /* copy time base */
tempbase[1] = tim_base[1]; tempbase[1] = tim_base[1];
/* used = time remaining in this service interval (instructions) used = tmr_poll - (sim_activate_time (&tim_unit) - 1);
* poll = instructions in the whole service interval. fract = (double)used / (double)tmr_poll;
* incr = fraction of interval consumed * HW ticks per interval.
* Thus, incr is approximate number of HW ticks to add to the timebase /*
* incr is approximate number of HW ticks to add to the timebase
* value returned. This does NOT update the timebase. * value returned. This does NOT update the timebase.
*/ */
used = tmr_poll - (sim_activate_time (&tim_unit) - 1); incr = fract * (double)tim_period;
incr = (d10) (((double) used * TIM_HW_FREQ) /
((double) tmr_poll * (double) tim_period));
tim_incr_base (tempbase, incr); tim_incr_base (tempbase, incr);
/* Although the two LSB of the counter contribute carry to the /* Although the two LSB of the counter contribute carry to the
@ -279,20 +279,27 @@ return update_interval (tim_interval);
static t_bool update_interval (d10 new_interval) static t_bool update_interval (d10 new_interval)
{ {
tim_new_period = CLRS (new_interval + ((new_interval & TIM_HWRE_MASK)? 010000 : 0)); /*
if (!(tim_new_period & ~TIM_HWRE_MASK)) * The value provided is in milliseconds shifted 12 positions to the
tim_new_period = 010000; * left; if any of the 12 rightmost bits is different to zero we must
* add one millisecond to the interval. Reference:
clk_tps = (int32) (0.5 + ( ((double)TIM_HW_FREQ) / (double)tim_new_period )); * AA-H391A-TK_DECsystem-10_DECSYSTEM-20_Processor_Reference_Jun1982.pdf
* (page 4-37)
*/
int32 interval_millis = (new_interval >> 12) +
(new_interval & TIM_HWRE_MASK ? 1 : 0);
if (interval_millis == 0) interval_millis = 1;
/* tim_new_period is the new value for the interval in hw ticks */
tim_new_period = interval_millis * (TIM_HW_FREQ / 1000);
/* clk_tps is the new number of clocks ticks per second */
clk_tps = 1000 / interval_millis;
/* tmxr is polled every tim_mult clks. Compute the divisor matching the target. */ /* tmxr is polled every tim_mult clks. Compute the divisor matching the target. */
tim_mult = (clk_tps <= TIM_TMXR_FREQ) ? 1 : (clk_tps / TIM_TMXR_FREQ) ;
tim_mult = (clk_tps <= TIM_TMXR_FREQ)? 1 : ((clk_tps + (TIM_TMXR_FREQ-1)) / TIM_TMXR_FREQ);
/* Estimate instructions/tick for fixed timing - just for KLAD */
/* Estimate instructions/tick for fixed timing */
tim_unit.wait = TIM_WAIT_IPS / clk_tps; tim_unit.wait = TIM_WAIT_IPS / clk_tps;
tmxr_poll = tim_unit.wait * tim_mult; tmxr_poll = tim_unit.wait * tim_mult;
/* The next tim_svc will update the activation time. /* The next tim_svc will update the activation time.