Subject: Re: pmax interrupt problem solved
To: Michael L. Hitch <mhitch@lightning.msu.montana.edu>
From: Todd Whitesel <toddpw@best.com>
List: port-pmax
Date: 03/10/2000 00:12:42
>   In the case of the 5000/200, we are only checking 6 bits for possible
> interrupts, and in the case of multiple "if (bitset) process_interrupt()"
> statements, egcs only needs 2 instructions per test for the case where the
> interrupt bit is not set.  It would seem to me that it's probably
> preferable to use straight-forward, simple code to check and dispatch
> the interrupts, rather than adding complexity and obscurity to the code
> (unless the effort can produce a *signifcant* performance improvment).

The method I described is primarily useful when you have "many" bits to
check, and the priorities are relatively static. So for the 5000/200 I
agree it probably would not make a heckuva lot of sense.

>   I was thinking that the interrupt dispatch could be written something
> like this:
> 
> 	while (1) {
> 		csr = <read CSR>;
> 		if (csr & INTBIT_1) {
> 			CALLINTR(INTR_1); continuye;
> 		}
> 		if (csr & INTBIT_2) {
> 			CALLINTR(INTR_2); continue;
> 		}
> 		...
> 		break;
> 	}

Sure, that works. However, in the single-interrupt case, the second pass
through the if-chain chews time unnecessarily. (solution given below)

When the priorities are really dynamic, then the method I gave becomes a
total lose and you're better off doing something totally data driven:

/* Interrupt pending bit numbers, in descending priority order. */
signed char pend_bit_to_check[] = { <bit numbers>, -1 };

csr = <read CSR>;
do	{
	signed char pend_bit, *ppend_bit;

	ppend_bit = pend_bit_to_check;
	while ((pend_bit = *ppend_bit) >= 0) {
		if (csr & (1 << pend_bit)) {
			CALLINTR(pend_bit);
			break;
		}
		++ppend_bit;
	}
	csr = <read CSR>;
} while (csr & ALL_POSSIBLE_PEND_BITS); /* only loop if more work to do */

Assuming I typed this in exactly right, it re-scans the array each time,
checking the bits in priority order, dispatching to the handler for each
bit number and then starting over.

Note that in the re-scan case, I added a quickie check for "any bits set"
before looping back. I think this makes sense in general; the Ultrix code
gets it for free because of the way the hardware works.

BTW this method can be combined with your version that I quoted above,
so that fixed interrupt sources above/below the dynamic ones get handled
by explicit code (which is slightly faster). Fixed sources in the middle
of the dynamic ones probably should just be treated like dynamic ones.

One real problem with this data-driven method is that it puts a load-delay
right smack in the middle of the critical loop. I can think of ways to
mitigate this, but they all involve complicated code, so I'll skip typing
them in here :)

>   One further optimization that might be made here is to use a local
> pointer to intrcnt and intrtab.  That looks like it should make the code

I've used local pointers in embedded code before. Usually a good idea.
Sometimes the compiler can do it automatically ("CSE"), but I prefer
leaving nothing to chance in critical code like interrupt routines.

Todd Whitesel
toddpw @ best.com