EU2ControlImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier March 28, 1986 12:11:16 pm PST
DIRECTORY CoreCreate, Dragon, EU2Arith, EU2Control, EU2ControlAlps, EU2Utils, Ports, Rosemary;
EU2ControlImpl: CEDAR PROGRAM
IMPORTS CoreCreate, EU2Arith, EU2ControlAlps, EU2Utils, Ports, Rosemary
EXPORTS EU2Control =
BEGIN OPEN CoreCreate, EU2Arith, EU2Control, EU2Utils;
public: Wire ← Union[GenPGnEWires[], GenClockWires[], GenWiresCtrlToPads[], GenWiresPadsToCtrl[], GenWiresDBus[], GenWiresForRouter[]];
-- PGE
Vdd: PUBLIC NAT ← PortIndex[public, "Vdd"];
Gnd: PUBLIC NAT ← PortIndex[public, "Gnd"];
phA: PUBLIC NAT ← PortIndex[public, "phA"];
phB: PUBLIC NAT ← PortIndex[public, "phB"];
nPhA: PUBLIC NAT ← PortIndex[public, "nPhA"];
nPhB: PUBLIC NAT ← PortIndex[public, "nPhB"];
-- Inputs
res3BisP: PUBLIC NAT ← PortIndex[public, "res3BisP"];
writePBus: PUBLIC NAT ← PortIndex[public, "writePBus"];
aluOp: PUBLIC NAT ← PortIndex[public, "aluOp"];
condSel: PUBLIC NAT ← PortIndex[public, "condSel"];
reject: PUBLIC NAT ← PortIndex[public, "reject"];
debug: PUBLIC NAT ← PortIndex[public, "debug"];
ramAdr: PUBLIC NAT ← PortIndex[public, "ramAdr"];
ctrl8: PUBLIC NAT ← PortIndex[public, "ctrl8"];
st3AisC: PUBLIC NAT ← PortIndex[public[ctrl8], "st3AisC"];
leftSrc: PUBLIC NAT ← PortIndex[public[ctrl8], "leftSrc"];
rightSrc: PUBLIC NAT ← PortIndex[public[ctrl8], "rightSrc"];
st2ASrc: PUBLIC NAT ← PortIndex[public[ctrl8], "st2ASrc"];
zero: PUBLIC NAT ← PortIndex[public, "zero"];
carryOut: PUBLIC NAT ← PortIndex[public, "carryOut"];
res: PUBLIC NAT ← PortIndex[public, "res"];
opL: PUBLIC NAT ← PortIndex[public, "opL"];
opR: PUBLIC NAT ← PortIndex[public, "opR"];
fd: PUBLIC NAT ← PortIndex[public, "fd"];
insertFd: PUBLIC NAT ← PortIndex[public[fd], "insertFd"];
maskFd: PUBLIC NAT ← PortIndex[public[fd], "maskFd"];
shiftFd: PUBLIC NAT ← PortIndex[public[fd], "shiftFd"];
-- Outputs
enWrtPBus: PUBLIC NAT ← PortIndex[public, "enWrtPBus"];
enWrtIFU: PUBLIC NAT ← PortIndex[public, "enWrtIFU"];
condition: PUBLIC NAT ← PortIndex[public, "condition"];
selA: PUBLIC NAT ← PortIndex[public, "selA"];
selB: PUBLIC NAT ← PortIndex[public, "selB"];
selC: PUBLIC NAT ← PortIndex[public, "selC"];
selALow: PUBLIC NAT ← PortIndex[public, "selALow"];
selBLow: PUBLIC NAT ← PortIndex[public, "selBLow"];
selCLow: PUBLIC NAT ← PortIndex[public, "selCLow"];
dRamRead: PUBLIC NAT ← PortIndex[public, "dRamRead"];
pipeRegsSel: PUBLIC NAT ← PortIndex[public, "pipeRegsSel"];
op: PUBLIC NAT ← PortIndex[public, "op"];
carryIn: PUBLIC NAT ← PortIndex[public, "carryIn"];
insert: PUBLIC NAT ← PortIndex[public, "insert"];
mask: PUBLIC NAT ← PortIndex[public, "mask"];
shift: PUBLIC NAT ← PortIndex[public, "shift"];
sh: PUBLIC NAT ← PortIndex[public, "sh"];
CreateEU2Control: PUBLIC PROC RETURNS [cellType: CellType] = {
cellType ← Cell[
name: "EU2Control",
public: public,
instances: LIST[
Instance[EU2ControlAlps.CreateDPControl[]],
Instance[EU2ControlAlps.CreateRamControl[]]]
];
-- PGE
[] ← Rosemary.SetFixedWire[cellType.public[Vdd], H];
[] ← Rosemary.SetFixedWire[cellType.public[Gnd], L];
-- Inputs
[] ← Ports.InitPort[cellType.public[aluOp], c, none];
[] ← Ports.InitPort[cellType.public[condSel], c, none];
[] ← Ports.InitPort[cellType.public[ramAdr][a][hi], c, none];
[] ← Ports.InitPort[cellType.public[ramAdr][a][hi], c, none];
[] ← Ports.InitPort[cellType.public[ramAdr][b][low], c, none];
[] ← Ports.InitPort[cellType.public[ramAdr][b][hi], c, none];
[] ← Ports.InitPort[cellType.public[ramAdr][c][low], c, none];
[] ← Ports.InitPort[cellType.public[ramAdr][c][low], c, none];
[] ← Ports.InitPort[cellType.public[ctrl8][st3AisC], b, none];
[] ← Ports.InitPort[cellType.public[ctrl8][leftSrc], c, none];
[] ← Ports.InitPort[cellType.public[ctrl8][rightSrc], c, none];
[] ← Ports.InitPort[cellType.public[ctrl8][st2ASrc], c, none];
[] ← Ports.InitPort[cellType.public[res], c, none];
[] ← Ports.InitPort[cellType.public[opL], c, none];
[] ← Ports.InitPort[cellType.public[opR], c, none];
[] ← Ports.InitPort[cellType.public[fd][insertFd], b, none];
[] ← Ports.InitPort[cellType.public[fd][maskFd], c, none];
[] ← Ports.InitPort[cellType.public[fd][shiftFd], c, none];
-- Outputs
[] ← Ports.InitPort[cellType.public[enWrtPBus], b, drive];
[] ← Ports.InitPort[cellType.public[enWrtIFU], b, drive];
[] ← Ports.InitPort[cellType.public[condition], b, drive];
InitLeafPorts[cellType.public[selA], drive];
InitLeafPorts[cellType.public[selB], drive];
InitLeafPorts[cellType.public[selC], drive];
InitLeafPorts[cellType.public[selALow], drive];
InitLeafPorts[cellType.public[selBLow], drive];
InitLeafPorts[cellType.public[selCLow], drive];
[] ← Ports.InitPort[cellType.public[dRamRead], b, drive];
InitLeafPorts[cellType.public[pipeRegsSel], drive];
InitLeafPorts[cellType.public[op], drive];
[] ← Ports.InitPort[cellType.public[carryIn], b, drive];
[] ← Ports.InitPort[cellType.public[insert], b, drive];
[] ← Ports.InitPort[cellType.public[mask], c, drive];
[] ← Ports.InitPort[cellType.public[shift], c, drive];
InitLeafPorts[cellType.public[sh], drive];
[] ← Rosemary.BindCellType[cellType: cellType, roseClassName: EU2ControlClass];
};
EU2ControlClass: ROPE = Rosemary.Register[roseClassName: "EU2Control", evalSimple: EU2ControlSimple];
bndCheck: NAT = ORD[Dragon.ALUOps[BndChk]]; -- also in EU2Utils
fop: NAT = ORD[Dragon.ALUOps[FOP]];
EU2ControlSimple: Rosemary.EvalProc = {
state: EU2ControlState ← NARROW[stateAny];
{OPEN state;
Reset: PROC [reg: PipeRange] ~ {
size: NAT ← sources[reg].sizeSel;
FOR i: NAT IN [0..size+1) DO
p[pipeRegsSel][reg][i].b ← FALSE;
ENDLOOP;
};
SimpleSel: PROC [reg: PipeRange, source: NAT] ~ {
size: NAT ← sources[reg].sizeSel;
FOR i: NAT IN [0..size) DO
p[pipeRegsSel][reg][i].b ← (p[source].c=i) AND ~rejectBA;
ENDLOOP;
p[pipeRegsSel][reg][size].b ← FALSE; -- read for debugging
};
IF p[phA].b THEN {
selAluOps: Dragon.ALUOps ← VAL[p[aluOp].c];
aluOpRec: ALUOpRec ← aluOps[selAluOps];
cAdr: NAT ← p[ramAdr][c][hi].c*4+p[ramAdr][c][low].c;
-- drive PBus
p[enWrtPBus].b ← TRUE;
-- drive KBus
p[enWrtIFU].b ← cAdr=IFUAdr;
-- drive condition
p[condition].b ← FALSE; -- actually, it could be anything I like
-- drive ram select lines
p[selA][p[ramAdr][a][hi].c].b ← TRUE;
p[selB][p[ramAdr][b][hi].c].b ← TRUE;
p[selC][p[ramAdr][c][hi].c].b ← TRUE;
p[selALow][p[ramAdr][a][low].c].b ← TRUE;
p[selBLow][p[ramAdr][b][low].c].b ← TRUE;
p[selCLow][p[ramAdr][c][low].c].b ← TRUE;
-- set PhA regs muxes
SimpleSel[left, leftSrc];
SimpleSel[right, rightSrc];
SimpleSel[st2A, st2ASrc];
p[pipeRegsSel][st3A][0].b ← ~p[st3AisC].b AND ~rejectBA;  -- s2Bus
p[pipeRegsSel][st3A][1].b ← p[st3AisC].b AND ~rejectBA;  -- cBus
p[pipeRegsSel][field][0].b ← (cAdr=fieldAdr) AND ~rejectBA;
p[pipeRegsSel][r3A][0].b ← ~rejectBA;
p[pipeRegsSel][cBus][0].b ← ~rejectBA;  -- dataIn
p[pipeRegsSel][cBus][1].b ← rejectBA;  -- r3B
-- reset PhB regs muxes
Reset[st2B]; Reset[kReg]; Reset[r2B]; Reset[r3B]; Reset[dataIn];
-- States: cycle carry: before ALU op!!!
IF ~rejectBA AND ~conditionBA THEN carryAB ← carryBA;
-- alu and cc
p[op][0].b ← TRUE;  -- !!!
p[op][1].b ← TRUE;
p[op][2].b ← TRUE;
p[op][3].b ← TRUE;
p[op][4].b ← TRUE;
p[carryIn].b ← OpToCarryIn[selAluOps, carryAB];
-- field unit
p[insert].b ← p[fd][insertFd].b;
p[mask].c ← p[fd][maskFd].c;
p[shift].c ← p[fd][shiftFd].c;
FOR i: NAT IN [0..wordSize+1) DO
p[sh][i].b ← p[fd][shiftFd].c=i;
ENDLOOP;
};
IF p[phB].b THEN {
selAluOps: Dragon.ALUOps ← VAL[p[aluOp].c];
overflow: BOOL ← ((p[carryOut].b#p[res][0].b)#(p[opL][0].b#p[opR][0].b));
lz: BOOL ← (p[carryOut].b#(p[opL][0].b#p[opR][0].b));
il: BOOL ← p[opL].c IN (0..7) OR p[opR].c IN (0..7) OR p[res].c IN (0..7);
-- States: latch reject ASAP
rejectBA ← p[reject].b;
-- drive PBus
p[enWrtPBus].b ← FALSE; -- work on this!!!
-- drive KBus
p[enWrtIFU].b ← FALSE; -- IFU sends addresses and control, so wait
-- drive condition and set carry
p[condition].b ← SELECT Dragon.CondSelects[VAL[p[condSel].c]] FROM
False => FALSE,
EZ => p[zero].b,
LZ => lz,
LE => p[zero].b OR lz,
AddressCheckFault => p[res].c=0,
NE => ~p[zero].b,
GE => ~lz,
GZ => ~(p[zero].b AND lz),
OvFl => overflow,
BC => p[carryOut].b,
IL => il,
NotBC => ~p[carryOut].b,
NotIL => ~il,
ModeFault => TRUE,
ENDCASE => ERROR;
-- ALU and Field Unit: just wait since they are combinatorial and started on PhA
carryBA ← OpToCarryOut[selAluOps, p[carryOut].b, carryBA];
-- lower all select lines
FOR i: NAT IN [0.. nRows) DO
p[selA][i].b ← p[selB][i].b ← p[selC][i].b ← FALSE;
ENDLOOP;
FOR i: NAT IN [0.. sizeSelLow) DO
p[selALow][i].b ← p[selBLow][i].b ← p[selCLow][i].b ← FALSE;
ENDLOOP;
-- set PhB regs muxes
p[pipeRegsSel][st2B][0].b ← TRUE;
p[pipeRegsSel][kReg][0].b ← ~p[reject].b;
p[pipeRegsSel][kReg][1].b ← p[reject].b; -- cAdr ← euMAR
p[pipeRegsSel][r2B][0].b ← ~(p[aluOp].c=bndCheck OR p[aluOp].c=fop);
p[pipeRegsSel][r2B][1].b ← p[aluOp].c=fop;
p[pipeRegsSel][r2B][2].b ← p[aluOp].c=bndCheck;
p[pipeRegsSel][r3B][0].b ← p[res3BisP].b; -- address
p[pipeRegsSel][dataIn][0].b ← p[res3BisP].b; -- data from cache, or junk
-- reset PhA regs muxes
Reset[left]; Reset[right]; Reset[st2A]; Reset[st3A]; Reset[field]; Reset[r3A];
};
}};
END.