EUImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier June 17, 1986 8:06:14 pm PDT
McCreight, May 12, 1986 12:23:08 pm PDT
Bertrand Serlet February 25, 1987 6:11:10 pm PST
Barth, April 19, 1986 5:25:00 pm PST
Last Edited by: Louis Monier April 24, 1987 1:35:31 pm PDT
DIRECTORY CMosB, CoreClasses, CoreCreate, CoreFlat, CoreIO, CoreProperties, Dragon, EU, EUArith, EUInner, EUUtils, PadFrame, Ports, PWCore, Rosemary, Sisyph;
EUImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreCreate, CoreFlat, CoreIO, CoreProperties, EUArith, EUInner, EUUtils, PadFrame, Ports, PWCore, Rosemary
EXPORTS EU =
BEGIN OPEN EU, CoreCreate;
public: Wire ← EUUtils.GenWiresForBonnie[];
EUName: ROPE = Rosemary.Register[roseClassName: "EU", init: EUInit, evalSimple: EUSimple];
AssertionFailed: SIGNAL [message: ROPE] = CODE;
MoreThanOne: PROC [a, b, c, d: BOOLFALSE] RETURNS [BOOLFALSE] ~ {
BtoN: PROC [b: BOOL] RETURNS [NAT] ~ {RETURN[IF b THEN 1 ELSE 0]};
RETURN[BtoN[a]+BtoN[b]+BtoN[c]+BtoN[d]>1];
};
CreateEU: PUBLIC PROC [ typeData: REF EUTypeData ← NIL, fullEU: BOOLFALSE, useCkPt: BOOLFALSE] RETURNS [ cellType: CellType ] = {
props: Properties ← CoreProperties.Props[[$ClusterInfo, typeData]];
SELECT TRUE FROM
~fullEU => cellType ← CoreClasses.CreateUnspecified[public, EUName, props];
fullEU AND ~useCkPt => {
cellType ← EUUtils.Fetch["EU"];
IF cellType=NIL THEN {
cellType ← CreateFullEU[EUUtils.GetContext[], props];
EUUtils.Store["EU", cellType];
}};
ENDCASE => cellType ← CoreIO.RestoreCellType[EUName];
CoreProperties.PutCellTypeProp[cellType, $ClusterInfo, typeData];
Ports.InitPorts[cellType, lc, none, "DPData", "KBus"];
Ports.InitPorts[cellType, c, none, "EUAluOp2AB", "EUCondSel2AB"];
Ports.InitPorts[cellType, b, drive, "EUCondition2B", "DShOut"];
[] ← Rosemary.BindCellType[cellType: cellType, roseClassName: EUName];
[] ← CoreFlat.CellTypeCutLabels[cellType, "EU"];
};
EUInit: Rosemary.InitProc = {
state: EUState ← NEW[EUStateRec -- [ nRegs ] -- ];
{OPEN state;
[Vdd, Gnd, PadVdd, PadGnd, PhA, PhB, DPRejectB, DPData] ←
Ports.PortIndexes[cellType.public, "Vdd", "Gnd", "PadVdd", "PadGnd", "PhA", "PhB", "DPRejectB", "DPData"];
[KBus, EURdFromPBus3AB, EUWriteToPBus3AB, EUAluOp2AB, EUCondSel2AB, EUCondition2B] ←
Ports.PortIndexes[cellType.public, "KBus", "EURdFromPBus3AB", "EUWriteToPBus3AB", "EUAluOp2AB", "EUCondSel2AB", "EUCondition2B"];
[DShA, DShB, DShRd, DShWt, DShIn, DShOut, DHold, DStAd] ←
Ports.PortIndexes[cellType.public, "DShA", "DShB", "DShRd", "DShWt", "DShIn", "DShOut", "DHold", "DStAd"];
data ← NARROW[CoreProperties.GetCellTypeProp[cellType, $ClusterInfo]];
FOR i: NAT IN [0..nRegs) DO ram[i] ← 0 ENDLOOP;
ram[EUUtils.constAdr+1] ← 1;
ram[EUUtils.constAdr+2] ← 2;
ram[EUUtils.constAdr+3] ← 3;
};
stateAny ← state;
};
EUSimple: Rosemary.EvalProc = {
-- shRegB[msb] goes out first
ShiftByOne: PROC [bIn: BOOL, shRegA, shRegB: CARD] RETURNS [newShRegA: CARD] ~ {
newShRegA ← 2*shRegB + (IF bIn THEN 1 ELSE 0); -- very, very ugly
};
Assert: PROC [condition: BOOL, message: ROPENIL] =
{IF NOT condition THEN SIGNAL AssertionFailed[message]};
state: EUState ← NARROW[stateAny];
{OPEN state;
aAdr, bAdr, cAdr: CARD; -- actually, only bytes
lSrc, rSrc, stSrc: NAT;
st3IsC: BOOL;
p[KBus].d ← p[DPData].d ← none;
-- DBus stuff
Assert[NOT MoreThanOne[p[DShRd].b, p[DShWt].b, p[DShA].b, p[DShB].b], "DBus signals in illegal configuration"]; -- breaks the cluster simulation during reset
SELECT TRUE FROM
p[DShRd].b => {
regAd: NAT ← p[DStAd].c;
shRegA ← reg[regAd];
};
p[DShWt].b => {
regAd: NAT ← p[DStAd].c;
reg[regAd] ← shRegB;
};
p[DShA].b => shRegA ← ShiftByOne[p[DShIn].b, shRegA, shRegB];
p[DShB].b => {
shRegB ← shRegA;
p[DShOut].b ← EUArith.EBFLC[shRegB, 0];
};
ENDCASE => NULL;
-- PhA phase. Note that rejectBA alone inhibits almost any state change during PhA
IF p[PhA].b THEN {
cAdrInRAM: CARD;  -- different from cAdr in case of reject
-- This instruction must be the first one of PhA!
-- We select dataIn only in the case of a fetch without reject
cBusVal: CARDIF NOT rejectBA AND readPBusBA
THEN reg[dataIn]
ELSE reg[r3B];
-- Updating the RAM addresses and various control bits; notice the role of reject
[aAdr, bAdr, cAdr, st3IsC, lSrc, rSrc, stSrc] ← EUArith.ExplodeKReg[reg[kReg]];
-- On every PhA with RejectBA the faulty address is saved in ram[euMAR]; the EU generates the appropriate cAdrInRAM when RejectBA is sensed, so the rule is: we always write into the register file!
cAdrInRAM ← IF rejectBA THEN EUUtils.marAdr ELSE cAdr; -- force address on reject
IF cAdr=EUUtils.IFUAdr THEN {p[KBus].d ← drive; p[KBus].lc ← cBusVal};
IF cAdrInRAM IN [EUUtils.stackAdr .. EUUtils.bogusAdr) THEN ram[cAdrInRAM] ← cBusVal
ELSE Assert[FALSE, "EU cAdr out of range"];
-- I don't know who wrote this, so I treat it as a black box (LMM)
IF cAdr # EUUtils.junkAdr THEN {
IF data # NIL AND data.noteStore # NIL AND NOT data.storeNoted THEN {
data.noteStore[data: data.data, reg: cAdrInRAM, value: cBusVal];
data.storeNoted ← TRUE;
};
};
IF ~rejectBA AND ~conditionBA THEN carryAB ← carryBA;
IF ~rejectBA THEN {
IF cAdr=EUUtils.fieldAdr THEN reg[field] ← cBusVal;
reg[left] ← SELECT Dragon.ALULeftSources[VAL[lSrc]] FROM
aBus  => ram[aAdr],
rBus  => reg[r2B],
cBus  => cBusVal,
ENDCASE => ERROR;
reg[right] ← SELECT Dragon.ALURightSources[VAL[rSrc]] FROM
bBus  => ram[bAdr],
rBus  => reg[r2B],
cBus  => cBusVal,
kBus  => p[KBus].lc,
fCtlReg => reg[field],
ENDCASE => ERROR;
reg[st2A] ← SELECT Dragon.Store2ASources[VAL[stSrc]] FROM
bBus   => ram[bAdr],
cBus   => cBusVal,
rBus   => reg[r2B],
ENDCASE => ERROR;
reg[r3A] ← reg[r2B];
reg[st3A] ← IF st3IsC THEN cBusVal ELSE reg[st2B];
p[DPData].d ← drive; -- Send address to Cache only once: the cache latches it.
p[DPData].lc ← reg[r2B];
};
}
ELSE IF data # NIL THEN data.storeNoted ← FALSE;
-- PhiB phase. Most of the computations take place during PhB
IF p[PhB].b THEN {
aluOut, fuOut: CARD; -- temporary
overflow, c32, lz, ez, il: BOOL;
aluOps: Dragon.ALUOps ← VAL[p[EUAluOp2AB].c];
DPRejectB is valid at the end of PhiB but bogus on PhiA, so it must be latched on PhiB.
rejectBA ← p[DPRejectB].b;
readPBusBA ← p[EURdFromPBus3AB].b;
-- Receive RAM addresses and control bits on KBus from IFU
reg[kReg] ← p[KBus].lc;
-- PBus: notice that in case of reject during a store, we keep sending the data even though it is useless; this could be changed if needed.
Assert[NOT (p[EUWriteToPBus3AB].b AND p[EURdFromPBus3AB].b)];
reg[r3B] ← reg[r3A]; -- copy address
reg[dataIn] ← p[DPData].lc; -- latch whatever comes from the pads
-- Driving the PBus in case of a store
IF p[EUWriteToPBus3AB].b THEN {
p[DPData].d ← drive;
p[DPData].lc ← reg[st3A]
};
-- Data pipe
reg[st2B] ← reg[st2A];
-- ALU computation
[aluOut, c32, carryBA] ← EUArith.ALUOperation[aluOps, reg[left], reg[right], carryAB];
-- FU computation
fuOut ← IF aluOps=FOP THEN EUArith.FieldOp[reg[left], reg[st2A], reg[right]] ELSE 0;
-- Now pick up the result
reg[r2B] ← SELECT aluOps FROM
BndChk => reg[left],
FOP => fuOut,
ENDCASE => aluOut;
-- Condition and trap generation
overflow ← ((c32 # EUArith.EBFLC[aluOut, 0]) # (EUArith.EBFLC[reg[left], 0] # EUArith.EBFLC[reg[right], 0]));
lz ← (c32#(EUArith.EBFLC[reg[left], 0]#EUArith.EBFLC[reg[right], 0]));
ez ← aluOut=0;
il ← EUArith.LispTest[reg[left]] OR EUArith.LispTest[reg[right]] OR EUArith.LispTest[aluOut];
conditionBA ← SELECT Dragon.CondSelects[VAL[p[EUCondSel2AB].c]] FROM
False  => FALSE,
EZ   => ez,
LZ   => lz, -- VSub<0
LE   => ez OR lz, -- VSub<=0,
NE  => ~ez,
GE   => ~lz, -- VSub>=0
GZ   => ~(ez OR lz), -- VSub>0,
OvFl  => overflow,
BC   => ~c32,
IL   => il, -- the 3 high-order bits must be the same for both operands and result
NotBC  => c32,
NotIL  => ~il,
ModeFault  => TRUE,
ENDCASE => ERROR Rosemary.Stop["Invalid EUCondition2B Code"];
p[EUCondition2B].b ← conditionBA;
};
}};
globalPos: NAT ← 0; -- add the increment, then put the pad
SetFirst: PROC [pos: NAT] = {globalPos ← pos};
Next: PROC [] RETURNS [NAT] = {RETURN[Move[1]]};
Move: PROC [delta: NAT] RETURNS [NAT] = {
globalPos ← globalPos+delta;
RETURN[globalPos]};
CreateFullEU: PROC [cx: Sisyph.Context, props: Properties ← NIL] RETURNS [cellType: CellType] = {
vSize: NAT = 41;
hSize: NAT = 50;
left: NAT = 0;
bottom: NAT = left+vSize; -- 41
right: NAT = bottom+hSize; -- 91
top: NAT = right+vSize;  -- 132
pads: PadFrame.Pads ← NIL;
dpData: Wire ← FindWire[public, "DPData"];
aluOp: Wire ← FindWire[public, "EUAluOp2AB"];
condSel: Wire ← FindWire[public, "EUCondSel2AB"];
kBus: Wire ← FindWire[public, "KBus"];
dStAd: Wire ← FindWire[public, "DStAd"];
onlyInternal: Wire ← WireList[LIST[
"phA", "phB", "nPhA", "nPhB",
"enWrtPBusPhA", "enWrtPBusPhB", "enWrtIFUPhA", "enWrtIFUPhB", "condition",
"writePBus", "readPBus3AB", "dpRejectB", Seq["aluOp", 4], Seq["condSel", 4],
"shiftA", "shiftB", "read", "write", "shIn", "shOut", "hold", Seq["dStateAd", 4],
Seq["fromIFU", 32], Seq["toIFU", 32], Seq["toPBus", 32], Seq["fromPBus", 32],
"reject" ]]; -- just for routing
-- Left side
SetFirst[left+10];
pads ← PadFrame.AddPad[pads, "DShA", $In, Next[], ["toChip", "shiftA"]]; -- new: 11
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Next[]];
pads ← PadFrame.AddPad[pads, "DShB", $In, Next[], ["toChip", "shiftB"]];
pads ← PadFrame.AddPad[pads, "DShRd", $In, Next[], ["toChip", "read"]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Next[]];
pads ← PadFrame.AddPad[pads, "DShWt", $In, Next[], ["toChip", "write"]];
pads ← PadFrame.AddPad[pads, "DShIn", $In, Next[], ["toChip", "shIn"]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Next[]];
pads ← PadFrame.AddPad[pads, "DShOut", $Out, Next[], ["fromChip", "shOut"]];
pads ← PadFrame.AddPad[pads, "DHold", $In, Next[], ["toChip", "hold"]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Next[]];
pads ← PadFrame.AddPad[pads, dStAd[0], $In, Next[], ["toChip", "dStateAd[0]"]];
pads ← PadFrame.AddPad[pads, dStAd[1], $In, Next[], ["toChip", "dStateAd[1]"]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Next[]];
pads ← PadFrame.AddPad[pads, dStAd[2], $In, Next[], ["toChip", "dStateAd[2]"]];
pads ← PadFrame.AddPad[pads, dStAd[3], $In, Next[], ["toChip", "dStateAd[3]"]];
pads ← PadFrame.AddPad[pads, NIL, $Copyright, Next[]];
pads ← PadFrame.AddPad[pads, NIL, $Logo, Next[]];
pads ← PadFrame.AddPad[pads, NIL, $Name, Next[]];
-- Bottom side: msb(0) on the left
SetFirst[bottom];  -- 41
FOR i: NAT IN [0..16) DO
index: NAT ← 2*i;
pads ← PadFrame.AddPad[pads, dpData[index], $IOTst, Move[2],  -- s on 43
["toChip", Index["fromPBus", index]],
["fromChip", Index["toPBus", index]],
["enWA", "enWrtPBusPhA"],
["enWB", "enWrtPBusPhB"]];
pads ← PadFrame.AddPad[pads, dpData[index+1], $IOTst, Next[],  -- s on 44
["toChip", Index["fromPBus", index+1]],
["fromChip", Index["toPBus", index+1]],
["enWA", "enWrtPBusPhA"],
["enWB", "enWrtPBusPhB"]];
ENDLOOP;
SetFirst[bottom];  -- 42
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Next[]];   -- v on 42
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Move[3]];
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Move[3]];
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Move[3]];
-- Right side: msb(0) on the left
SetFirst[right+8];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Next[]];  -- v on 100
pads ← PadFrame.AddPad[pads, "DPRejectB", $In, Next[], ["toChip", "dpRejectB"]];
pads ← PadFrame.AddPad[pads, "PhA", $Clk, Next[], ["Clock", "phA"], ["nClock", "nPhA"]];
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Next[]];
pads ← PadFrame.AddPad[pads, "PhB", $Clk, Next[], ["Clock", "phB"], ["nClock", "nPhB"]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Next[]];  -- former VRef
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Next[]];
pads ← PadFrame.AddPad[pads, "EUCondition2B", $Out, Next[], ["fromChip", "condition"]];
pads ← PadFrame.AddPad[pads, "EURdFromPBus3AB", $In, Next[], ["toChip", "readPBus3AB"]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Next[]];
pads ← PadFrame.AddPad[pads, "EUWriteToPBus3AB", $In, Next[], ["toChip", "writePBus"]];
pads ← PadFrame.AddPad[pads, aluOp[0], $In, Next[], ["toChip", "aluOp[0]"]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Next[]];
pads ← PadFrame.AddPad[pads, aluOp[1], $In, Next[], ["toChip", "aluOp[1]"]];
pads ← PadFrame.AddPad[pads, aluOp[2], $In, Next[], ["toChip", "aluOp[2]"]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Next[]];
pads ← PadFrame.AddPad[pads, aluOp[3], $In, Next[], ["toChip", "aluOp[3]"]];
pads ← PadFrame.AddPad[pads, condSel[0], $In, Next[], ["toChip", "condSel[0]"]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Next[]];
pads ← PadFrame.AddPad[pads, condSel[1], $In, Next[], ["toChip", "condSel[1]"]];
pads ← PadFrame.AddPad[pads, condSel[2], $In, Next[], ["toChip", "condSel[2]"]];
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Next[]];
pads ← PadFrame.AddPad[pads, condSel[3], $In, Next[], ["toChip", "condSel[3]"]];
-- Top side
SetFirst[top]; -- 132
FOR i: NAT IN [0..16) DO
index: NAT ← 31-2*i;
pads ← PadFrame.AddPad[pads, kBus[index], $IOTst, Move[2],  -- s on 134
["toChip", Index["fromIFU", index]],
["fromChip", Index["toIFU", index]],
["enWA", "enWrtIFUPhA"],
["enWB", "enWrtIFUPhB"]]; -- EU never write on KBus during PhB
pads ← PadFrame.AddPad[pads, kBus[index-1], $IOTst, Next[],  -- s on 135
["toChip", Index["fromIFU", index-1]],
["fromChip", Index["toIFU", index-1]],
["enWA", "enWrtIFUPhA"],
["enWB", "enWrtIFUPhB"]];
ENDLOOP;
SetFirst[top]; -- 132
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Next[]];  -- v on 133
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Move[3]];
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Move[3]];
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadGnd", $PadGnd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "Vdd", $Vdd, Move[3]];
pads ← PadFrame.AddPad[pads, "PadVdd", $PadVdd, Move[3]];
pads ← PadFrame.AddPad[pads, "Gnd", $Gnd, Move[3]];
cellType ← PadFrame.CreatePadFrame[
public: public,
onlyInternal: onlyInternal,
innerInstance: Instance[PWCore.RotateCellType[EUInner.CreateEUInner[cx], $Rot90],
["dStateAd", "dStateAd"], ["hold", "hold"], ["reject", "reject"] ],
pads: pads,
params: [
nbPadsX: hSize,
nbPadsY: vSize,
horizLayer: "metal2",
vertLayer: "metal",
centerDisplacement: [-200*CMosB.lambda, 0]],
name: EUName,
props: props
];
};
END.