-*- Mode:Text -*- Exceptions ... ================ Terminology: When discussing software, "exception" means any of "trap", "synchronous interrupt" or "asynchronous interrupt", which are distinct from each other. In context of signal names, "TRAP" is the same as "exception"; it is the shortest name to use. General info: The general name for a trap or interrupt is an "exception". All exceptions, when enabled, cause the machine to abort the current instruction and jump to zero. The instruction that is aborted is the instruction that is about to write its destination value. This is the "commit point" of an instruction, beyond which its side-effects cannot be reversed. The preceding instructions have completed and cannot be determined or reversed; the following instructions that are in the pipeline are aborted and their early side-effects are also reversed. That an exception will be caused may be known earlier, but to say that a particular instruction is aborted means that the exception signal is asserted during the compute cycle of that instruction. The complete ALU state and last two PC's are frozen when the exception occurs; the state is saved in the exception entry code and is sufficient to completely restore the machine state after the exception processing has completed. Types of exceptions: For purposes of the machine timing, exceptions are divided into two classes: interrupts, which re-execute the aborted instruction exactly, and traps, which re-execute the aborted instruction but store a destination value that may be modified by the trap code. For traps, it is not obvious that it is neccessary to re-execute the aborted instruction if its computed result is to be replaced by a value computed in the trap code. The aborted instruction must be executed to cause the correct sequencing of the call-hardware and the instruction stream. Entry / Exit sequences: The exception entry sequence is the same for all types of exceptions, but the exit sequence is different for traps vs. interrupts. The sequence of instructions for exception entry, trap exit and interrupt exit is fixed in the hardware timing, so that individual register clocks may be controlled as required for the machine state to be saved and restored. For purposes of software, interrupts may be subdivided into two classes: synchronous interrupts, which are caused by direct side effects of specific instructions and occur at precisely determined times relative to the instructions that cause them, and asynchronous interrupts, which are caused by events unrelated to the instruction stream and may be arbitrarily deferred as required by the instructions being executed. Note that the destination value computed and stored during the trap exit sequence is temporary. After a trap is processed, if the re-executed instruction is aborted again for a different reason than the original trap, the trap-computed destination value is lost. After the second exception is processed and the aborted instruction is executed for the third time, the ALU sources are the original sources for which the first trap was caused. If the cause of the original trap has not been cancelled by the second exception, the original trap is caused again. Priority; simultaneous exceptions: The priority of exceptions is fixed in the hardware, as required by the logical functionality of the machine. When any exception occurs, further exceptions are disabled until the first exception is processed or the exception handler explicitly reenables exceptions while in the exception handler. When two exceptions occur simultaneously, the one of higher priority is taken. When the first exception has been processed, the aborted instruction is re-executed. If the lower-priority exception is still asserted, the instruction is aborted again that that exception is processed. If the cause of the lower-priority exception is no longer present, it is ignored and no exception is caused. For example, if an exception is caused because MD was sourced after a memory read to a swapped-out page, a page-fault interrupt is caused. Because the data read from MD is garbage, a spurious data-type trap may also be caused at the same time. After the page-fault exception is processed and the instruction is re-executed, the data-type trap is asserted if it was real, but is not asserted and is never processed if it was spurious. Some exceptions remain asserted until processed or until the cause is explicitly reset, and some are only asserted during the one cycle for which the actual cause is present. If, on exception entry, 1) one of the once-only bits is set, 2) it is not the highest-priority exception that is asserted, and 3) it is an exception type that is not spurious and therefore must be processed before the request is lost, the exception handler must remember that the bit was set on initial entry, and then process the exception after the first one is done but while still in the exception handler. ================ Priority and class of exceptions: Priority 0 is highest. Exception class (trap or interrupt) is only for software. The 4 enables (TRAP_EN_1 .. TRAP_EN_4) are control-register bits. pri class enable name description === ===== ====== ==== =========== 0 trap en_1 trace software trace-trap; trap after one instruction 1 intr en_1 par-ic Main-mem parity error during Icache fill 2 intr en_1 par-ic-nubus Nubus parity error during Icache fill 3 intr en_1 par-proc Main-mem parity error during access from VMA 4 intr en_1 par-proc-nubus Nubus parity error during access from VMA 5 intr en_1 nubus-timeout Nubus timeout during Icache or VMA access (?) 6 intr en_1 ic-pgf Page-fault during Icache fill 7 intr en_1 pgf-read Page-fault on read from VMA 8 intr en_1 trans-read Transport-trap on read from VMA 9 intr en_1 gc-write GC-trap on write from VMA 10 intr en_1 pgf-write Page-fault on write from VMA 11 intr en_1 ch-full Call-hardware Hram full 12 trap en_2 data-type Data-type trap 13 trap en_3 overflow ALU Overflow trap 14-19 as-intr en_4 nubus-intr Nubus interrupts (0..7) 20 as-intr en_4 rtc Local real-time-clock (~60Hz) ================ Exception timing: (The real signal names are different; this is just for descriptive purposes) TRAP is the OR of all exception sources, gated with TRAP_EN. If asserted at least (~15ns) before C, (1) the instruction currently in its Compute cycle is aborted, (2) the PC is forced to 0, the address of the exception entry code, (3) the next four register and func-dest write cycles starting with the one that would normally begin on C are inhibited, (4) the call-hardware operation starting at the next call-hardware operation boundary is inhibited, (5) the ALU state is frozen so that it can be saved by the exception code, and (6) the call-hardware state is "backed-up" to before the instruction that is being aborted. The important timing starts on a rising-edge-of-C during which one of the trap requests is asserted. This causes the machine to start the "trap entry" sequence, which disables most of the ALU register clocks, each for a different number of cycles. During this time, the processor is executing code that is expected to match up with the clock sequencing so as to save the processor state in a set of "global" register words. Two similar sequences are also required: one for "trap exit" and the other for "interrupt exit", as described earlier. The exact sequence of clocks is not yet known, but the list of clocks that must be controlled and the requirements of and methods for controlling them are known and are described below. (SOON) Plausible signals for implementing this: TRAP_EN_1 .. TRAP_EN_4: Control-register bits that enable groups of exceptions. If exceptions are asserted while disabled, then when the enable is asserted, the exception is only caused if the source is still asserted. TRAP-in-progress: Set when an exception is entered; reset after last cycle of exception exit sequence. Inhibits traps while in trap code. May also be reset from software, to allow recursive exceptions when desired. TRAP_1: Clocked on C; asserted for exactly one C cycle. Used to start call-hardware back-up sequence. TRAP_2: Same as TRAP_1 except asserted for two cycles. Implement if required. TRAP_3: Same as TRAP_1 except asserted for three cycles. TRAP_EXIT: INTR_EXIT: Set (by writing to func-dest) by software to start the trap-exit or interrupt-exit timing sequence. TRAP_REG: Register with one bit per exception source; is clocked every C up until the first C after a C during which any of the bits were set (after mask with trap enables). Clock to this register is re-enabled as part of the exception-entry sequence after the processor has read the register. The bits are not explicitly cleared as the corresponding exceptions are processed, rather, as they are processed, the bits are implicitly reset at their sources. ================ Specification of individual exceptions: Data-type DT_TRAP (trap): The data-type trap aborts an instruction that causes a type-checking error. The type-checking logic is a function of the ALU inputs and the type-checking field of the instruction corresponding to the ALU inputs. The trap is only asserted during the compute cycle of the instruction that causes the error. If a higher-priority exception is asserted at the same time, then after the exception is processed, the data-type trap is only taken if the type-checking logic asserts the trap again. The exception handler computes the correct result for the aborted instruction. The trap exit sequence forces this value to be stored as the destination value when the instruction is re-executed. Overflow OV_TRAP (trap): The overflow trap aborts an instruction for which the ALU overflow flag is asserted during the compute cycle. The timing is otherwise the same as for the data-type trap. ;Pace's trace-trap info page The trace trap is a feature that can be used to single step a program. It is activated by setting a mode register bit during the trap return sequence. After the trap return, at most one instruction is executed before causing another trap. In other words, the instruction being returned to by the trap is executed normally. If this instruction causes a trap (data type or overflow), or if there is an asynchronous interrupt pending, then that trap will happen, as usual, before the commit point of this instruction. (Notice that the memory system is idle during the return from a trap, so no page-fault or transporter traps can go off.) If no traps go off, then a trap is unconditionally signaled at the commit point of the following instruction. ........ (traps) alu overflow unsynchronized output from ALU random up to ALU valid output time (60ns after C) gated with control-reg disable-overflow-trap valid as long as **all** ALU inputs are held data type output from type-checking ram valid 10ns + ram-access + 1-gate after C (45-60ns) valid as long as ALU input-regs and IR are held (may be difficult to latch...) (interrupts) page-fault may want to delay this one clock so it can't abort the instruction that caused it. (-early...) nubus error Set when sourcing MD after MAP indicates page-fault (can incorporate nubus-error?) (note that until map is valid, or if memory system is busy, sourcing MD freezes machine.) Also set when VMA/MD write had page-fault (may not be set for several cycles, if memory system is busy?) GC transport set when referencing MD after read set after write nubus interrupts local interrupts sets bit (synchronously) per interrupt that remains set until reset by software. Include disable bits for: 1. local interrupts at their sources 2. one bit for all nubus interrupts 3. one bit per nubus interrupt 4. no disable for nubus interrupts call hardware full / error sets bit (synchronously) that remain set until reset by software. reset set by nubus-reset, which also enables traps. ================ Exception entry / exit timing: (Just before C at end of Compute cycle, assert TRAP.) ALU input and output regs and OPC clocks are inhibited as part of entry sequence; are re-enabled after the software should have saved them. First C cycle after TRAP backs up call-hardware; rest of call-hardware chop's come from actual trap code. "G0" means "global register 0". Exception-entry (same for all sources): G0 <- (garbage) ;save output reg, re-enable out-reg clock G1 <- L ;save left input-reg G2 <- R ;save right input-reg, re-enable input-reg clocks G3 <- internal stat-reg ;then disable ALU HOLD input G4 <- saved-jump-status ;then re-enable jump-status clock (opt.) G5 <- opc2 ;opc of aborted I (opt.) G6 <- opc1 ;opc of next, then re-enable opc clock Interrupt-exit: d-indir-jump-stat <- G4 ;set up indirect jump stat int-stat-reg <- G3 ;;assert ALU HOLD to inhibit status reg clock ;;select internal status reg as status bit outputs (garbage) <- G5 ;set up alu output for dispatch to re-exec aborted I (garbage) <- G6 ;set up next alu output in case aborted I was dispatch dispatch-x1, (garbage) <- G0, JCOND <- indir ;G0 is if next I was dispatch (re-exec aborted instruction) ;;re-enable OPC clock (exec next instruction) ;;deassert ALU HOLD since re-executed instruction now assertes valid status ;;select direct status bit outputs ;;re-enable traps (exec next instruction) ;new trap can occur or same trap can re-occur here Trap-exit is harder than for interrupt: must restore alu out-reg pipeline for dispatch's, but need final ALU value to be from the trap routine instead of recomputed from sources of re-executed instruction. Trap-exit: d-indir-jump-stat <- G4 ;set up indirect jump stat R <- desired-dest ;;inhibit R clock after loaded with desired-dest (garbage) <- G5 ;set up alu output for dispatch to re-exec aborted I; use L (garbage) <- G6 ;set up next alu output in case aborted I was dispatch; use L dispatch-x1, (garbage) <- G0, JCOND <- indir ;G0 is if next I was dispatch ;;inhibit data-type trap for the next instruction ;;force ALU inst of re-exec'd I to be "Y <- R" (re-exec aborted instruction) ;;re-enable OPC clock (exec next instruction) ;;re-enable R clock ;;re-enable traps (exec next instruction) ;new trap can occur or same trap can re-occur here ALU status doesn't matter when returning from trap, but jump status for aborted I does matter. Restore jump-status used by aborted instruction; select it with indir for last I in trap-exit. Don't need to frob internal status reg; jump condition for restarted I is recomputed from new data. OPC's may be used directly (from MFIO); must be explicitly saved and restord if recursive trap is enabled. ================================================================ ;-*- Mode:Text -*- Traps caused by reading / writing MD / VMA: Two bits of state are kept for traps caused by memory cycles. During normal operation, the bits are set from the map, transport and GC ram outputs after memory cycles have been started. The bits should be readable in a status register, and must be directly writable so that a trap routine can save and restore the complete state of the MD and VMA registers, MD and VMA boxed-bits, and RD_TRAP and WR_TRAP bits. For example, if a trap is caused for a reason unrelated to the memory system, and the memory system state is such that a vma-start-read was done and the cycle is complete, but MD has not been referenced yet, the trap routine must be able to save state, do arbitrary work with MD and VMA, and then restore the MD and VMA state such that when the aborted code reads MD, the original trap will be caused. RD_TRAP: Bit that indicates if sourcing MD will cause a trap. Bit is set and cleared as a side-effect of starting memory cycles, and is also directly readable and writable from software. RD_TREQ: Bit indicates that a trap is currently asserted because MD was sourced while RD_TRAP was set. Bit is an input to trap logic, and is readable as a (read-only) status bit. WR_TRAP: Bit indicates that a memory write has caused a page-fault or GC trap. RD_TRAP: Bit is set when starting a memory read, by VMA-START-READ or VMA-START-READ-EARLY, if the cycle causes the map / GC logic to assert the page-fault or trans-trap outputs. Bit is cleared when starting any memory read or write. Trap request is asserted during the cycle after a cycle in which MD is sourced and the RD_TRAP bit is set, such that the instruction that sourced MD is aborted. The RD_TRAP bit is also directly readable and writable (0 or 1) from software. This may be a bit in a more general control register. The Sourcing MD does not reset RD_TRAP; the trap is caused every time MD is sourced until RD_TRAP is cleared. If MD is never sourced during a period that RD_TRAP is set, the trap is never caused. This is so that a higher-priority trap caused at the same time as an RD_TRAP trap will complete and then be followed by the RD_TRAP trap. If MD is sourced when MD and the RD_TRAP bit are not valid, the machine is frozen in the MD source cycle until they are valid. WR_TRAP: Set after starting a memory write, after md-start-write or vma-start-write, if the cycle wants to cause a page-fault or GC trap. The trap is caused as soon as this bit is set. ;;;;;;;;;;;;;;;;