Subject: Re: _delay: and SCSI
To: None <dej@achilles.net, mcr@latour.sandelman.ocunix.on.ca>
From: Gordon W. Ross <gwr@mc.com>
List: port-sun3
Date: 12/05/1995 14:01:22
> From: dej@achilles.net (David Jones)
> Date: Tue, 5 Dec 1995 08:23:45 -0500 (EST)
> To achieve minimal-overhead delays, we want to sleep for
>
> delaytime * clockfreq
> ---------------------
> looptime
Yes, in general, the loop count is a rational multiple of the
delay time given in microseconds.
> iterations, where looptime is the time taken to perform one iteration of the
> delay loop. The current code computes (delaytime*clockfreq) in advance,
> and suffers due to the time required to do the multiply.
>
> Far better would be to compute (clockfreq/looptime) at boot time using
> fixed-point arithmetic, possibly 64-bit if that's warranted. The result
> is a "constant" that can be accumulated until the fixed-point sum is
> greater than delaytime, e.g.:
>
> delay(int usecs)
> {
> long long sum = INT_TO_FIXEDPT(usecs);
>
> while (sum > 0) sum -= delayval;
> }
>
> Where delayval is the calibration constant previously computed.
That's an interesting idea, and it breeds another one:
We could use as our "rational" multiplier something like:
(1 << 8) / divisor
where divisor is tuned at boot time. This would allow delay() to
just use a shift in place of its initial multiply. Each iteration
through the loop would subtract the divisor from that product, so
the loop count would be as shown by the formula above.
For now, the divisors could be constants set in sun3_startup.c
just the same way cpuspeed is set now.
> Of course, this is written in assembler for maximum speed (small granularity)
> and INT_TO_FIXEDPT() is at worst a swap instruction, or if 64-bit
> values are used, it "disappears" into the multiprecision addition. The
> inner loop could be something like:
I don't think 64-bit products are necessary. Also, note that the
current implementation of a rational multiplier is essentially
fixed-point arithmetic with a three-bit fractional part.
Gordon