IPipe.rose
Copyright © 1984 by Xerox Corporation. All rights reserved.
Uses MicroInstructionBA and microinstruction history to set up EUControl
It interfaces with the IDecoder above and the IStack below
May raise DelayACycleAB
Last edited by: McCreight, April 13, 1984 5:46:06 pm PST
Last edited by: Curry, August 23, 1984 1:59:55 pm PDT
Directory DragonMicroPLA;
Imports Dragon, DragonIFU;
IPipe: CELL [
Decoder
XBus      =INT[32],
Lev0PA     <INT[32],
Lev0LA     <INT[8],
Lev0SA     <INT[8],
Lev0AaddrBA   <INT[8],
Lev0BaddrBA   <INT[8],
Lev0CaddrA    <INT[8],
Lev0AluRtIsKBA  <BOOL,
Lev0AluOpBA   <EnumType["Dragon.ALUOps"],
Lev0CondSelBA   <EnumType["Dragon.CondSelects"],
Lev0CondEffectBA  <EnumType["DragonMicroPLA.CondEffect"],
Lev0IStackPostEffectBA <EnumType["DragonMicroPLA.IStackPostEffect"],
Lev0ITrapPostEffectBA <EnumType["DragonMicroPLA.ITrapPostEffect"],
Lev0EuPBusCmdBA  <EnumType["Dragon.PBusCommands"],
Lev2CondSelBA   >EnumType["Dragon.CondSelects"],
Lev3CaddrBA   >INT[8],
XBSourceBA    <EnumType["DragonMicroPLA.XBSource"],
Exceptions
DontBypassBA   <BOOL,
KillPipeAB    <BOOL,
PushPendingAB   >BOOL,
PopPendingAB   >BOOL,
ITrapEffectPendingAB >EnumType["DragonMicroPLA.ITrapPostEffect"],
Lev3ITrapEffectBA  >EnumType["DragonMicroPLA.ITrapPostEffect"],
DelayACycleAB   >BOOL,
Lev2CondEffectBA  >EnumType["DragonMicroPLA.CondEffect"],
Stack
IStkPushBA    >BOOL,
IStkPopBA    >BOOL,
Lev3PBA     >INT[32],
Lev3LBA     >INT[8],
EU
KBus      =INT[32], -- PhA bidirectional, PhB A,B,C to EU
EUAluLeftisR1BA  >BOOL, -- Left Default is aRam 1B
EUAluLeftisR3BA  >BOOL, -- Left Default is aRam 1B
EUAluRightisR1BA   >BOOL, -- Right Default is bRam 1B
EUAluRightisR3BA   >BOOL, -- Right Default is bRam 1B
EUAluRightisKBA   >BOOL, -- Right Default is bRam 1B
EUS1isR1BA    >BOOL, -- Default is bRam   1B
EUS1isR3BA    >BOOL, -- Default is bRam   1B
EUAluOpAB    >EnumType["Dragon.ALUOps"],  -- 2A
EUCondSelAB   >EnumType["Dragon.CondSelects"], -- 2A
EUR2isR3BA    >BOOL, -- Default is R1    2B
EUS3isR3BA    >BOOL, -- Default is S2    2B
EUTrapBA    >BOOL, -- Trap on conditon  2B
EUHoldCarryBA   >BOOL, -- Preserve carry
EUR3isR2AB    >BOOL, -- Default is RData   3A
EUWriteToPBusAB  >BOOL, -- Data direction   3A
EUCheckPParityAB  >BOOL, -- Yes for non-FP Fetch 3A
FP
FPCSLoadBA   >EnumType["DragonFP.CSLoad"],
FPCSUAluBA  >EnumType["DragonFP.CSUnload"],
FPCSUMultBA  >EnumType["DragonFP.CSUnload"],
euPBus PBus
EPCmdA    >EnumType["Dragon.PBusCommands"],
EPRejectB   <BOOL,
Serial debugging interface
ResetAB   <BOOL,
DHoldAB   <BOOL,
DShiftAB   <BOOL,
DExecuteAB  <BOOL,
DNSelectAB  <BOOL,
DDataInAB  <BOOL,
DDataOutAB  =BOOL,
Timing and housekeeping interface
RescheduleAB <BOOL,
PhA    <BOOL,
PhB    <BOOL
]
State
delayed1: ARRAY Dragon.Phase OF DragonIFU.Level1,
level1: ARRAY Dragon.Phase OF DragonIFU.Level1,
level2: ARRAY Dragon.Phase OF DragonIFU.Level2,
level3: ARRAY Dragon.Phase OF DragonIFU.Level3,
lastCycleDelayedBA  :BOOL,
level3RejectingBA  :BOOL,
killPipeBA    :BOOL,
dHoldBA     :BOOL
EvalSimple
Bypass: PROC[
next1: DragonIFU.Level1,
lev1: DragonIFU.Level1,
lev2: DragonIFU.Level2,
lev3: DragonIFU.Level3,
noBypassing: BOOL]
RETURNS[interlock: BOOL, adjustedNext1: DragonIFU.Level1] = {
field  :Dragon.HexByte ← DragonIFU.PRtoByte[euField];
read1  :BOOL ← DragonIFU.IsRdCmd [next1.euPBus];
read2  :BOOL ← DragonIFU.IsRdCmd [lev1.euPBus];
ac2   :BOOL ← next1.a = lev1.c;
ac3   :BOOL ← next1.a = lev2.c;
bc2   :BOOL ← next1.b = lev1.c;
bc3   :BOOL ← next1.b = lev2.c;
passRt  :BOOL
next1.aluOp=Or AND next1.a=(DragonIFU.PRtoByte[euConstant]+0) AND -- EU ALU nop
NOT DragonIFU.IsFPCmd[next1.euPBus]; -- can't bypass address
interlock ← read2 AND (ac2 OR (bc2 AND NOT (next1.aluRt=k OR passRt)));
interlock ← interlock OR
next1.aluOp=FOP AND (lev1.c=field OR lev2.c=field OR lev3.c=field);
adjustedNext1 ← IF interlock THEN [] ELSE next1;
IF NOT noBypassing AND NOT interlock THEN { OPEN adjustedNext1;
aluLt ← IF ac2 THEN r1 ELSE IF ac3 THEN r3 ELSE aluLt;
aluRt ← IF next1.aluRt=k THEN aluRt
ELSE IF bc2 AND NOT read2 THEN r1
ELSE IF bc3 THEN r3 ELSE aluRt;
store1 ← IF next1.aluRt#k THEN store1 -- Write to EU => =k
ELSE IF bc2 AND NOT read2 THEN r1
ELSE IF bc3 THEN r3 ELSE store1;
result2 ← IF bc2 AND passRt THEN r3 ELSE result2;
store3 ← IF bc2 THEN r3 ELSE store3;
result3 ← IF read1 THEN rdata ELSE result3;
} };
IF PhA AND NOT dHoldBA THEN {
pipeInterlock:BOOLFALSE;
input: DragonIFU.Level1 ← [
a   : Lev0AaddrBA,
b   : Lev0BaddrBA,
aluLt  : aRam,
aluRt  : IF Lev0AluRtIsKBA THEN k ELSE bRam,
store1  : bRam,
ka   : Dragon.LFD[XBus],
aluOp  : Lev0AluOpBA,
condSel : Lev0CondSelBA,
condOp : Lev0CondEffectBA,
result2  : r1,
store3  : s2,
euPBus : Lev0EuPBusCmdBA,
result3  : IF DragonIFU.IsRdCmd[Lev0EuPBusCmdBA] THEN rdata ELSE r2,
c   : Lev0CaddrA,
iStackOp : Lev0IStackPostEffectBA,
iTrapOp : Lev0ITrapPostEffectBA,
p   : Dragon.LFD[Lev0PA],
l    : Lev0LA,
s    : Lev0SA
];
IF killPipeBA
THEN {delayed1[a] ← level1[a] ← []; level2[a] ← []; level3[a] ← []}
ELSE IF level3RejectingBA
THEN {
level1[a] ← level1[b];
level2[a] ← level2[b];
level3[a] ← level3[b];
IF lastCycleDelayedBA
THEN delayed1[a] ← delayed1[b]
ELSE delayed1[a] ← input }
ELSE {
IF lastCycleDelayedBA
THEN {
delayed1[a] ← delayed1[b];
[pipeInterlock , level1[a]]
← Bypass[delayed1[b], level1[b], level2[b], level3[b], DontBypassBA] }
ELSE {
delayed1[a] ← input;
[pipeInterlock , level1[a]]
← Bypass[input,  level1[b], level2[b], level3[b], DontBypassBA] };
level2[a].ka   ← level1[b].ka;
level2[a].aluOp  ← level1[b].aluOp;
level2[a].condSel ← level1[b].condSel;
level2[a].condOp ← level1[b].condOp;
level2[a].result2  ← level1[b].result2;
level2[a].store3  ← level1[b].store3;
level2[a].euPBus  ← level1[b].euPBus;
level2[a].result3  ← level1[b].result3;
level2[a].c    ← level1[b].c;
level2[a].iStackOp ← level1[b].iStackOp;
level2[a].iTrapOp ← level1[b].iTrapOp;
level2[a].p    ← level1[b].p;
level2[a].l    ← level1[b].l;
level2[a].s    ← level1[b].s;
level3[a].euPBus  ← level2[b].euPBus;
level3[a].result3  ← level2[b].result3;
level3[a].c    ← level2[b].c;
level3[a].iStackOp ← level2[b].iStackOp;
level3[a].iTrapOp ← level2[b].iTrapOp;
level3[a].p    ← level2[b].p;
level3[a].l    ← level2[b].l;
level3[a].s    ← level2[b].s;
};
Send off EU PhA Control
PushPendingAB ← delayed1[a].iStackOp=push OR
level1[a].iStackOp=push OR
level2[a].iStackOp=push OR
level3[a].iStackOp=push;
PopPendingAB ← delayed1[a].iStackOp=pop OR
level1[a].iStackOp=pop OR
level2[a].iStackOp=pop OR
level3[a].iStackOp=pop;
ITrapEffectPendingAB ← IF delayed1[a].iTrapOp#none
THEN delayed1[a].iTrapOp
ELSE IF level1[a].iTrapOp#none
THEN level1[a].iTrapOp
ELSE IF level2[a].iTrapOp#none
THEN level2[a].iTrapOp
ELSE level3[a].iTrapOp;
DelayACycleAB ← level3RejectingBA OR pipeInterlock;
EUAluOpAB    ← level2[a].aluOp;
EUCondSelAB   ← level2[a].condSel;
EPCmdA     ← IF level3RejectingBA THEN NoOp ELSE level2[b].euPBus;
EUWriteToPBusAB ← DragonIFU.IsWtCmd[level3[a].euPBus];
EUCheckPParityAB ← EUWriteToPBusAB AND NOT DragonIFU.IsFPCmd[level3[a].euPBus];
EUR3isR2AB   ← level3[a].result3=r2;
PhA KBus and XBus Control
Every microinstruction that causes the EU to drive the KBus must insure that following micros do not conflict.
IF DragonIFU.BytetoPR[Lev3CaddrBA] IN [ifuXBus..ifuLast]
THEN XBus ← KBus
ELSE {
IF DragonIFU.BytetoPR[Lev0BaddrBA] = ifuLevel3LS
THEN XBus ← Dragon.LTD[level3[b].s*256 + level3[b].l];
IF level2[b].euPBus=StoreFP
THEN KBus ← Dragon.LTD[level2[b].ka]
ELSE KBus ← Dragon.LTD[level1[b].ka] } };
IF PhB THEN dHoldBA ← DHoldAB;
IF PhB AND NOT DHoldAB THEN {
PhB State changes
delayed1[b] ← IF KillPipeAB THEN [] ELSE delayed1[a];
level1[b]  ← IF KillPipeAB THEN [] ELSE level1[a];
level2[b]  ← IF KillPipeAB THEN [] ELSE level2[a];
level3[b]  ← IF KillPipeAB -- p l s must be preserved for restart
THEN [p:level3[a].p, l:level3[a].l, s:level3[a].s] ELSE level3[a];
lastCycleDelayedBA ← DelayACycleAB;
level3RejectingBA ← EPRejectB;
killPipeBA   ← KillPipeAB;
Send off PhB Exception Control to IDecoder:
Lev2CondEffectBA ← level2[b].condOp;
Lev2CondSelBA  ← level2[b].condSel;
Lev3CaddrBA  ← IF level3RejectingBA THEN DragonIFU.noStore ELSE level3[b].c;
Send off PhB IStack Control and Data:
IStkPushBA
IF level3RejectingBA THEN FALSE ELSE level3[b].iStackOp=push;
IStkPopBA
IF level3RejectingBA THEN FALSE ELSE level3[b].iStackOp=pop;
Lev3ITrapEffectBA
IF level3RejectingBA THEN none ELSE level3[b].iTrapOp;
Lev3PBA  ← Dragon.LTD[level3[b].p];
Lev3LBA  ← level3[b].l;
FP Control
FPCSUAluBA ← IF NOT level3RejectingBA AND level1[b].euPBus=FetchFPAlu
THEN unload ELSE dont;
FPCSUMultBA ← IF NOT level3RejectingBA AND level1[b].euPBus=FetchFPMult
THEN unload ELSE dont;
FPCSLoadBA  ← IF NOT level3RejectingBA AND
level2[b].euPBus=StoreFP
May Need nop load to clock D regs
OR level1[b].euPBus=FetchFPAlu
OR level1[b].euPBus=FetchFPMult
THEN load ELSE dont;
Send off PhB EU Control and Data
KBus ← Dragon.LTD
[(((level1[b].a*LONG[256]) + level1[b].b)*256 + level3[b].c)*256];
EUAluLeftisR1BA ← level1[b].aluLt=r1;
EUAluLeftisR3BA ← level1[b].aluLt=r3;
EUAluRightisR1BA ← level1[b].aluRt=r1;
EUAluRightisR3BA ← level1[b].aluRt=r3;
EUAluRightisKBA ← level1[b].aluRt=k;
EUS1isR1BA   ← level1[b].store1=r1;
EUS1isR3BA   ← level1[b].store1=r3;
EUR2isR3BA   ← level2[b].result2=r3;
EUS3isR3BA   ← level2[b].store3=r3;
EUTrapBA   ← level2[b].condOp # microJump;
EUHoldCarryBA  ← killPipeBA;
Check to see if XBus driven from IPipe during phB
IF XBSourceBA = pipe3PC THEN XBus ← Dragon.LTD[level3[b].p];
}
ENDCELL