So my micro has around 8 interrupt sources. I had a few goals in mind:
So what I have is a register map like this:
SETINTMASK - write only: each bit that is a 1 is set in the "IRQ filter"
CLEARINTMASK - write only: each bit that is a 1 is cleared in the "IRQ filter"
INTSTATUS - read only: a priority encoded number for the interrupt bit that is currently active
At the same time as generating INTSTATUS the implementation also generates the CPUs IRQ line (by comparing the masked status against 0).
The reason for the SET and CLEAR action was to make the interrupt setup as simple as possible - no need to read in the current mask, OR the new mask and write it out again.
The priority encoding saves a whole bunch of code in the top-level ISR. It just has to read INTSTATUS, rotate it left once and extract the particular device's handler from a table. The value 0 means something has gone wrong (it should never happen because the IRQ line should be high in this case.) The priorities are hardcoded in the HDL, something I'm not especially pleased with (it could be nice to make them configurable from CPU code) but I can live with it. I'm not sure if this is how "real" interrupt routers deal with prioritising device interrupt lines?
I guess for efficiency I could rotate the INTSTATUS in the HDL, but that seems a bit dirty somehow.
One thing I've pondered is for the HDL itself to hold the table of the device ISRs. In theory that would reduce the CPU ISR code to reading the "INTSTATUS" 16 bit value and jumping through it, probably the next best thing to having the interrupt router present the device's vector directly. But this would consume a fair amount of resources in my limited FPGA.
What approaches have others taken for dealing with computers with "many" interrupt sources?