-- IB Prom (revision G)
-- for Rev B&up CP’s
-- last edited by R. Garner on April 24, 1980 5:34 PM
-- last edited by R. Garner on October 22, 1980 10:08 AM
--
RevFtoG: two F93453’s used instead of HM7649 for PC version only.
-- File: IBProm-PC.mesa in [Iris]<Workstation>LH>CPPromsMesa-J.dm
--
and in [Iris]<Workstation>LH>CPProms-J.press

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

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

Size:
CARDINAL = 1024;-- number of prom locations
addrWidth:
CARDINAL = 10;-- number of prom address bits
dataWidth:
CARDINAL = 8;-- 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.

Full: CARDINAL = 2;
Word:
CARDINAL = 3;
Byte:
CARDINAL = 1;
Empty:
CARDINAL = 0;

Addr:
TYPE = MACHINE DEPENDENT RECORD -- Right-justified
[pad: [0..77B],
unused: BOOLEAN,
readIBn: BOOLEAN,
loadIBn: BOOLEAN,
IBPtrTo0n: BOOLEAN,
IBPtrTo1n: BOOLEAN,
AllowMDR: BOOLEAN,
MesaInt: BOOLEAN,
IBDispn: BOOLEAN,
IBPtr: [0..3]];

Output:
TYPE = MACHINE DEPENDENT RECORD -- Left-justified
[loadIBFront: BOOLEAN,
GoodIBDispc2: BOOLEAN,
RefillIntc2: BOOLEAN,
SelIB0n: BOOLEAN,
IBPtr: [0..3],-- IBPtr.0,,IBPtr.1
null: BOOLEAN,
SelIB1n: BOOLEAN,
pad: [0..377B]];

Prom:
ARRAY [0..Size] OF Output;
A: Addr;
Out: Output;
GenIBProm: PROCEDURE =
BEGIN
i: CARDINAL;
FOR i IN [0..Size) DO
A ← LOOPHOLE[i];
Out.null ← TRUE;
Out.GoodIBDispc2 ← Out.RefillIntc2 ← FALSE;-- Initialize
Out.loadIBFront ← FALSE;-- Initialize to no load
Out.SelIB1n ← Out.SelIB0n ← TRUE;-- init to select neither IB[0] nor IB[1]
Out.IBPtr ← A.IBPtr;-- Assume old value of IB Pointer

--
IBDisp, AlwaysIBDisp
-- When RefillIntc2 is true, a microcode trap will be caused to one of four locations, which will be executed in c1. (The trap locations are saved in the TPC in c3 if the emulator does not run in the following click). Control goes to location 600x or 700x if there is a Mesa interrupt, and to location 400x for a buffer empty refill and 500x for a buffer not-empty refill.

-- If fY=IBDisp & no PgCross in last cycle, then execute either an IBDisp or an AlwaysIBDisp:

IF (~A.IBDispn AND A.AllowMDR AND A.loadIBn AND A.readIBn AND A.IBPtrTo0n) THEN
-- If we’re not doing an AlwaysIBDisp (i.e., fZ#IBPtr←1) AND there’s a pending mesa interrupt or the buffer needs refilling (IBPtr#0), then force a microcode trap. Equivalently, if we are doing an AlwaysIBDisp OR there is no interrupt pending and the buffer doesn’t need refilling, then do a real IB dispatch:
IF A.IBPtrTo1n AND (A.MesaInt OR A.IBPtr # Full) THEN Out.RefillIntc2 ← TRUE
ELSE
BEGIN-- Do an IBDisp, load IB Front, and advance the pointer.
Out.GoodIBDispc2 ← TRUE;
AdvanceIB[];
END;

--
←ib
-- "←ib" puts IBFront onto the X bus and advances the IBPtr. "←ibNA", however, doesn’t incr IBPtr. Since ther are always at least 2 bytes in the buffer when we begin executing a Mesa instr, "←ib" never traps. Note that "←ib, IBDisp" is not legal (It’s affect is a Noop).
IF (~A.readIBn AND A.IBDispn AND A.loadIBn AND A.IBPtrTo0n AND A.IBPtrTo1n)
THEN AdvanceIB[];

--
IB←
-- If we’re refilling not due to a jump instruction, IBPtr will always be either Byte or Empty. If its Empty, then we need to load IBFront with IB[0]. If its Byte (only IBFront full), then we shouldn’t load IBFront with an incoming memory byte. If we’re refilling due to a jump, then the value of IBPtr is unknown. (It will specified by an "IBPtr←" in the next cycle OR current cycle). "IB←, ←ib" is not legal (It’s affect is a Noop).

IF (~A.loadIBn AND A.IBDispn AND A.readIBn) THEN
IF A.IBPtr=Empty THEN
BEGIN
Out.loadIBFront ← TRUE;
IF ~A.IBPtrTo1n THEN
BEGIN-- Load IBFront from IB[1]
Out.SelIB1n ← FALSE;
Out.IBPtr ← Byte;
END
ELSE-- Normal case (default)
BEGIN-- Load IBFront from IB[0]
Out.SelIB0n ← FALSE;
Out.IBPtr ← Word;
END
END
ELSE Out.IBPtr ← Full;-- Don’t load IBFront, but set IBPtr to full

--
IBPtr←0, IBPtr←1
-- "IBPtr←0" or "IBPtr←1" always come in c1 immediately after an "IB←". They load IBFront with the even or odd destination byte and correspondingly establish the IBPtr.

IF (~A.IBPtrTo0n AND A.IBDispn AND A.readIBn AND A.loadIBn AND A.IBPtrTo1n) THEN
BEGIN
Out.loadIBFront ← TRUE;-- Load IB Front with IB[0]
Out.SelIB0n ← FALSE;
Out.IBPtr ← Word;
END;
IF (~A.IBPtrTo1n AND A.IBDispn AND A.readIBn AND A.loadIBn AND A.IBPtrTo0n) THEN
BEGIN
Out.loadIBFront ← TRUE;-- Load IB Front with IB[1]
Out.SelIB1n ← FALSE;
Out.IBPtr ← Byte;
END;
Prom[i] ← Out;
ENDLOOP;
END;

AdvanceIB: PROCEDURE =
BEGIN
-- Load IBFront from either IB[0] or IB[1] as specified by the old value of IBPtr.1
Out.loadIBFront ← TRUE;
Out.SelIB0n ← (A.IBPtr MOD 2) = 1;-- SelIB0n is inverse of IBPtr.1
Out.SelIB1n ← ~Out.SelIB0n;-- SelIB1n is inverse of SelIB0n
Out.IBPtr ← SELECT A.IBPtr FROM
Full => Word,
Word => Byte,
Byte => Empty,
ENDCASE => Empty;
END;

GenIBProm[];
WritePromData["IBProm-PC-RevG", addrWidth, dataWidth, @Prom[0]];
WritePromList["IBProm-PC-RevG", addrWidth, dataWidth, @Prom[0]];
ImageDefs.StopMesa[]

END.