-- Switch Prom (revision R)
-- Contains additional logic for Microcode Bank Switching
-- Used both for Rev B&up CP’s as well as for 16K CP’s
-- Last edited by TonyWest.PA on September 7, 1982 4:05 PM
-- File: [Ivy]<TonyWest>sCPE>SwitchProm.mesa

DIRECTORY
ImageDefs: FROM "ImageDefs"
USING [StopMesa],
PromBlowDefs: FROM "PromBlowDefs"
USING [WritePromData, WritePromList];

SwitchProm: PROGRAM IMPORTS ImageDefs, PromBlowDefs =
BEGIN OPEN PromBlowDefs;

Size:
CARDINAL = 256;-- number of prom locations
addrWidth:
CARDINAL = 8;-- number of prom address bits
dataWidth:
CARDINAL = 4;-- number of prom output data bits

-- Note: a "n" at the end of a name indicates it is an active low signal, i.e. assigning
FALSE means that it represents a true state.

Addr: TYPE = MACHINE DEPENDENT RECORD -- Right-justified
[pad: [0..377B],
Ct: [0..7],
Nt: [0..7],
Cycle2: BOOLEAN,
Wait: BOOLEAN];

Output:
TYPE = MACHINE DEPENDENT RECORD -- Left-justified
[Swc2: BOOLEAN,
null1: BOOLEAN,
Swc2n: BOOLEAN,
IOBank: BOOLEAN,
pad: [0..7777B]];

Prom:
ARRAY [0..Size] OF Output;
A: Addr;
Out: Output;
GenSwitchProm: PROCEDURE =
BEGIN
i: CARDINAL;
-- A potential task switch is always started in c2. There will be a task switch unless the kernel is being entered or the emulator is going to run again. Task switching implies that the address used to read out the first microinstruction of the upcoming click comes from the TPC and not the normal INIA computation. Thus, since there is no task switch on entering the kernel, the entry point of the kernel is determined by the GOTO field of the breakpoint instruction (or 0 if EKErrc2 is true).

-- Wait signifies three possible conditions:
--
(1) Loading CS: when the IOP is loading control store, wait is high so that the partially loaded instructions are not executed. Swc2 must be continuously true so that the CS addr comes from the TPC. This condition is detected by Wait true and the kernel is running (Ct=kernel or 6 {IOP dummy task for writing CS}). Thus, whenever the kernel is running and wait is activated by the IOP (via IOPWait), the kernel will be locked at the last TPC location it executed (which is in the wait loop).

--
(2) MouseHalt: If wait is true via IOPWait, this signifies a mouse halt. Swc2 must be true to read out the kernel’s TPC which is the mouse halt entry point. The kernel begins executing the MouseStop location as soon as wait is removed.

--
(3) If wait is true in c2, we must always select the next click’s starting address from the task’s TPC. If the current task is the emulator (and it is aborted for a click by Wait) and the next task is the emulator, then the emualtor should start in the next task with the (unwritten during Wait) TPC. (If the emulator was suspended, but it is not going to run again, there should be a task switch anyways).
--CtNtWaitc2SwitchIOBankComments
--Emu*FFNoNoEmulator code from any bank
--
~Emu*FFNoYesNon-Emulator code from IOBank

--
Emu*TFNoNoDisplay suspended click
--
IO*TFNoYesDisplay suspended click
--
Kern*TFYesYesKernel resume address

--
6***YesNoWrite control store location

--
EmuEmuFTNoNoNo task switch
--
EmuEmuTTYesNoEmulator restart after suspend
--
EmuKernFTNoYesKernel breakpoint entry
--
EmuKernTTYesYesKernel "mouse halt" entry
--
EmuIO*TYesYesTask switch

--
IOEmu*TYesNoTask switch
--
IOaIOaFTNoYesn.a.
--
IOaIOaTTYesYesn.a.
--
IOaIOb*TYesYesTask switch.
--
IOKernFTNoYesKernel breakpoint entry
--
IOKernTTYesYesKernel "mouse halt" entry

--
KernEmu*TYesNoTask switch
--
KernIO*TYesYesTask switch
--
KernKernFTNoYesNo task switch
--
KernKernTTYesYesKernel resume address

FOR i IN [0..Size) DO
A ← LOOPHOLE[i];
Out.null1 ← TRUE;

--
This is the code used in the standard DLion Proms, Rev B.
--
Out.Swc2 ←A.Cycle2 AND ~A.Nt=7 AND ~(A.Ct=0 AND A.Nt=0);
--
IF A.Wait AND A.Cycle2 THEN Out.Swc2 ←TRUE;
--
IF A.Wait AND ~A.Cycle2 AND (A.Ct=6 OR A.Ct=7) THEN Out.Swc2 ←TRUE;

--
Changes for Revision R
Out.Swc2 ← (A.Cycle2 AND (A.Wait OR (A.Ct#A.Nt AND A.Nt# 7))) OR
(~A.Cycle2 AND A.Wait AND A.Ct=7) OR
A.Ct=6;

Out.IOBank ←A.Ct#6 AND ((A.Cycle2 AND A.Nt#0) OR (~A.Cycle2 AND A.Ct#0));
--
End of changes

Out.Swc2n ← ~Out.Swc2;
Prom[i] ← Out;
ENDLOOP;
END;


GenSwitchProm[];
WritePromData["SwitchProm-RevR", addrWidth, dataWidth, @Prom[0]];
WritePromList["SwitchProm-RevR", addrWidth, dataWidth, @Prom[0]];
ImageDefs.StopMesa[]

END.