IFUPLAInstrDecodeImpl1.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by TWilliams, August 27, 1984 4:58:00 pm PDT
Last edited by Herrmann, August 14, 1985 12:57:15 pm PDT
Last edited by Curry, July 9, 1986 7:25:46 pm PDT
McCreight, February 27, 1986 3:51:08 pm PST
DIRECTORY
Basics,
DragOpsCross,
IFUPLAInstrDecode,
PLAOps;
IFUPLAInstrDecodeImpl1: CEDAR PROGRAM
IMPORTS IFUPLAInstrDecode, PLAOps EXPORTS IFUPLAInstrDecode =
BEGIN OPEN IFUPLAInstrDecode, PLAOps;
instr, temp:  BoolExpr;
m:   InstrDecodeOut;
DelayedRet:   InstrDecodeOut = [
nextMacro:   hold,
pcNext:    fromPCBus,
microCycleNext:  next, -- so we can recognize first cycle of RET
condEffect0: bubble ];
GenInstrDecodePLA1: PUBLIC GenInstrDecodePLAProc = {
GenInstrDecodePLAExceptions: PROC = {
ifuAddr:  BoolExpr ← BE[m:[alpha:   360B],  d:[alpha:   360B]]; -- last 16
userMode0: BoolExpr ← BE[m:[userMode0:  TRUE], d:[userMode0:  TRUE]];
pop0ping:  BoolExpr ← BE[m:[popPending: TRUE], d:[popPending: TRUE]];
push0ing:  BoolExpr ← BE[m:[pushPending: TRUE], d:[pushPending: TRUE]];
empty:  BoolExpr ← BE[m:[iStkEmpty:  TRUE], d:[iStkEmpty: TRUE]];
state0:   BoolExpr ← BE[m:[state: ByteTopSig[8]],  d:[state:   0]];
current0:  BoolExpr ← state0;
Set InstStarting bit
Set[ s: state0, out: [instStarting0: TRUE] ];
Do Exceptions
Note: Reset must be asserted for at least three machine cycles.
Set[m:[state: ByteTopSig[8]], d:[state: 116 -- Resetting -- ], out: [
nextMacro: hold,
microCycleNext: next,
protMicroCycle: TRUE,
pcNext: fromPCBus,
pcBusSrc: trapGen,
lSource: [ zero, zero ],
sSource: [ l, zero ],
aluOp: UAdd, -- clears EU carry flag
aReg: constantZero,
bReg: constantZero,
clearTrapsEnbled: TRUE,
clearUserMode: TRUE -- Kernel code should clear Reschedule waiting as well
]];
Set[m:[state: ByteTopSig[8]], d:[state: 117 -- Reset finished -- ],  out: [
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: pc,
lSource: [ zero, one ],
sSource: [ l, zero ],
aluOp: UAdd, -- clears EU carry flag
aReg: constantZero,
bReg: constantZero ]];
Set[ m:[state: ByteTopSig[8]], d:[120 -- trap0 -- ], out: [
nextMacro:   jump,
microCycleNext:  next,
protMicroCycle:  TRUE,
pcNext:    fromPCBus,
pcBusSrc:    trapGen,
lSource:    [ l3, zero ],
sSource:    [ s3, zero ]
]];
Set[ m:[state: ByteTopSig[8]], d:[121 -- trap1 -- ], out: [
nextMacro:   hold,
pcNext:    fromPCBus,
x2ASrcStatus0:  TRUE,
kIsRtOp0:    TRUE,
cReg:     [s, offset, one],
pushSc:    TRUE,
clearTrapsEnbled: TRUE,
clearUserMode:  TRUE
]];
Set[ m:[state: ByteTopSig[8]],d:[state: 124 -- cJump -- ],  out: [
nextMacro:    jump,
pcNext:    fromPCBus,
pcBusSrc:    pipe3,
lSource:    [ l3, zero ],
should be l2, but l2 = l3 because there is no conditional jump instruction that changes L
sSource:    [ s2, zero ] ]];
setStatusFrom3Lev: TRUE ]];
Set[ m:[state: ByteTopSig[8]], d:[state: 112 -- bubble --],  out: Delayed];
Not An Exception
currentBE[ m:[state: ByteTopSig[3]], d:[state: 0]];
Instruction not ready
Set[s: current,
m:[instReady: TRUE], d:[instReady: FALSE],  out: Delayed];
current ← And[current, BE[m: [instReady: TRUE], d: [instReady: TRUE]]];
Returns must wait for push0 or pop0. Today (October 25, 1985 11:54:04 am PDT) Russ Atkinson promised to make stack underflow illegal (by altering the PC of the bottom frame to point to a trap handler), so trapping an empty instruction stack is no longer necessary.
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dRET]]];
Set[s: And[instr,   Or[pop0ping, push0ing]],     out: [
nextMacro:   hold,
pcNext:    fromPCBus,
microCycleNext:  next, -- so we can recognize first cycle of RET
condEffect0: bubble]];
Set[s: And[instr, Not[Or[pop0ping, push0ing]],    empty], out: Trap];
Set[s: And[instr, Not[Or[pop0ping, push0ing]] -- ,  Not[empty] -- ], out: [
nextMacro:   jump,
pcNext:    fromPCBus,
pcBusSrc:    stack,
lSource:    [ zero, stack ],
sSource:    [ l, alpha ],
pop0:     TRUE ]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dRETN]]];
Set[s: And[instr,   Or[pop0ping, push0ing]],     out: [
nextMacro:   hold,
pcNext:    fromPCBus,
microCycleNext:  next, -- so we can recognize first cycle of RET
condEffect0: bubble
]];
Set[s: And[instr, Not[Or[pop0ping, push0ing]],    empty], out: Trap];
Set[s: And[instr, Not[Or[pop0ping, push0ing]] -- ,  Not[empty] -- ], out: [
nextMacro:   jump,
pcNext:    fromPCBus,
pcBusSrc:    stack,
lSource:    [ zero, stack ],
pop0:     TRUE ]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dRETK]]];
Note: We don't need to wait for the pipeline to empty of push0/pop0's because our own microionstructions flush the pipeline before it matters to us.
Set[s: And[instr, userMode0, state0], out: [condSel: ModeFault]]; -- OR it in
Set[s: And[instr, state0], out: [
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg:     abStackTop,
cReg:     toIfuXBus,
kPadsIn0:    TRUE,
lSource:    [ zero, stack ],
sSource:    [ l, alpha ]] ];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 1], out: NoOpMicro];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 1], out: [pop0: TRUE]];
... just add it in. This pop0 logically belongs with state 3, but can be piped ahead because the pop0 doesn't actually happen until three cycles later. This allows a return following a RETK to proceed without wait states.
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 2], out: NoOpMicro];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 3], out: [
nextMacro:   jump,
pcNext:    fromPCBus,
pcBusSrc:    stack,
x1ADstStatus:  TRUE]];
... x1ADstStatus is not pipelined, so it's generated at stage 0B to apply to the destination register address that has reached stage 3B.
Note: We formerly trapped ALS if the stack was empty. Russ Atkinson now (and has done for some time) guarantees that to be impossible. EMM October 25, 1985 11:26:44 am PDT.
ALS
Look for the case of a Call - ALS sequence broken by a Reschedule which returns with an empty IStack. ALS (L←S+alpha) => that the stack is expected to contain some local values which (if IStack is empty) have been swapped out.
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dALS]] ];
Set[s: And[instr,  pop0ping],          out: Delayed];
Set[s: And[instr, Not[pop0ping],  empty, Not[push0ing]], out: Trap];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dALS],     out:[lSource: [s, alpha]]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dASL],     out:[sSource: [l, alpha]]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dAL],     out:[lSource: [l, alpha]]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dAS],     out:[sSource: [s, alpha]]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dDIS],     out:[popSa: TRUE]];
LIP
check addr to determine if IFU or EU. EU has no special conditions.
Unfortunately, LIP from an IFU register sometimes has early side effects, including pop0ping the control stack. Therefore its last microinstruction must not experience any pipeline interference.
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dLIP]]];
Set[s: And[instr,  Not[ifuAddr]], out: [
bReg: [ zero, alpha ],
cReg: [ s, offset, one ],
pushSc: TRUE ] ];
instr ← And[instr, ifuAddr];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 0], out:[
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
pushSc: TRUE -- aborts if EU stack overflow
] ];
Set[s: And[instr, userMode0, state0], m: [alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuEldestPC].ORD], out: [condSel: ModeFault] ]; -- OR's in with other bits, protects just LIP IFUEldestPC
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro];  -- wait
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro];  -- wait
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 3], out: [
nextMacro: hold,
bReg: fromIfuXBus,
pcNext: fromPCBus,
microCycleNext: next,
kIsRtOp0: TRUE,
cReg: [ s, offset, zero ] ] ];
Set[s: And[instr, BE[m:[state: ByteTopSig[8]], d:[state: 3]]],
m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuStatus].ORD],
out: [x2ASrcStatus0: TRUE]]; -- add in register-specific bits, on time
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 4], out: []];
instr ← And[instr, BE[m:[state: ByteTopSig[8]], d:[state: 4]]]; -- add in register-specific bits, one cycle delayed
Set[s: instr,
m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuSLimit].ORD],
out: [x1ASrcSLimit: TRUE]];
Set[s: instr,
m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuYoungestL].ORD],
out: [x1ASrcStack: TRUE, x1ASrcStackL: TRUE, xBusStackL: TRUE]];
Set[s: instr,
m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuYoungestPC].ORD],
out: [x1ASrcStack: TRUE, x1ASrcStackP: TRUE]];
Set[s: instr,
m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuEldestL].ORD],
out: [x1ASrcStack: TRUE, x1ASrcStackL: TRUE, xBusStackEldest:TRUE, xBusStackL:TRUE]];
Set[s: instr,
m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuEldestPC].ORD],
out: [x1ASrcStack: TRUE, x1ASrcStackP: TRUE, xBusStackEldest:TRUE]];
SIP
trap if userMode0.
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dSIP]]];
Set[s: And[instr, userMode0, state0], out: [condSel: ModeFault] ]; -- OR's in with other bits
Set[s: And[instr, Not[ifuAddr]], out: [
bReg: abStackTop,
cReg: [ zero, alpha ],
popSb: TRUE ] ];
Set[s: instr,
m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[euField].ORD],
out: [cIsField0: TRUE ] ];
instr ← And[instr,  ifuAddr];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 0], out:[
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
popSb: TRUE,
cReg: toIfuXBus,
kPadsIn0: TRUE ] ];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro];  -- wait
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro];  -- wait
temp ← And[instr, BE[m:[state: ByteTopSig[8]], d:[state: 3]]]; -- add in register-specific bits
Set[s: temp, out: NoOpMicro];  -- wait
The following terms add in register-specific bits, to be broadcast in phase 1A.
Set[s: temp, m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuStatus].ORD], out: [x1ADstStatus: TRUE]];
Set[s: temp, m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuSLimit].ORD], out: [x1ADstSLimit: TRUE]];
Set[s: temp, m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuYoungestL].ORD], out: [x1ADstStack: TRUE, xBusStackL: TRUE]];
Set[s: temp, m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuYoungestPC].ORD], out: [x1ADstStack: TRUE]];
Set[s: temp, m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuEldestL].ORD], out: [x1ADstStack: TRUE, xBusStackEldest: TRUE, xBusStackL: TRUE]];
Set[s: temp, m:[alpha: ByteTopSig[8]], d:[alpha: DragOpsCross.ProcessorRegister[ifuEldestPC].ORD], out: [x1ADstStack: TRUE, xBusStackEldest: TRUE]];
Set[s: instr, m:[state: ByteTopSig[8]], d:[state: 4], out:[ ]];
This final state is necessary because a RET instruction can follow a SIP to IFUYoungestPC or IFUYoungestL, and perhaps in other cases as well.
};
GenInstrDecodePLAXfers: PROC = {
Used in RR and RJB instructions
src0:   BoolExpr ← BE[m:[alpha: 300B], d:[alpha: 0B]];
src1:   BoolExpr ← BE[m:[alpha: 300B], d:[alpha: 100B]];
srTop:   BoolExpr ← BE[m:[alpha: 200B], d:[alpha: 200B]];
srPop:   BoolExpr ← BE[m:[alpha: 300B], d:[alpha: 300B]];
opt:   BoolExpr ← BE[m:[alpha: 040B], d:[alpha: 040B]];
aux:   BoolExpr ← BE[m:[alpha: 020B], d:[alpha: 020B]];
m ← [
aReg: abStackTop,
x2ALitSource: alpha,
popSa: TRUE,
aluOp: VSub,
condEffect0: macroJump,
condSel: EZ,
nextMacro: get,
pcPipeSrc: offSetPC ]; -- pcOffSetSrc: betaS
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJEBB], out:m];
m.condSel ← NE;
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJNEBB], out:m];
m ← [
aReg: abStackTop,
x2ALitSource: alpha,
popSa: TRUE,
aluOp: VSub,
condEffect0: macroJump,
condSel: EZ,
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC, -- pcOffSetSrc: betaS
pcPipeSrc: seqPC
];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJNEBBJ], out:m];
m.condSel ← NE;
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJEBBJ], out:m];
dRJ*B and dRJ*BJ - Bit 4 distinguishes between them
instr ← And[current, BE[m:[op: InstrTopSig[4]], d:[op: dRJEB]]]; -- RJ*B and RJ*BJ
Main Body
Set[s:current, m:[op: InstrTopSig[5]], d:[op: dRJEB], out:[ -- RJ*B
aluOp: VSub,
condSelIsOp57: TRUE,
condEffect0: macroJump,
nextMacro: get,
pcPipeSrc: offSetPC ] ]; -- pcOffSetSrc: betaS
Set[s:current, m:[op: InstrTopSig[5]], d:[op: dRJEBJ], out:[ -- RJ*BJ
aluOp: VSub,
condSelIsOp57: TRUE,
condEffect0: macroJump,
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC, -- pcOffSetSrc: betaS
pcPipeSrc: seqPC] ];
AReg
Set[s: And[  src0, instr],        out:[aReg:[ cBase, offset, zero ]]];
Set[s: And[  src1, instr],        out:[aReg:[ cBase, offset, one ]]];
Set[s: And[  srTop, instr],        out:[aReg:[ s, offset, zero ]]];
BReg
Set[s: And[ Not[opt],   aux, instr],     out:[bReg:[ aBase, alpha47 ]]];
Set[s: And[ Not[opt],  Not[aux], instr],     out:[bReg:[ l,   alpha47 ]]];
Set[s: And[opt, instr], m:[alpha: 010B], d:[alpha: 000B], out:[bReg:[ cBase, alpha47 ]]];
Set[s: And[opt, instr], m:[alpha: 004B], d:[alpha: 000B], out:[bReg:[ cBase, alpha47 ]]];
Set[s: And[opt, instr], m:[alpha: 015B], d:[alpha: 014B], out:[bReg:[ s, offset, zero  ]]];
Set[s: And[opt, instr], m:[alpha: 015B], d:[alpha: 015B], out:[bReg:[ s, offset, minus1 ]]];
Stack
Set[s: And[srPop, instr],          out:[popSa: TRUE]];
Set[s: And[opt, instr], m:[alpha: 016B], d:[alpha: 016B], out:[popSb: TRUE]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJ1], out: DefaultMicro]; -- to mark as ~Xops
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJ2], out: DefaultMicro]; -- to mark as ~Xops
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJ3], out: DefaultMicro]; -- to mark as ~Xops
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJ5], out: DefaultMicro]; -- to mark as ~Xops
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dJS]]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 0], out:[ -- toIfuXBus ← [S]
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
cReg: toIfuXBus,
kPadsIn0: TRUE ]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 3], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 4], out:[ -- S ← S-1
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC,  -- pcOffSetSrc: xA,
popSa: TRUE ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJB], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJDB], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC ]]; -- pcOffSetSrc: alphaBetaS
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dJQB], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: alpBetGamDel ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dLFC], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: offSetPC,  -- pcOffSetSrc: alphaBetaS,
pcPipeSrc: seqPC,
push0: TRUE ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dDFC], out:[
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: alpBetGamDel,
pcPipeSrc: seqPC,
push0: TRUE ]];
Set[s:current, m:[op: InstrTopSig[8]], d:[op: dKFC], out:[
nextMacro:   jump,
pcNext:     fromPCBus,
pcBusSrc:    xopGen,
pcPipeSrc:   seqPC,
push0:     TRUE,
kIsRtOp0:    TRUE,
x2ASrcStatus0:  TRUE,
cReg:     [s, offset, one],
pushSc:    TRUE,
clearTrapsEnbled: TRUE,
clearUserMode:  TRUE
]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dSFC]]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 0], out:[ -- toIfuXBus ← [S]
nextMacro: hold,
pcNext: fromPCBus,
microCycleNext: next,
bReg: abStackTop,
cReg: toIfuXBus,
kPadsIn0: TRUE ]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 3], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 4], out:[ -- S ← S-1
nextMacro: jump,
pcNext: fromPCBus,
pcBusSrc: x,
pcPipeSrc: seqPC,
popSa: TRUE,
push0: TRUE ]];
instr ← And[current, BE[m:[op: InstrTopSig[8]], d:[op: dSFCI]]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 0], out:[ -- toIfuXBus ← [S]^
nextMacro:  hold,
pcNext:   fromPCBus,
microCycleNext: next,
bReg:    abStackTop,
cReg:    toIfuXBus,
kPadsIn0:   TRUE,
dPCmnd:   Fetch,
dPCmndIsRd0: TRUE ]];
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 1], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 2], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 3], out:NoOpMicro]; -- wait
Set[s:instr, m:[state: ByteTopSig[8]], d:[state: 4], out:[ -- S ← S-1
nextMacro:   jump,
pcNext:    fromPCBus,
pcBusSrc:    x,
pcPipeSrc: seqPC,
push0:     TRUE ]] };
current ← old;
GenInstrDecodePLAExceptions[];
GenInstrDecodePLAXfers[]};
END.