IDecoder.rose
Copyright © 1984 by Xerox Corporation. All rights reserved.
IDecoder covers Level 0 State, MicroCodeWord, A, B, C, S, L and PC
It interfaces with the IFetcher above and the IPipe below
The 16, 128, and 256 sprinkled in here need to be replaced
Last edited by: McCreight, May 9, 1984 6:47:30 pm PDT
Last edited by: Twilliams, August 27, 1984 5:43:33 pm PDT
Last edited by: Curry, August 21, 1984 12:27:02 pm PDT
Directory BitOps, DragOpsCross;
Imports Atom, Cucumber, Dragon, DragonFP, DragonIFU, DragonMicroPLA, IO;
IDecoder: CELL [
XBus      =INT[32],
IFetcher
PreOpA    <INT[8],
PreAlphaA   <INT[8],
PreBetaA    <INT[8],
PreGammaA   <INT[8],
PreDeltaA    <INT[8],
PreLengthA   <INT[3],
InstReadyA   <BOOL,
PreFetchFaultedBA <BOOL,
GetNextInstB    >BOOL,
JumpB      >BOOL,
IRegAddr
ASum0B    >EnumType["DragonMicroPLA.ABRegSum0"],
ASum1B    >EnumType["DragonMicroPLA.ABRegSum1"],
BSum0B    >EnumType["DragonMicroPLA.ABRegSum0"],
BSum1B    >EnumType["DragonMicroPLA.ABRegSum1"],
CSum0A    >EnumType["DragonMicroPLA.CRegSum0"],
CSum1A    >EnumType["DragonMicroPLA.CRegSum1"],
LSum0A    >EnumType["DragonMicroPLA.LSource0"],
LSum1A    >EnumType["DragonMicroPLA.LSource1"],
SSum0A    >EnumType["DragonMicroPLA.SSource0"],
SSum1A    >EnumType["DragonMicroPLA.SSource1"],
DeltaSPlus2A   >INT[2],
OpBA     >INT[8],
AlphaBA    >INT[8],
BetaBA    >INT[8],
ReadSLimitA   >BOOL,
SetSLimitA   >BOOL,
LAB     <INT[7],
SAB     <INT[7],
IPipe 
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"],
Exception Signals
DontBypassBA   >BOOL,
KillPipeAB    >BOOL,
PushLevel3BA   >BOOL,
PushPendingAB   <BOOL,
PopPendingAB   <BOOL,
ITrapEffectPendingAB <EnumType["DragonMicroPLA.ITrapPostEffect"],
Lev3ITrapEffectBA  <EnumType["DragonMicroPLA.ITrapPostEffect"],
DelayACycleAB   <BOOL,
Lev2CondEffectBA  <EnumType["DragonMicroPLA.CondEffect"],
EStkOverflowBA  <BOOL,
EUConditionBA   <BOOL,
EPFaultB     <EnumType["Dragon.PBusFaults"],
EPRejectB    <BOOL,
IStkEmptyA    <BOOL,
IStkTooFullA    <BOOL,
InstrCountAB   >INT[32],
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
iDecoderLogRef: REF REF,
phALastFLAG: BOOL,
iLogged:   BOOL,
State Latched during PhA
Macroinstruction
instReadyAB   :BOOL,
opNameAB   :DragOpsCross.Inst,
opAB     :Dragon.HexByte,
alphaAB    :Dragon.HexByte,
betaAB    :Dragon.HexByte,
gammaAB    :Dragon.HexByte,
deltaAB    :Dragon.HexByte,
lengthAB    :[0..6),
xAB      :Dragon.HexWord,
pAB      :Dragon.HexWord,
iStkOverflowAB  :BOOL,
iStkEmptyAB  :BOOL,
mTrapAB    :DragonMicroPLA.MicroTrap,
mStateAB    :DragonMicroPLA.IFUState,
ifuStatusControlAB :DragonMicroPLA.IFUStatusControl,
instrCountAB  :Dragon.Word,
State Latched during PhB
MicroInstruction and MicroState
mStateBA  :DragonMicroPLA.IFUState,
mInstrBA  :DragonMicroPLA.MicroInst,
The a,b,c reg microInstruction components need not be saved
instReadyBA  :BOOL, -- for logging
gammaBA   :Dragon.HexByte,
deltaBA   :Dragon.HexByte,
lengthBA   :Dragon.HexByte,
cBA     :Dragon.HexByte,
pBA     :Dragon.HexWord,
lBA    :Dragon.HexWord,
sBA     :Dragon.HexWord,
xBA     :Dragon.HexWord,
branchBA   :Dragon.HexByte,
trapPBA   :Dragon.HexWord,
delayedBA    :BOOL,
doneBA     :BOOL,
resetBA     :BOOL,
rescheduleBA   :BOOL,
iStkOverflowBA   :BOOL,
pushPendingBA   :BOOL,
popPendingBA   :BOOL,
iTrapEffectPendingBA :DragonMicroPLA.ITrapPostEffect,
lev3RejectBA   :BOOL,
lev3FaultBA    :Dragon.PBusFaults,
ifuStatusControlBA  :DragonMicroPLA.IFUStatusControl,
dHoldBA    :BOOL,
instrCountBA  :Dragon.Word
EvalSimple
ReadIFUStatus: PROC[state: DragonMicroPLA.IFUState]
RETURNS[l: LONG CARDINAL] = {
status:DragOpsCross.IFUStatus ← ALL[FALSE];
status[rescheduleClear]   ← state.rescheduleWaiting;
status[inhibitClear]    ← state.inhibitTraps;
l ← Dragon.LFD[LOOPHOLE[status]]};
ReadStatusControl:PROC[d:BitOps.BitDWord]
RETURNS[sc:DragonMicroPLA.IFUStatusControl] = {
status:DragOpsCross.IFUStatus ← LOOPHOLE[d];
IF status[rescheduleClear] THEN sc.reschedule ← clear;
IF status[rescheduleSet]  THEN sc.reschedule ← set;
IF status[inhibitClear]  THEN sc.inhibit  ← clear;
IF status[inhibitSet]   THEN sc.inhibit  ← set };
SExtnd: PROC[b: Dragon.HexByte] RETURNS [l: INT] = {
RETURN[ IF b>=128 THEN (LONG[b]-256) ELSE LONG[b]] };
log: IO.STREAM = NARROW[iDecoderLogRef^];
IF PhA THEN {
Dragon.Assert[ resetBA OR mStateBA.exceptions IN [aboutToReset..reset] OR NOT instReadyBA OR OpBA IN (0..255), "Breakpoint XOP encountered" ];
IF NOT dHoldBA THEN {
IF NOT phALastFLAG THEN {
Get Next Micro Trap Instruction
phALastFLAG ← TRUE;
iLogged ← resetBA OR mStateBA.exceptions = aboutToReset;
[mTrapAB, mStateAB] ← DragonMicroPLA.GetMicroTrap[ [
state      :mStateBA,
ifuStatusControl  :ifuStatusControlBA,
iTrapEffect3   :Lev3ITrapEffectBA,
delayed    :delayedBA,
done     :doneBA,
reset     :resetBA,
reschedule   :rescheduleBA,
preFetchFaulted  :PreFetchFaultedBA,
pushPending   :pushPendingBA,
popPending   :popPendingBA,
iTrapEffectPending :iTrapEffectPendingBA,
iStkOverflow   :iStkOverflowBA,
eStkOverflow  :EStkOverflowBA,
aluCondResult2  :EUConditionBA,
aluCond2    :Lev2CondSelBA,
condEffect2   :Lev2CondEffectBA,
pBusReject3   :lev3RejectBA,
pBusFault3   :lev3FaultBA
] ];
instrCountAB ← IF resetBA OR mStateBA.exceptions = aboutToReset
THEN 0
ELSE IF ( NOT mInstrBA.dontGetNextMacro ) OR mInstrBA.doMacroJump
THEN instrCountBA+1
ELSE instrCountBA };
Check to see if PhA XBus driven from IDecoder
SELECT mInstrBA.xASource FROM
none    => { };
alpha    => XBus ← Dragon.LTD[AlphaBA];
beta    => XBus ← Dragon.LTD[BetaBA];
betaAlpha  => XBus ← Dragon.LTD[BetaBA*256 + AlphaBA];
deltaGammaBetaAlpha =>
XBus ← Dragon.LTD[((deltaBA*LONG[256]+gammaBA)*256+BetaBA)*256+AlphaBA];
bAddrIFUReg  => {
IF Lev0BaddrBA=DragonIFU.PRtoByte[ifuStatus]
THEN XBus ← Dragon.LTD[ReadIFUStatus[mStateBA]]};
fpLdMode => XBus ← DragonFP.InsertLoadFunction[mode, AlphaBA, XBus];
fpLdAMsw => XBus ← DragonFP.InsertLoadFunction[aHi, AlphaBA, XBus];
fpLdALsw => XBus ← DragonFP.InsertLoadFunction[aLo, AlphaBA, XBus];
fpLdBMsw => XBus ← DragonFP.InsertLoadFunction[bHi, AlphaBA, XBus];
fpLdBLsw => XBus ← DragonFP.InsertLoadFunction[bLo, AlphaBA, XBus];
fpUnldMsw => XBus ← DragonFP.InsertUnload[msw, XBus];
fpUnldLsw => XBus ← DragonFP.InsertUnload[lsw, XBus];
ENDCASE  => ERROR;
ReadSLimitA ← mInstrBA.xASource=bAddrIFUReg AND Lev0BaddrBA=DragonIFU.PRtoByte[ifuSLimit];
Buffer copy of PhA XBus
xAB ← Dragon.LFD[XBus];
Load P,L and S
pAB ← xBA;
LSum0A ← mInstrBA.lSource.s0;
LSum1A ← mInstrBA.lSource.s1;
DeltaSPlus2A ← 2 +
(IF (mInstrBA.deltaSc = push) THEN 1 ELSE 0) -
(IF (mInstrBA.deltaSa = pop) THEN 1 ELSE 0) -
(IF (mInstrBA.deltaSb = pop) THEN 1 ELSE 0);
SSum0A ← mInstrBA.sSource.s0;
SSum1A ← mInstrBA.sSource.s1;
Load PreFetch MacroWord
instReadyAB ← InstReadyA;
opAB   ← PreOpA; TRUSTED {opNameAB ← LOOPHOLE[PreOpA]};
alphaAB  ← PreAlphaA;
betaAB   ← PreBetaA;
gammaAB  ← PreGammaA;
deltaAB  ← PreDeltaA;
lengthAB  ← PreLengthA;
Save IStack overflow conditions
iStkEmptyAB  ← IStkEmptyA;
iStkOverflowAB  ← IStkTooFullA;
Check to see if PhA XBus has IFU data
SetSLimitA ← Lev3CaddrBA=DragonIFU.PRtoByte[ifuSLimit];
ifuStatusControlAB ← IF Lev3CaddrBA=DragonIFU.PRtoByte[ifuStatus]
THEN ReadStatusControl[XBus]
ELSE [nop, nop];
Send out the PhA Piped PLS
SELECT mInstrBA.pipedPLSASpec FROM
pls     => {
Lev0PA ← Dragon.LTD[pBA];
Lev0LA ← lBA;
Lev0SA ← sBA };
pLenLSnext  => {
Lev0PA ← Dragon.LTD[pBA + lengthBA];
Lev0LA ← LAB;
Lev0SA ← SAB };
pAlphasLSnext => {
Lev0PA ← Dragon.LTD[(pBA + SExtnd[AlphaBA])]; 
Lev0LA ← LAB;
Lev0SA ← SAB };
ENDCASE   => ERROR;
Send out C and killpipe to Pipe
CSum0A ← mInstrBA.cReg.s0;
CSum1A ← mInstrBA.cReg.s1;
KillPipeAB ← mTrapAB.killPipe;
Register instruction count update (for simulation only)
InstrCountAB ← Dragon.LTD[instrCountBA];
};
};
IF NOT PhA AND NOT iLogged AND log # IO.noWhereStream THEN {
This logging was formerly done at the beginning of Ph0B. Now we do it
at the end of Ph1A. This means that we have to pipeline instReadyAB.
iLogged ← TRUE;
IF mStateBA.exceptions=reset THEN {
log.Flush[];
log.PutF["\n\n\nIDecoder Log %g", IO.time[] ]};
log.PutF["\n%5g", IO.card[instrCountBA] ];
SELECT TRUE FROM
mStateBA.exceptions=reset
=> log.PutF["**Reset "];
mStateBA.exceptions=epFault
=> log.PutF["**EPFault "];
mStateBA.exceptions=euCC
=> log.PutF["**EUCC "];
mStateBA.exceptions=epReject
=> log.PutF["**EPReject "];
mStateBA.exceptions=cJump
=> log.PutF["**CJRestrt "];
mStateBA.exceptions=rschlWait
=> log.PutF["**Reschdl "];
mStateBA.exceptions=iStkOFlow
=> log.PutF["**IStkOver "];
mStateBA.exceptions=eStkOFlow
=> log.PutF["**EStkOver "];
mStateBA.exceptions=iFtchFault
=> log.PutF["**IPgFault "];
mInstrBA.doMacroJump AND xBA=4010040B
=> log.PutF["**IStkUndr "];
ENDCASE
=> log.PutF[" "];
IF mInstrBA.delayed
THEN log.PutF["dly "]
ELSE log.PutF[" "];
log.PutF["pc:%08x", IO.card[pBA] ];
IF NOT instReadyBA
THEN log.PutF["---"]
ELSE {
log.PutF[" %-7g", IO.rope[opName[OpBA]]];
IF lengthBA > 3
THEN log.PutF[" %02x%02x", IO.card[deltaBA], IO.card[gammaBA]]
ELSE log.PutF[" "];
IF lengthBA > 2 THEN log.PutF["%02x", IO.card[BetaBA]] ELSE log.PutF[" "];
IF lengthBA > 1 THEN log.PutF["%02x", IO.card[AlphaBA]] ELSE log.PutF[" "];
log.PutF[" l:%02x", IO.card[lBA]]; -- at beginning of instruction
log.PutF[ " s:%02x", IO.card[sBA]]; -- at beginning of instruction
IF NOT mInstrBA.delayed THEN {
log.PutF[" a:%02x", IO.card[Lev0AaddrBA]];
log.PutF[ " b:%02x", IO.card[Lev0BaddrBA]];
log.PutF[ " c:%02x", IO.card[Lev0CaddrA]] } } };
IF PhB THEN dHoldBA ← DHoldAB;
IF PhB AND NOT DHoldAB THEN {
IF phALastFLAG THEN {
phALastFLAG ← FALSE;
[mInstrBA] ← DragonMicroPLA.GetMicroInst[ [
state      :mStateAB,
op      :opNameAB,
alpha     :alphaAB,
beta     :betaAB,
delayACycle   :DelayACycleAB,
iStkEmpty   :iStkEmptyAB,
pushPending   :PushPendingAB,
popPending   :PopPendingAB,
instReady   :instReadyAB
] ] };
Latch PhB Copies
OpBA     ← opAB;
AlphaBA    ← alphaAB;
BetaBA    ← betaAB;
gammaBA   ← gammaAB;
deltaBA    ← deltaAB;
lengthBA    ← lengthAB;
instReadyBA   ← instReadyAB;
pBA     ← pAB;
lBA     ← LAB;
sBA     ← SAB;
mStateBA    ← mStateAB;
doneBA ←
mInstrBA.doMacroJump OR
( NOT mInstrBA.dontGetNextMacro ) OR
mStateAB.cycle = 0 AND NOT instReadyAB;
delayedBA ← mInstrBA.delayed;
resetBA    ← ResetAB;
rescheduleBA  ← RescheduleAB;
iStkOverflowBA  ← iStkOverflowAB;
pushPendingBA  ← PushPendingAB OR mInstrBA.iStackPostEffect=push;
popPendingBA  ← PopPendingAB OR mInstrBA.iStackPostEffect=pop;
iTrapEffectPendingBA ← IF mInstrBA.iTrapPostEffect#none
THEN mInstrBA.iTrapPostEffect
ELSE ITrapEffectPendingAB;
lev3RejectBA  ← EPRejectB;
lev3FaultBA   ← EPFaultB;
ifuStatusControlBA ← ifuStatusControlAB;
instrCountBA  ← instrCountAB;
Check to see if XBus driven from IDecoder during phB
SELECT mInstrBA.xBSource FROM
pcPlusAlphaS   => XBus ← Dragon.LTD[pBA+SExtnd[alphaAB]];
pcPlusBetaAlphaS  => XBus ← Dragon.LTD[pBA+SExtnd[betaAB]*256 + alphaAB];
deltaGammaBetaAlpha =>
XBus ← Dragon.LTD[((deltaAB*LONG[256]+gammaAB)*256+betaAB)*256+alphaAB];
pc     => XBus ← Dragon.LTD[pBA];
pcPlusLen  => XBus ← Dragon.LTD[pBA + lengthAB];
xA    => XBus ← Dragon.LTD[xAB];
pcPlusXA   => XBus ← Dragon.LTD[pBA + xAB];
xopGenerator  => XBus ← Dragon.LTD[16*(opAB+DragOpsCross.XopBase)];
trapPCGenerator => XBus ← Dragon.LTD[mTrapAB.trapPC];
iStackPC   => {-- Driven in IStack --};
pipe3PC   => {-- Driven in IPipe --};
ENDCASE   => ERROR;
Latch PhB XBus Copies
xBA ← Dragon.LFD[XBus];
Calculate A and B register addresses
ASum0B ← mInstrBA.aReg.s0;
ASum1B ← mInstrBA.aReg.s1;
BSum0B ← mInstrBA.bReg.s0;
BSum1B ← mInstrBA.bReg.s1;
Send out PhB IFetcher control and data
GetNextInstB  ← NOT ResetAB AND NOT mInstrBA.dontGetNextMacro;
JumpB   ← ResetAB OR mInstrBA.doMacroJump;
Send out the PhB Pipe goodies
Lev0AluRtIsKBA ← mInstrBA.aluRtIsK;
Lev0AluOpBA  ← IF mInstrBA.aluOp = op47
THENLOOPHOLE[opAB MOD 16]
ELSE mInstrBA.aluOp;
Lev0CondSelBA  ← IF mInstrBA.condSel = op57
THENLOOPHOLE[opAB MOD 8]
ELSE mInstrBA.condSel;
Lev0CondEffectBA ← mInstrBA.condEffect;
DontBypassBA    ← mInstrBA.dontBypass;
PushLevel3BA    ← mInstrBA.pushLevel3;
Lev0IStackPostEffectBA  ← mInstrBA.iStackPostEffect;
Lev0ITrapPostEffectBA  ← mInstrBA.iTrapPostEffect;
Lev0EuPBusCmdBA   ← mInstrBA.euPBusCmd;
XBSourceBA   ← mInstrBA.xBSource;
};
Initializer
IF initData#NIL THEN
WITH initData SELECT FROM
pl: Atom.PropList =>
BEGIN
r: REF;
IF (r ← pl.GetPropFromList[$LogRef]) # NIL THEN
iDecoderLogRef ← NARROW[r, REF REF];
END;
ENDCASE => NULL;
ENDCELL;
CEDAR
opName:DragonIFU.DragOpTable ← DragonIFU.GenDragOpTable[];
IDecoderStateHandler: Cucumber.Handler = NEW[Cucumber.HandlerRep ← [
PrepareWhole: IDecoderStatePrepareProc,
PartTransfer: IDecoderTransferProc
]];
IDecoderStatePrepareProc: PROC [ whole: REF ANY, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY ] RETURNS [ leaveTheseToMe: Cucumber.SelectorList ] -- Cucumber.Bracket -- =
{leaveTheseToMe ← LIST[$iDecoderLogRef]};
IDecoderTransferProc: PROC [ whole: REF ANY, part: Cucumber.Path, where: IO.STREAM, direction: Cucumber.Direction, data: REF ANY ] -- Cucumber.PartTransferProc -- = {NULL};
Cucumber.Register[IDecoderStateHandler, CODE[IDecoderStateRec]];