IFURAMControl.rose
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by: McCreight, September 11, 1984 5:58:58 pm PDT
Last edited by: Curry, September 28, 1984 10:14:09 am PDT
Imports BitOps, Dragon;
Cedar
iBufWords: NAT = 4;
iBufBytes: NAT = 4*iBufWords;
iStackWords: NAT = 16;
InBufInterval: PROC [ point, base, length: NAT, modulus: NAT ← iBufBytes ] RETURNS [ BOOL ] =
{RETURN[InInterval[point, base, length, modulus]};
InStackInterval: PROC [ point, base, length: NAT, modulus: NAT ← iStackWords ] RETURNS [ BOOL ] =
{RETURN[InInterval[point, base, length, modulus]};
InInterval: PROC [ point, base, length, modulus: NAT ] RETURNS [ BOOL ] =
{RETURN[Mod[point-base, modulus] < length]};
Mod: PROC [ x: INTEGER, modulus: NAT ] RETURNS [ NAT ] =
{RETURN[(x+modulus) MOD modulus]};
;
IFUFetchControl: CELL [
Signal names obey the following convention: If a signal x is computed during PhA and remains valid throughout the following PhB, it is denoted as xAB. If x is computed during PhA and can change during the following PhB (as, for example, in precharged logic), it is denoted as xA. In this latter case, a client wanting to use x during PhB must receive it in his own latch open during PhA. xBA and xB are defined symmetrically. Positive logic is assumed (asserted = TRUE = 1 = more positive logic voltage); negative-logic signals have an extra "N" at or very near the beginning of the signal name (e.g., PNPError for PBus Negative-TRUE Parity Error).
Interface to IFU control
PreFetchFaultedBA >BOOL,
GetNextInstB   <BOOL, -- iff InstReadyA
JumpB     <BOOL, -- allowed any time
JumpByteOffsetB <INT[2],
P Interfaces for IFU cache
IPCmdA   >EnumType["Dragon.PBusCommands"],
IPRejectB   <BOOL,
IPFaultB   <EnumType["Dragon.PBusFaults"],
IPNPErrorB   =BOOL,
Control slice to IPCHandler
IncrPrefetchPCBA > BOOL,
Control slice to IPrefetchBuffer
IBufWrtWdClkB > INT[4],
IBufRdByteClkA > INT[16],
Control slice to IReg
BufHasAtLeast1A > BOOL, -- control slice
BufHasAtLeast2A > BOOL,
BufHasAtLeast3A > BOOL,
BufHasAtLeast5A > BOOL,
OpLengthAB   < INT[3],
Serial debugging interface
All the following signals change during PhA and propagate during the remainder of PhA and PhB, giving an entire clock cycle for them to propagate throughout the machine. Each user must receive them into a latch open during PhB. The effects of changes are intended to happen throughout the following PhA, PhB pair.
DHold0BA, DHold1AB <BOOL, -- must be high before testing
Timing and housekeeping interface
PhA    <BOOL,
PhB    <BOOL
]
State
phBNeedsCheck: BOOLFALSE,
pendingJumpBA, pendingJumpAB: BOOL,
jumpFinishedBA, jumpFinishedAB: BOOL,
newFetchBA: BOOL,
fetchingBA, fetchingAB: BOOL,
faultedBA, faultedAB: BOOL,
firstWrtWordBA, firstWrtWordAB: [0..iBufWords),
firstRdByteBA, firstRdByteAB: [0..iBufBytes)
EvalSimple
IF PhA THEN
BEGIN
pendingJumpAB ← pendingJumpBA;
jumpFinishedAB ← jumpFinishedBA;
fetchingAB ← fetchingBA;
faultedAB ← faultedBA;
firstRdByteAB ← firstRdByteBA;
firstWrtWordAB ← firstWrtWordBA;
IPCmdA ← IF newFetchBA THEN Fetch ELSE NoOp;
BufHasAtLeast1A ← jumpFinishedBA AND firstRdByteBA#4*firstWrtWordBA;
BufHasAtLeast2A ← ((firstRdByteBA+1) MOD iBufBytes)#4*firstWrtWordBA;
BufHasAtLeast3A ← ((firstRdByteBA+2) MOD iBufBytes)#4*firstWrtWordBA;
BufHasAtLeast5A ← ((firstRdByteBA+3) MOD iBufBytes)#4*firstWrtWordBA AND
((firstRdByteBA+4) MOD iBufBytes)#4*firstWrtWordBA;
IBufRdByteClkA ← BitOps.WShift[op: 1, containerWidth: 16, shift: firstRdByteBA];
END -- of PhA evaluation
ELSE IBufRdByteClkA ← 0;
IF PhB THEN
BEGIN
pendingJumpBA ← (DHold1AB AND pendingJumpAB) OR
(pendingJumpAB AND IPRejectB) OR
(NOT DHold1AB AND JumpB AND IPRejectB);
jumpFinishedBA ← (DHold1AB AND jumpFinishedAB) OR
(jumpFinishedAB AND NOT JumpB) OR
(NOT DHold1AB AND NOT pendingJumpAB AND NOT JumpB AND NOT IPRejectB);
newFetchBA ←
(NOT DHold1AB AND NOT faultedAB AND NOT IPRejectB AND fetchingAB AND NOT InBufInterval[point: 4*firstWrtWordAB, base: firstRdByteAB, length: 9] -- plenty of space exists -- ) OR
(NOT DHold1AB AND NOT faultedAB AND NOT IPRejectB AND NOT fetchingAB AND NOT InBufInterval[point: 4*firstWrtWordAB, base: firstRdByteAB, length: 5] -- slightly less space exists -- );
fetchingBA ← (DHold1AB AND fetchingAB) OR
(fetchingAB AND IPRejectB AND IPFaultB#None) OR
newFetchBA;
faultedBA ← (DHold1AB AND faultedAB) OR
(faultedAB AND NOT JumpB) OR
(NOT DHold1AB AND IPFaultB#None);
firstWrtWordBA ← SELECT TRUE FROM
DHold1AB => firstWrtWordAB,
JumpB => 0,
fetchingAB AND NOT IPRejectB => (firstWrtWordAB+1) MOD iBufWords,
ENDCASE => firstWrtWordAB;
firstRdByteBA ← SELECT TRUE FROM
DHold1AB=> firstRdByteAB,
JumpB => JumpByteOffsetB,
GetNextInstB => (firstRdByteAB+OpLengthAB) MOD iBufBytes,
ENDCASE => firstRdByteAB;
IncrPrefetchPCBA ← NOT DHold1AB
AND fetchingAB
AND NOT IPRejectB
AND NOT pendingJumpAB
AND NOT JumpB;
IBufWrtWdClkB ← BitOps.WShift[op: (IF fetchingAB THEN 1 ELSE 0), containerWidth: 4, shift: firstWrtWordAB];
phBNeedsCheck ← TRUE;
END -- of PhB evaluation
ELSE
BEGIN
IF phBNeedsCheck THEN
BEGIN
Dragon.Assert[NOT (IPFaultB # None AND NOT IPRejectB)];
Dragon.Assert[NOT (GetNextInstB AND (JumpB OR NOT jumpFinishedBA OR InBufInterval[point: 4*firstWrtWordAB, base: firstRdByteAB, length: OpLengthAB]))];
phBNeedsCheck ← FALSE;
END;
IBufWrtWdClkB ← 0;
END
ENDCELL;
IFUStackControl: CELL [
Interface to IFU control
ResetBA   < BOOL,
IStkPushBA  < BOOL,
IStkPopBA  < BOOL,
IStkEmptyA  > BOOL,
IStkTooFullA  > BOOL,
Control slice to IPCStack
PushEldestPCA < BOOL,
PopEldestPCA < BOOL,
WritePCStackBA < BOOL,
IPCStkWrtClkA > INT[16],
IPCStkRdClkB > INT[16],
Control slice to ILStack
ILStkWrtClkA < INT[16],
ILStkRdClkB  < INT[16],
Lev0BaddrBA <INT[8], -- for LIFUR
Lev3CaddrBA <INT[8], -- for SIFUR
XBSourceBA  <EnumType["DragonMicroPLA.XBSource"],
Serial debugging interface
All the following signals change during PhA and propagate during the remainder of PhA and PhB, giving an entire clock cycle for them to propagate throughout the machine. Each user must receive them into a latch open during PhB. The effects of changes are intended to happen throughout the following PhA, PhB pair.
DHold0BA, DHold1AB <BOOL, -- must be high before testing
PhA    <BOOL,
PhB    <BOOL
]
State
phALast: BOOL;
topBA, topAB, bottomBA, bottomAB: [0..iStackWords),
pushYoungestA, popYoungestA, pushEldestA, popEldestA, wasEmpty: BOOLFALSE
EvalSimple
b0: DragOpsCross.ProcessorRegister ← DragonIFU.BytetoPR[Lev0BaddrBA];
c3: DragOpsCross.ProcessorRegister ← DragonIFU.BytetoPR[Lev3CaddrBA];
IF PhA THEN
BEGIN
topAB ← SELECT TRUE FROM
DHold0BA => topBA,
ResetBA => 0,
IStkPushBA OR PushLevel3BA => topBA+1,
IStkPopBA => topBA-1,
ENDCASE => topBA;
bottomAB ← SELECT TRUE FROM
DHold0BA => bottomBA,
ResetBA => 0,
c3 = ifuEldestPC => bottomBA-1,
b0 = ifuEldestPC => bottomBA+1,
ENDCASE => bottomBA;
IStkEmptyA ← topBA=bottomBA;
IStkTooFull ← Mod[topBA-bottomBA, iStackWords] < (iStackWords-gap);
IPCStkWrtClkA ← BitOps.WShift[op: 1, containerWidth: 16, shift: topBA];
ILStkWrtClkA ← BitOps.WShift[op: 1, containerWidth: 16, shift: topBA];
SELECT TRUE FROM
b0 IN [ifuYoungestL..ifuEldestPC] => {
Dragon.Assert[ NOT wasEmpty ];
SELECT b0 FROM
ifuYoungestL => XBus ← BitOps.ICID[iStk[top].l, [0,0], 32, lpx, lwx];
ifuYoungestPC => XBus ← Dragon.LTD[iStk[top].p];
ifuEldestL  => XBus ← BitOps.ICID[iStk[bot].l, [0,0], 32, lpx, lwx];
ifuEldestPC  => XBus ← Dragon.LTD[iStk[bot].p];
ENDCASE   => NULL}; -- Not an IFU stack register
c3 IN [ifuYoungestL..ifuEldestPC] =>
SELECT c3 FROM
ifuYoungestL => iStk[top].l ← BitOps.ECFD[XBus, 32, lpx, lwx];
ifuYoungestPC => iStk[top].p ← Dragon.LFD[XBus];
ifuEldestL  => iStk[bot].l ← BitOps.ECFD[XBus, 32, lpx, lwx];
ifuEldestPC  => iStk[(bot+m1) MOD depth].p ← Dragon.LFD[XBus];
ENDCASE   => NULL; -- Not an IFU stack register
ENDCASE => NULL; -- nothing special happening
phALast ← TRUE;
END
ELSE
BEGIN
IF phALast THEN
BEGIN
Dragon.Assert[NOT Dragon.MoreThanOneOf[IStkPushBA, PushLevel3BA]];
Dragon.Assert[NOT Dragon.MoreThanOneOf[c3 = ifuEldestPC, b0 = ifuEldestPC]];
Dragon.Assert[NOT Dragon.MoreThanOneOf[IStkPushBA OR PushLevel3BA, IStkPopBA]];
IF top=depth OR bot=depth THEN {
Dragon.Assert[top=depth AND bot=depth, "Both or neither"];
top ← 0; bot ← 1; wasEmpty ← TRUE;
IF Valid[0] THEN Dragon.Assert[FALSE, "IStack completely full"]};
size ← (top+(depth-bot)+1) MOD depth;
SELECT delta+size FROM
<0     => Dragon.Assert[FALSE, "IStack Underflowed"];
=0     => {IStkEmptyA ← TRUE; IStkTooFullA ← FALSE};
IN(0..depth-gap] => {IStkEmptyA ← FALSE; IStkTooFullA ← FALSE};
ENDCASE   => {IStkEmptyA ← FALSE; IStkTooFullA ← TRUE};
phALast ← FALSE;
END;
IPCStkWrtClkA ← 0;
END;
IF PhB THEN
BEGIN
topBA ← SELECT TRUE FROM
DHold1AB => topAB,
pushYoungestA => topAB+1,
popYoungestA => topAB-1,
ENDCASE => topAB;
bottomBA ← SELECT TRUE FROM
DHold1AB => bottomAB,
pushEldestA => bottomAB-1,
popEldestA => bottomAB+1,
ENDCASE => bottomAB;
FOR i: NAT IN [0..depth) DO
IF iStk[i].valid[b]
AND NOT iStk[(i+1) MOD depth].valid[b] -- top
AND XBSourceBA = iStackPC THEN {
Dragon.Assert[ NOT IStkEmptyA ];
XBus ← Dragon.LTD[iStk[i].p]};
ENDLOOP;
END;
ENDCELL