;-*- Mode:Text -*- 6/23: want RD to be clocked at end of D, so the valid RD can be clocked again on C by the reg-adr select. No way to get RD before clock at C, so reg-adr select mux change. Delay IR_DEST and DRET_SEL; mux with RD after that. Is there time for the two mux delays? 6/6/86: added register between Hram addr mux and Hram ;;;;;;;;;;;;;;;; Sources are CH state before current instruction's call-hardware operation; destinations are after. Frames available as source and destination bases: Open: Frame to store arguments for function that is about to be called. Active: Frame for current function local variables and the arguments the function was called with. Return: Frame in which to store values to be returned by the active function. Global: Frame number comes from IR 4-bit immediate combined with frame offset. Functional Source / Dest ... ;;;;;;;;;;;;;;;; Definition of instruction cycles: Cycle 1: PC / IR IR: (70ns) PC is asserted at PC mux output for last 50ns of this cycle. Mux inputs must be valid for this time; PC is not latched. IR is clocked with valid instruction at end of this cycle. Cycle 2: Decode / R Decode: (35ns) ALU opcode is computed from IR. First call-hardware cycle. First call-hardware clock is at end. Assert values of O, A, R for use as sources for this R and as destination for previous W. R: (35ns) Register read for ALU sources. Second call-hardware cycle. Call-hardware op is complete and is clocked at end. Cycle 3: ALU ALU: (70ns) ALU instruction and data inputs are asserted; output is valid in time for clock at end. clocked at input and output (start of ALU0, end of ALU1). Cycle 4: W W: (35ns) Register write with ALU dest (or ret-dest). Register ram is addressed by dest from IR for all but RETURN, and by ret-dest from Hram for RETURN. ;;;;;;;;;;;;;;;; Call-hardware operations specified for R and ALU0: Must clock new O, A, and R at end of R. For RETURN, RPC must be valid at clock at start of D, and RD must be valid before clock at end of R. INPUT DEFINITIONS: C, CD, C2: primary machine clocks IR_CHOP (3): CHOP field from IR D_CHOP (3): IR_CHOP clocked on C~ (to delay 1/2 cycle) D2_CHOP (3): IR_CHOP clocked twice on C (delay 2 full cycles) CH_DIRECT (1): "direct access" call-hardware control-reg mode bit TRAP_1 (1): asserted during first cycle of trap entry TRAP_2 (1): asserted during first two cycles of trap entry CHCLK: 16L8-B (clocks and Hram addr select) inputs: IR_CHOP(3), D_CHOP(3), C(1), CD(1), CH_DIRECT(1), TRAP_1(1) left: 0 inputs, 0 outputs OF_CEN~ ;gated with C2 AF_CEN~ ; "" RF_CEN~ ; "" RDRPC_CEN~ ; "" (RD, RPC) TOA_FRA_CEN~ ; "" (TO, TA, FRA) HADR_SEL (3) ;Hram adr mux select backup stuff: TRAP . CD: assert clock enables to clock OF, AF, RF with OO, OA, OR ;;CHSEL: 16R8-B (mux selects and Hram write enables) ;; inputs: IR_CHOP(3), CD(1), CH_DIRECT(1), TRAP_1(1) ;; left: 2 inputs, 2 outputs ;; clock: C2 ;; enable: always CHSEL: 16L8-B (mux selects and Hram write enables) inputs: IR_CHOP(3), D_CHOP(3), C(1), CD(1), CH_DIRECT(1), TRAP_1(1) left: 0 inputs, 0 outputs O_A_SEL ;OF, AF RD_PC_T_SEL ;RD, RPC, TO, TA TR_SEL ;TR R_SEL ;RF; normally AF; OR during backup, MFO during trap OOAR_OE~ ;OO, OA, OR output enables HRAM_CS~ ;Hram chip select ;; ..WEN's are clocked on C2 before use. HO_HA_WEN ;HO, HA write-enable; gate with C2~ (pos. true if easy) HRDPC_WEN ;HRD, HPC write-enable; "" CHFREE: 16L8-B (freelist) inputs: IR_CHOP(3), D2_CHOP(3), C(1), CH_DIRECT(1), TRAP_2(1) left: 1 input, 2 outputs RDP_CEN~ ;read-ptr clock enable WRP_CEN~ ;write-ptr clock enable FR_PE~ ;parallel-entry for in/out/nl NL_CEP~ ;number-left clock enable NL_UP ;number-left up (down~) FR_WR ;freelist ram write (pos. true if easy) constant: TR ;clock on C~ NEW ;clock on C OO, OA, OR ;clock on C Haddr reg ;clock on C2 to-do: HMFI_DIR ;Hram to MFI direction OAR_IEN~ ;O/A/R / MFI buffer enable RDRPC_IEN~ ;RD/RPC / MFI buffer enable backup: TRAP_1 is asserted for first C cycle. TRAP_1 immediately forces OOAR_OE on and HRAM_CS off; selects OO/OA/OR for OF/AF/RF; asserts OF_CEN, AF_CEN and RF_CEN during first clock. OOAR_OE can turn off during second half of C; turn HRAM_CS back on after TRAP_1. PALs supply OOAR_OE~ and HRAM_CS~ (go through "none" when switching) func source/dest decode supplies HMFI_DIR, OAR_IEN~ and RDRPC_IEN~ trap: backup direct-mode chops: (nop): read H(active) HO/HA through MFI (nop): read H(active) HRD/HPC through MFI (read OOAR): read OO/OA/OR through MFI write to func-dest d-oar; select and clock OF/AF/RF at end of R write to func-dest d-rdrpc; select and clock RD/RPC at end of R (??): read RDP through MFI ... RDP / WRP use same func-source with diff. chops. (??): read WRP through MFI (??): read NL through MFI (only needs func-source decoding) (??): write RDP/WRP/NL from MFO (??): write Hram address from MFO; maybe HADDR-DIRECT reg can be removed. ;;or, most direct Hram address is from OF or AF. RDP/WRP/NL chop's can overlap other direct-mode chop's ;;;;;;;;;;;;;;;; Sequence is: (assume all legal possible preceding instructions left valid defaults set up during D) clocked at end of D: asserted during R: clocked at end of R: asserted during ALU0: defaults, asserted during ALU0 for use by next instruction: H(active) O <- H(active) A <- H(active) TO <- O TA <- A RPC <- PC+1 RD <- IR:ret-dest R <- A TR < R free-ptr-mode <- count-down ;;;;;;;;;;;;;;;; 6/7: move selects back to D and R; (changes CH_SEL from 16R8 to 16L8) clocks are still D and R; writes are R and ALU0 6/6: register on Hram address; means selected address is from before clock (C2) at start of write. ... Means Hram address select must be known before clock. No-op: Do nothing; read next RPC and RD from H(active). asserted during D: Haddr <- A clocked at end of D: asserted during R: RPC, RD <- H(active) ;RPC, RD valid if RETURN follows Haddr <- A ;to assert H(active) during ALU0 clocked at end of R: RPC, RD Open: Create a new open frame in preparation for a function call. 1. allocate a new frame and save open and active in it. 2. make the new frame be the open frame. asserted during D: Haddr <- NEW TO <- O TA <- A O <- NEW clocked at end of D: O, TO, TA freelist out-ptr asserted during R: H(free) <- TO, TA clocked at end of R: Call: Call a function. Make the current open frame become the active frame. Set up RPC and RD since RETURN may follow. 1. copy open frame pointer to active frame. 2. save the return-PC and return-destination in H(active). asserted during D: Haddr <- O RPC <- PC+1 RD <- IR:ret-dest clocked at end of D: RPC, RD asserted during R: H(open) <- RPC, RD ;RPC, RD valid if RETURN follows A <- O ;Haddr Haddr <- O ;to assert H(active) during ALU0 clocked at end of R: A Open-call: Create a new open frame, make it the active frame and call a function. Set up RPC and RD since RETURN may follow. 1. allocate a new frame and save open, active, ret-PC and ret-dest in it. 2. set open and active to the new frame. asserted during D: Haddr <- NEW RPC <- PC+1 ;PC+1 is only valid until end of D RD <- IR:ret-dest TO <- O TA <- A O <- NEW clocked at end of D: O, TO, TA, RPC, RD ;RPC, RD valid if RETURN follows freelist out-ptr asserted during R: H(free) <- TO, TA, RPC, RD A <- Haddr ;free from D Haddr <- O ;to assert H(active) during ALU0 clocked at end of R: A Tail-recursive-open: Copy the current active frame into a new open frame, in preparation for a tail-recursive call, which will throw away the active frame as if returning; then start a new call by copying open to active. 1. copy H(active) into a new frame H(free) 2. make the new frame be the open frame. asserted during D: Haddr <- A O <- NEW clocked at end of D: O freelist out-ptr asserted during R: TO, TA, RPC, RD <- H(active) Haddr <- O ;free clocked at end of R: TO, TA, RPC, RD asserted during ALU0: H(open) <- TO, TA, RPC, RD ;OK; not followed by anything that uses H(active) Tail-recursive-call: Call a function. Discard the active frame as if returning, and make the current open frame become the active frame. Set up RPC and RD since RETURN may follow. 1. push return onto frame freelist 2. copy active to return 3. copy open to active. asserted during D: Haddr <- O TR <- R clocked at end of D: TR freelist in-ptr asserted during R: RPC, RD <- H(open) ;so RPC, RD valid if RETURN follows A <- O ;Haddr R <- A Haddr <- O ;to assert H(active) during ALU0 clocked at end of R: R, A, RPC, RD asserted during ALU0: freelist(in-ptr) <- TR Return: Restore the frame environment to that prior to the preceding CALL. Dest is H(active) ret-dest dest and offset. Set up RPC and RD since RETURN may follow - allows RETURN - RETURN. Requires that RPC and RD already contains H(active) RPC and RD at the start of this instruction Decode cycle, so RPC can immediately be selected as the next PC source. *** NOTE: If Haddr <- HA path is too slow, the RPC/RD clocked during RETURN is invalid. This is the slowest path from the Hram outputs. The only effect is that RETURN - RETURN can't be used; any other instruction following RETURN will compute the correct RPC / RD for a following RETURN. 1. push return onto frame freelist. 2. copy active to return. 3. pop open, active, PC and ret-dest from H(active) assumed asserted during D: H(active) ;this return frame RPC, RD already valid asserted during D: Haddr <- HA ;H(active), next return frame O <- H(active) A <- H(active) TR <- R R <- A clocked at end of D: O, A, R, TR freelist in-ptr asserted during R: Haddr <- A ;to assert next H(active) during ALU0 (address free-list by in-ptr) clocked at end of R: RPC, RD <- H(active) ;RPC, RD valid for RETURN following this RETURN freelist(in-ptr) <- TR Cancel-open-frame: Undo an open or a t-open. Cannot be followed by RETURN. 1. push open onto the freelist. 2. restore active and open from H(open). asserted during D: Haddr <- O TR <- O clocked at end of D: TR freelist in-ptr asserted during R: O, A <- H(open) clocked at end of R: O, A freelist(in-ptr) <- TR ;;;; back-up and direct access operations: back-up frame regs: one cycle; clock OO/OA/OR into O/A/R back-up freelist: two cycles; run counters backwards ;;;;;;;;;;;;;;;; call hardware backup: During TRAP_1, restore O/A/R from OO/OA/OR, and back-up the freelist. OO/OA/OR don't need to be clocked; just disable the Hram, turn on the OO/ out-enables, select O/A/R, and clock O/A/R. Note: can MMI 'LS548 internal clock enables be used? The two chop's between the instruction that was aborted and the C* inhibit after TRAP are the two that are backed-up. The one after that - that is started on the C* after TRAP - is the back-up chop. That must be forced with the TRAP_1 input to the CH PALS. After that, the chop's are from the valid IR's of the trap entry code. At worst, two states may be needed for backup. The first must be forced with TRAP_1, but the second can depend on the chop from the first trap entry IR. Call-hardware needs internal control of Hram OE and OO/OA/OR OE; how to share control with MFO access and func-dest / func-source decoding? ;;;; Freelist FIFO: Easiest way to save pointer values is with MMI '548 double-reg. Easiest way to do hardware is with 8-bit common-I/O counters, two MMI '548s, and freelist ram all on common bus, with MFO access. Common-I/O ram too? State-save with common counter outputs is easier if counters are only clocked on C or C*. If only clocked on C ("end of R"), only one reg is needed per counter; maybe one '548 can be used for both? ;;;; backing up last two normal free-list operations: in-ptr: count-up or hold out-ptr: count-up or hold nfree: function of in-ptr and out-ptr