EUImpl.Mesa
created by RoseTranslate 3.1.3 of September 5, 1985 12:14:34 pm PDT
created from EU.Rose of March 11, 1986 12:22:37 pm PST
created for McCreight.pa
created at March 11, 1986 12:24:42 pm PST
DIRECTORY
RoseTypes, EU, RoseCreate, Rope, DragOpsCross, LizardRosemary, Atom, Basics, ClusterParams, DragonRosemary, DragonRoseExtras, IO, BitOps, RoseEvents, RoseRun, RoseVectors, DragOpsCrossUtils, ViewerIO, SwitchTypes, Dragon, PrintTV, AMBridge, NumTypes;
EUImpl:
CEDAR
PROGRAM
IMPORTS RoseCreate, Atom, Basics, ClusterParams, DragonRosemary, DragonRoseExtras, IO, BitOps, RoseEvents, RoseRun, RoseTypes, RoseVectors, DragOpsCrossUtils, ViewerIO, PrintTV, AMBridge, NumTypes
EXPORTS EU
=
BEGIN
OPEN
RoseTypes, EU;
Signal Type decls
ALUOps: TYPE = Dragon.ALUOps;
CondSelects: TYPE = Dragon.CondSelects;
RegisterCells:
PROC =
BEGIN
EUCompute ← RoseCreate.RegisterCellType[name: "EUCompute",
expandProc: NIL,
ioCreator: CreateEUComputeIO, driveCreator: CreateEUComputeDrive, initializer: InitializeEUCompute,
evals: [EvalSimple: EUComputeEvalSimple],
tests: LIST[],
ports: CreateEUComputePorts[]
];
END;
otherss: SymbolTable ← RoseCreate.GetOtherss["EU.partsAssertions"];
explicitly requested CEDAR:
fieldAdr: INTEGER = DragOpsCross.ProcessorRegister[euField].ORD;
marAdr: INTEGER = DragOpsCross.ProcessorRegister[euMAR].ORD;
Remark: PROC [ message: Rope.ROPE ] = {RoseRun.DisableableStop[Remark, message]};
FieldOp:
PROC[aluLeft, aluRight, fieldDesc: Dragon.HexWord]
RETURNS [result:Dragon.HexWord] =
BEGIN OPEN DragOpsCross, DragOpsCrossUtils;
fd: FieldDescriptor = CardToFieldDescriptor[fieldDesc MOD 65536];
Left: Word = CardToWord[aluLeft];
Right: Word = CardToWord[aluRight];
out: Word;
From here on, the code is copied from LizardHeartImpl, which in turn purports to be identical to the manual.
shifter: Word = DoubleWordShiftLeft[Left, Right, fd.shift];
The shifter output has the input double word shifted left by fd.shift bits
mask: Word ← SingleWordShiftRight[OnesWord, 32-fd.mask];
The default mask has fd.mask 1s right-justified in the word
IF fd.insert
THEN mask ← DragAnd[mask, SingleWordShiftLeft[OnesWord, fd.shift]];
fd.insert => clear rightmost fd.shift bits of the mask
out ← DragAnd[mask, shifter];
1 bits in the mask select the shifter output
IF fd.insert
THEN out ← DragOr[out, DragAnd[DragNot[mask], Right]];
fd.backR => 0 bits in the mask select bits from Right to OR in to the result
result ← WordToCard[out];
END;
Returns a+b+carry and c32, where a and b are considered to be signed numbers
DoubleADD:
PROC[al, bl: Dragon.HexWord, carry:
BOOL]
RETURNS [sl: Dragon.HexWord, c32: BOOL] = {
Xor:
PROC[x, y:
BOOL]
RETURNS [z:
BOOL] =
{RETURN[(x AND NOT y) OR (y AND NOT x)]};
ai, bi: BOOL;
s: BOOL ← FALSE;
c: BOOL ← carry;
i: INTEGER;
sum: BitOps.BitDWord ← [0,0];
FOR i
IN [1..32]
DO
ai ← EBFL[al, 32-i];
bi ← EBFL[bl, 32-i];
s ← Xor[ai, Xor[bi, c]];
c ← (ai AND bi) OR (bi AND c) OR (ai AND c);
sum ← BitOps.IBID[s, sum, 32, 32-i];
ENDLOOP;
RETURN[DragonRoseExtras.LFD[sum], c]};
DoubleNOT:
PROC[a: Dragon.HexWord]
RETURNS [c: Dragon.HexWord] = {
c ← LOOPHOLE[Basics.DoubleNot[LOOPHOLE[a]]]
};
WordOp:
PROC[op:{or, and, xor}, left, right:Dragon.HexWord ← 0]
RETURNS[result:Dragon.HexWord] = {
RETURN[DragonRoseExtras.
LFD[
SELECT op
FROM
or => BitOps.DOR [DragonRoseExtras.LTD[left], DragonRoseExtras.LTD[right]],
and => BitOps.DAND [DragonRoseExtras.LTD[left], DragonRoseExtras.LTD[right]],
xor => BitOps.DXOR [DragonRoseExtras.LTD[left], DragonRoseExtras.LTD[right]],
ENDCASE => ERROR]] };
ELispFL:
PROC[word: Dragon.HexWord]
RETURNS[[0..7]] = {
RETURN[ BitOps.ECFD[DragonRoseExtras.LTD[word], 32, 0, 3]] };
EBFL:
PROC[word: Dragon.HexWord, index:
CARDINAL]
RETURNS[
BOOL] = {
RETURN[ BitOps.EBFD[DragonRoseExtras.LTD[word], 32, index]] };
DblShiftRt:
PROC[msb:
BOOL, ltIn, rtIn: Dragon.HexWord]
RETURNS[ltOut, rtOut: Dragon.HexWord] =
{rtOut ← ShiftRt[EBFL[ltIn, 31], rtIn]; ltOut ← ShiftRt[msb, ltIn]};
ShiftRt:
PROC[msb:
BOOL, w: Dragon.HexWord]
RETURNS[r: Dragon.HexWord] =
{r𡤍ragonRoseExtras.LFD[BitOps.IBID[msb, BitOps.MDTD[DragonRoseExtras.LTD[w],32,0,31,[0,0],32,1,31],32,0]]};
DblShiftLt:
PROC[ltIn, rtIn: Dragon.HexWord, lsb:
BOOL]
RETURNS[cry: BOOL, ltOut, rtOut: Dragon.HexWord] =
{cry ← EBFL[ltIn,0]; ltOut ← ShiftLt[ltIn, EBFL[rtIn, 0]]; rtOut ← ShiftLt[rtIn, lsb]};
ShiftLt:
PROC[w: Dragon.HexWord, lsb:
BOOL]
RETURNS[r: Dragon.HexWord] =
{r𡤍ragonRoseExtras.LFD[BitOps.IBID[lsb, BitOps.MDTD[DragonRoseExtras.LTD[w],32,1,31,[0,0],32,0,31],32,31]]};
vectorStream: IO.STREAM ← NIL;
SeeSettle:
PROC [event:
ATOM, watched, watcherData, arg:
REF
ANY]
--RoseEvents.NotifyProc-- = {
cell: RoseTypes.Cell = NARROW[watcherData];
IF ClusterParams.clusterPanel.enaEULog
THEN {
IF vectorStream =
NIL
THEN {
vectorStream ← ViewerIO.CreateViewerStreams["EU Vectors"].out;
RoseVectors.WriteHeader[vectorStream, cell];
};
RoseVectors.WriteVector[vectorStream, cell];
}
};
EUCompute: PUBLIC CellType;
CreateEUComputePorts: PROC RETURNS [ports: Ports] = {ports ← RoseCreate.PortsFromFile["EU.EUCompute.rosePorts"]};
EUComputeSwitchIORef: TYPE = REF EUComputeSwitchIORec;
EUComputeSwitchIORec:
TYPE =
RECORD [
DPData: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,DPRejectB: SwitchTypes.SwitchVal
,PhA: SwitchTypes.SwitchVal
,PhB: SwitchTypes.SwitchVal
,Vdd: SwitchTypes.SwitchVal
,Gnd: SwitchTypes.SwitchVal
,PadVdd: SwitchTypes.SwitchVal
,PadGnd: SwitchTypes.SwitchVal
,KBus: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,EUSt3AisCBus2BA: SwitchTypes.SwitchVal
,EURes3BisPBus3AB: SwitchTypes.SwitchVal
,EUWriteToPBus3AB: SwitchTypes.SwitchVal
,EUAluOp2AB: PACKED ARRAY [0 .. 4) OF SwitchTypes.SwitchVal
,EUCondSel2AB: PACKED ARRAY [0 .. 4) OF SwitchTypes.SwitchVal
,EUCondition2B: SwitchTypes.SwitchVal
,DShiftAB: SwitchTypes.SwitchVal
,DExecuteAB: SwitchTypes.SwitchVal
,DNSelectAB: SwitchTypes.SwitchVal
,DHoldAB: SwitchTypes.SwitchVal
,DDataInAB: SwitchTypes.SwitchVal
,DDataOutAB: SwitchTypes.SwitchVal
,CBusResult3BA: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,ALULeft2AB: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,ALURight2AB: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,Store2AB: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
];
EUComputeSimpleIORef: TYPE = REF EUComputeSimpleIORec;
EUComputeSimpleIORec:
TYPE =
RECORD [
DPData: ARRAY [0..2) OF CARDINAL
,fill1: [0 .. 32767],
DPRejectB: BOOLEAN
,fill2: [0 .. 32767],
PhA: BOOLEAN
,fill3: [0 .. 32767],
PhB: BOOLEAN
,fill4: [0 .. 32767],
Vdd: BOOLEAN
,fill5: [0 .. 32767],
Gnd: BOOLEAN
,fill6: [0 .. 32767],
PadVdd: BOOLEAN
,fill7: [0 .. 32767],
PadGnd: BOOLEAN
,KBus: ARRAY [0..2) OF CARDINAL
,fill9: [0 .. 32767],
EUSt3AisCBus2BA: BOOLEAN
,fill10: [0 .. 32767],
EURes3BisPBus3AB: BOOLEAN
,fill11: [0 .. 32767],
EUWriteToPBus3AB: BOOLEAN
,fill12: [0 .. 4095],
EUAluOp2AB: ALUOps
,fill13: [0 .. 4095],
EUCondSel2AB: CondSelects
,fill14: [0 .. 32767],
EUCondition2B: BOOLEAN
,fill15: [0 .. 32767],
DShiftAB: BOOLEAN
,fill16: [0 .. 32767],
DExecuteAB: BOOLEAN
,fill17: [0 .. 32767],
DNSelectAB: BOOLEAN
,fill18: [0 .. 32767],
DHoldAB: BOOLEAN
,fill19: [0 .. 32767],
DDataInAB: BOOLEAN
,fill20: [0 .. 32767],
DDataOutAB: BOOLEAN
,CBusResult3BA: ARRAY [0..2) OF CARDINAL
,ALULeft2AB: ARRAY [0..2) OF CARDINAL
,ALURight2AB: ARRAY [0..2) OF CARDINAL
,Store2AB: ARRAY [0..2) OF CARDINAL
];
EUComputeDriveRef: TYPE = REF EUComputeDriveRec;
EUComputeDriveRec: TYPE = RECORD [driveRecordInitialPadding: DriveTagType, drive: PACKED ARRAY EUComputePort OF DriveLevel];
EUComputePort:
TYPE = {
DPData, DPRejectB, PhA, PhB, Vdd, Gnd, PadVdd, PadGnd, KBus, EUSt3AisCBus2BA, EURes3BisPBus3AB, EUWriteToPBus3AB, EUAluOp2AB, EUCondSel2AB, EUCondition2B, DShiftAB, DExecuteAB, DNSelectAB, DHoldAB, DDataInAB, DDataOutAB, CBusResult3BA, ALULeft2AB, ALURight2AB, Store2AB, EUComputePortTypePad25, EUComputePortTypePad26, EUComputePortTypePad27};
CreateEUComputeIO:
PROC [ct: CellType, switch:
BOOL]
RETURNS [ioAsAny:
REF
ANY]
--IOCreator-- = {
ioAsAny ← IF switch THEN NEW[EUComputeSwitchIORec] ELSE NEW[EUComputeSimpleIORec];
};
CreateEUComputeDrive:
PROC [ct: CellType]
RETURNS [driveAsAny:
REF
ANY]
--DriveCreator-- = {
driveAsAny ← NEW[EUComputeDriveRec];
};
EUComputeStateRef: TYPE = REF EUComputeStateRec;
EUComputeStateRec:
TYPE =
RECORD [
Pipeline registers
aluLeft, aluRight, aluOut: Dragon.HexWord,
result2BA, result3AB, cBusResult3BA: Dragon.HexWord,
store2AB, store2BA, store3AB: Dragon.HexWord,
RAM, RAM addresses and various aliased registers
The RAM is organised as follows (Ref DragOpsCross):
registers 0 through 127 constitute the stack
128: euJunk i.e. no write
129: euToKBus, write result to KBus
130: euMAR
131: euField
132 through 143 are constants registers
144 through 159 are auxilliary registers
Any aAdr larger than 160 is illegal
aAdr, bAdr, cAdr: Dragon.HexByte,
cIsField: BOOL,
EUAluLeftSrc1BA: Dragon.ALULeftSources,
EUAluRightSrc1BA: Dragon.ALURightSources,
EUStore2ASrc1BA: Dragon.Store2ASources,
ram: ARRAY Dragon.HexByte OF Dragon.HexWord,
field: Dragon.HexWord, -- a copy is kept as RAM[fieldAdr], another copy is in the field unit. Any write is performed to both physical locations, any read is from the most convenient location.
Bits and pieces for the ALU and the Field Unit
carryAB, carryBA: BOOL, -- carryBA is the output of the adder modified by the opcode of the previous operation and latched if no trap; carryAB is a copy of carryBA if there is no reject or trap.
conditionB: BOOL,
Other pieces from the Control pipeline
rejectBA: BOOL -- a copy of DPRejectB stable during PhiA
];
InitializeEUCompute: Initializer = {
drive: EUComputeDriveRef ← NARROW[cell.realCellStuff.newDriveAsAny];
sw: EUComputeSwitchIORef ← NARROW[cell.realCellStuff.switchIO];
newIO: EUComputeSimpleIORef ← NARROW[cell.realCellStuff.newIO];
state: EUComputeStateRef ← NEW[EUComputeStateRec];
cell.realCellStuff.state ← state;
BEGIN
OPEN drive, newIO, state;
RoseEvents.AddWatcher[
event: $Settled,
watcher: [SeeSettle, cell],
watched: cell.sim];
END;
};
EUComputeEvalSimple: SimpleEval =
BEGIN
drive: EUComputeDriveRef ← NARROW[cell.realCellStuff.newDriveAsAny];
sw: EUComputeSwitchIORef ← NARROW[cell.realCellStuff.switchIO];
newIO: EUComputeSimpleIORef ← NARROW[cell.realCellStuff.newIO];
state: EUComputeStateRef ←
NARROW[cell.realCellStuff.state];
BEGIN
OPEN drive, newIO, state;
drive[DPData] ← ignore;
drive[KBus] ← ignore;
PhiA phase. Note that rejectBA alone inhibits almost any state change during PhiA
IF PhA
THEN {
cReg: DragOpsCross.ProcessorRegister;
DragonRosemary.Assert[aAdr>=0 AND aAdr<164];
No simultaneous bypass control signals on
IF NOT (rejectBA OR EUCondition2B) THEN {carryAB ← carryBA};
IF
NOT rejectBA
THEN {
SELECT EUAluLeftSrc1BA
FROM
aBus => aluLeft ← (
SELECT aAdr
FROM
DragOpsCross.ProcessorRegister[euConstant].ORD => 0,
ENDCASE => ram[aAdr] -- watch out for illegal addresses
);
rBus => aluLeft ← result2BA;
cBus => aluLeft ← cBusResult3BA;
ENDCASE => DragonRosemary.Assert[FALSE];
SELECT EUAluRightSrc1BA
FROM
bBus => aluRight ← (
SELECT bAdr
FROM
DragOpsCross.ProcessorRegister[euConstant].ORD => 0,
ENDCASE => ram[bAdr] -- watch out for illegal addresses
);
rBus => aluRight ← result2BA;
cBus => aluRight ← cBusResult3BA;
kBus => aluRight ← DragonRoseExtras.LFD[KBus];
fCtlReg => aluRight ← field;
ENDCASE => DragonRosemary.Assert[FALSE];
SELECT EUStore2ASrc1BA
FROM
bBus => store2AB ← (
SELECT bAdr
FROM
DragOpsCross.ProcessorRegister[euConstant].ORD => 0,
ENDCASE => ram[bAdr] -- watch out for illegal addresses
);
cBus => store2AB ← cBusResult3BA;
rBus => store2AB ← result2BA;
ENDCASE => DragonRosemary.Assert[FALSE];
result3AB ← result2BA;
Always send address to Cache during PhiA
drive[DPData] ← drive;
DPData ← DragonRoseExtras.LTD[result2BA];
store3AB ←
SELECT EUSt3AisCBus2BA
FROM
TRUE => cBusResult3BA,
ENDCASE => store2BA;
IF
NOT rejectBA
AND cIsField
THEN field ← cBusResult3BA;
ALULeft2AB ← DragonRoseExtras.LTD[aluLeft];
ALURight2AB ← DragonRoseExtras.LTD[aluRight];
Store2AB ← DragonRoseExtras.LTD[store2AB];
};
-- On every PhA with RejectBA the faulty address is saved in ram[euMAR]; the EU generates the appropriate cAdr when RejectBA is sensed, so the rule is: we always write into the register file! (Q: what about euToKBus? LMM)
SELECT (cReg ←
VAL[cAdr])
FROM
IN [euStack .. euJunk), euMAR,
IN [euField .. euBogus) =>
ram[cAdr] ← cBusResult3BA;
euJunk => NULL;
euToKBus => {
-- don't mind reject???
drive[KBus] ← drive;
KBus ← DragonRoseExtras.LTD[cBusResult3BA];
};
ENDCASE => DragonRosemary.Assert[FALSE, "EU cAdr out of range"];
};
PhiB phase. Most of the computations take place during PhiB
IF PhB
THEN {
c32, cx: BOOL;
rejectBA ← DPRejectB;
DPRejectB is valid at the end of PhiB but bogus during PhiA, so it must be latched at the end of PhiB. A current problem is that the source for cBusResult3BA depends upon DPRejectB, and the choice is made during the same PhiB as it is received. So this statement has to be first.
Updating the RAM addresses
aAdr ← BitOps.ECFD[KBus, 32, Dragon.aRegKBusPos, 8];
bAdr ← BitOps.ECFD[KBus, 32, Dragon.bRegKBusPos, 8];
cAdr ←
IF rejectBA
THEN DragOpsCross.ProcessorRegister[euMAR].
ORD
ELSE BitOps.ECFD[KBus, 32, Dragon.cRegKBusPos, 8];
cIsField ← BitOps.EBFD[KBus, 32, 24];
EUAluLeftSrc1BA ← VAL[BitOps.ECFD[KBus, 32, 25, 2]];
EUAluRightSrc1BA ← VAL[BitOps.ECFD[KBus, 32, 27, 3]];
EUStore2ASrc1BA ← VAL[BitOps.ECFD[KBus, 32, 30, 2]];
PBus: notice that in case of reject during a store, we keep sending the data even though it is useless
DragonRosemary.Assert[NOT (EUWriteToPBus3AB AND EURes3BisPBus3AB)];
SELECT
TRUE
FROM
EUWriteToPBus3AB => {
-- store in progress
drive[DPData] ← drive;
DPData ← DragonRoseExtras.LTD[store3AB]; -- send data to Cache (Store)
cBusResult3BA ← result3AB};
save the address in cBusResult3BA, done normally since NOT EURes3BisPBus3AB;
ENDCASE => {
-- either a fetch, an op, or a move in progress
IF rejectBA
-- Fetch with reject => save address in cBusResult3BA and don't listen to IFU
THEN cBusResult3BA ← result3AB
ELSE
-- Fetch without reject --
IF EURes3BisPBus3AB
THEN {
cBusResult3BA ← DragonRoseExtras.LFD[DPData];}
ELSE cBusResult3BA ← result3AB}; -- op or move ;
Data pipe
store2BA ← store2AB;
Alu and Field Unit computation
Set Default values of state
carryBA ← carryAB;
SELECT EUAluOp2AB
FROM
SAdd => {
[aluOut, c32] ← DoubleADD[aluLeft, aluRight, carryAB];
result2BA ← aluOut;
carryBA ← FALSE};
SSub => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], NOT carryAB];
c32 ← NOT cx;
result2BA ← aluOut;
carryBA ← FALSE};
UAdd => {
[aluOut, c32] ← DoubleADD[aluLeft, aluRight, carryAB];
result2BA ← aluOut;
carryBA ← c32};
USub => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], NOT carryAB];
c32 ← NOT cx;
result2BA ← aluOut;
carryBA ← c32};
VAdd, VAdd2 => {
[aluOut, c32] ← DoubleADD[aluLeft, aluRight, FALSE];
result2BA ← aluOut};
VSub => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], TRUE];
c32 ← NOT cx;
result2BA ← aluOut};
LAdd => {
[aluOut, c32] ← DoubleADD[aluLeft, aluRight, FALSE];
result2BA ← aluOut;
carryBA ← FALSE};
LSub => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], TRUE];
c32 ← NOT cx;
result2BA ← aluOut;
carryBA ← FALSE};
FOP => {
result2BA ← aluOut ← FieldOp[aluLeft, store2AB, aluRight]};
And => {
result2BA ← aluOut ← WordOp[and, aluLeft, aluRight]};
Or => {
result2BA ← aluOut ← WordOp[or, aluLeft, aluRight]};
Xor => {
result2BA ← aluOut ← WordOp[xor, aluLeft, aluRight]};
BndChk => {
[aluOut, cx] ← DoubleADD[aluLeft, DoubleNOT[aluRight], TRUE];
c32 ← NOT cx;
result2BA ← aluLeft};
ENDCASE => ERROR Stop["Invalid ALU Operation"];
Condition and trap generation
conditionB ←
SELECT EUCondSel2AB
FROM
False => FALSE,
EZ => aluOut=0, -- aluOut=0
LZ => (c32 # (EBFL[aluLeft, 0] # EBFL[aluRight, 0])), -- VSub<0
LE => (aluOut=0) OR (c32 # (EBFL[aluLeft, 0] # EBFL[aluRight, 0])), -- VSub<=0,
AddressCheckFault => aluOut < DragOpsCross.KernalLimit,
NE => aluOut#0, -- aluOut#0
GE => NOT (c32 # (EBFL[aluLeft, 0] # EBFL[aluRight, 0])), -- VSub>=0
GZ => NOT ((aluOut=0) OR (c32 # (EBFL[aluLeft, 0] # EBFL[aluRight, 0]))), -- VSub>0
OvFl => ((c32 # EBFL[aluOut, 0]) # (EBFL[aluLeft, 0] # EBFL[aluRight, 0])),
BC => NOT c32,
IL => (ELispFL[aluLeft] IN (0..7) ) OR
(ELispFL[aluRight] IN (0..7) ) OR
(ELispFL[aluOut] IN (0..7) ),
NotBC => c32,
NotIL => NOT ((ELispFL[aluLeft] IN (0..7) ) OR
(ELispFL[aluRight] IN (0..7) ) OR
(ELispFL[aluOut] IN (0..7) )),
ModeFault => TRUE,
ENDCASE => ERROR Stop["Invalid EUCondition2B Code"];
EUCondition2B ← conditionB;
CBusResult3BA ← DragonRoseExtras.LTD[cBusResult3BA];
};
END;
END;
OldEULogger: TYPE = RECORD [args: EULoggerArgs, ct: CellType];
oldEULogger: LIST OF OldEULogger ← NIL;
EULogger:
PUBLIC
PROC [args: EULoggerArgs]
RETURNS [ct: CellType]
= BEGIN
FOR old:
LIST
OF OldEULogger ← oldEULogger, old.rest
WHILE old #
NIL
DO
IF old.first.args = args THEN RETURN [old.first.ct]
ENDLOOP;
ct ← RoseCreate.RegisterCellType[name: EULoggerName[args],
expandProc: NIL,
ioCreator: CreateEULoggerIO, driveCreator: CreateEULoggerDrive, initializer: InitializeEULogger,
evals: [EvalSimple: EULoggerEvalSimple],
tests: LIST[],
ports: CreateEULoggerPorts[args]
,
typeData: NEW [EULoggerArgs ← args]];
oldEULogger ← CONS[[args, ct], oldEULogger];
END;
EULoggerName:
PROC [args: EULoggerArgs]
RETURNS [name:
ROPE] = {
to: IO.STREAM ← IO.ROS[]; to.PutRope["EULogger"];
TRUSTED {PrintTV.Print[tv: AMBridge.TVForReferent[NEW [EULoggerArgs ← args]], put: to, depth: 2]};
name ← IO.RopeFromROS[to]};
CreateEULoggerPorts: PROC [args: EULoggerArgs] RETURNS [ports: Ports] = {ports ← RoseCreate.PortsFromFile["EU.EULogger.rosePorts"]};
EULoggerSwitchIORef: TYPE = REF EULoggerSwitchIORec;
EULoggerSwitchIORec:
TYPE =
RECORD [
KBus: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,ALULeft2AB: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,ALURight2AB: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,Store2AB: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,CBusResult3BA: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,DPRejectB: SwitchTypes.SwitchVal
,ResetAB: SwitchTypes.SwitchVal
,PhA: SwitchTypes.SwitchVal
,PhB: SwitchTypes.SwitchVal
];
EULoggerSimpleIORef: TYPE = REF EULoggerSimpleIORec;
EULoggerSimpleIORec:
TYPE =
RECORD [
KBus: ARRAY [0..2) OF CARDINAL
,ALULeft2AB: ARRAY [0..2) OF CARDINAL
,ALURight2AB: ARRAY [0..2) OF CARDINAL
,Store2AB: ARRAY [0..2) OF CARDINAL
,CBusResult3BA: ARRAY [0..2) OF CARDINAL
,fill5: [0 .. 32767],
DPRejectB: BOOLEAN
,fill6: [0 .. 32767],
ResetAB: BOOLEAN
,fill7: [0 .. 32767],
PhA: BOOLEAN
,fill8: [0 .. 32767],
PhB: BOOLEAN
];
EULoggerDriveRef: TYPE = REF EULoggerDriveRec;
EULoggerDriveRec: TYPE = RECORD [driveRecordInitialPadding: DriveTagType, drive: PACKED ARRAY EULoggerPort OF DriveLevel];
EULoggerPort:
TYPE = {
KBus, ALULeft2AB, ALURight2AB, Store2AB, CBusResult3BA, DPRejectB, ResetAB, PhA, PhB, EULoggerPortTypePad9, EULoggerPortTypePad10, EULoggerPortTypePad11};
CreateEULoggerIO:
PROC [ct: CellType, switch:
BOOL]
RETURNS [ioAsAny:
REF
ANY]
--IOCreator-- = {
args:
REF EULoggerArgs ←
NARROW[ct.typeData];
{OPEN args;
ioAsAny ← IF switch THEN NEW[EULoggerSwitchIORec] ELSE NEW[EULoggerSimpleIORec];
};
};
CreateEULoggerDrive:
PROC [ct: CellType]
RETURNS [driveAsAny:
REF
ANY]
--DriveCreator-- = {
args:
REF EULoggerArgs ←
NARROW[ct.typeData];
{OPEN args;
driveAsAny ← NEW[EULoggerDriveRec];
};
};
EULoggerStateRef: TYPE = REF EULoggerStateRec;
EULoggerStateRec:
TYPE =
RECORD [
phALast: BOOL,
cAdr3BA: DragOpsCross.ProcessorRegister
];
InitializeEULogger: Initializer = {
args:
REF EULoggerArgs ←
NARROW [cell.type.typeData];
{OPEN args;
state: EULoggerStateRef ← NEW[EULoggerStateRec];
cell.realCellStuff.state ← state;
};
};
EULoggerEvalSimple: SimpleEval =
BEGIN
args: REF EULoggerArgs ← NARROW[cell.type.typeData];
drive: EULoggerDriveRef ← NARROW[cell.realCellStuff.newDriveAsAny];
sw: EULoggerSwitchIORef ← NARROW[cell.realCellStuff.switchIO];
newIO: EULoggerSimpleIORef ← NARROW[cell.realCellStuff.newIO];
state: EULoggerStateRef ←
NARROW[cell.realCellStuff.state];
BEGIN
OPEN drive, newIO, args, state;
IF ResetAB
THEN Atom.PutProp[$Cluster, $RegStores,
NIL];
IF PhA
AND
NOT phALast
THEN {
phALast ← TRUE;
SELECT cAdr3BA
FROM
euJunk, euBogus => NULL;
ENDCASE => Atom.PutProp[$Cluster, $RegStores,
CONS[
NEW[LizardRosemary.RegStoreRec ← [
instr: ClusterParams.clusterPanel.instrCount,
reg: cAdr3BA,
data: DragonRoseExtras.LFD[CBusResult3BA]]],
NARROW[Atom.GetProp[$Cluster, $RegStores], LIST OF REF ANY]]];
};
IF PhB
THEN {
phALast ← FALSE;
cAdr3BA ← IF DPRejectB THEN euBogus ELSE VAL[BitOps.ECFD[KBus, 32, Dragon.cRegKBusPos, 8]];
};
END;
END;
OldEU: TYPE = RECORD [args: EUArgs, ct: CellType];
oldEU: LIST OF OldEU ← NIL;
EU:
PUBLIC
PROC [args: EUArgs]
RETURNS [ct: CellType]
= BEGIN
FOR old:
LIST
OF OldEU ← oldEU, old.rest
WHILE old #
NIL
DO
IF old.first.args = args THEN RETURN [old.first.ct]
ENDLOOP;
ct ← RoseCreate.RegisterCellType[name: EUName[args],
expandProc: EUExpand,
ioCreator: CreateEUIO, driveCreator: CreateEUDrive,
evals: [],
tests: LIST[],
ports: CreateEUPorts[args]
,
typeData: NEW [EUArgs ← args]];
oldEU ← CONS[[args, ct], oldEU];
END;
EUName:
PROC [args: EUArgs]
RETURNS [name:
ROPE] = {
to: IO.STREAM ← IO.ROS[]; to.PutRope["EU"];
TRUSTED {PrintTV.Print[tv: AMBridge.TVForReferent[NEW [EUArgs ← args]], put: to, depth: 2]};
name ← IO.RopeFromROS[to]};
CreateEUPorts: PROC [args: EUArgs] RETURNS [ports: Ports] = {ports ← RoseCreate.PortsFromFile["EU.EU.rosePorts"]};
EUSwitchIORef: TYPE = REF EUSwitchIORec;
EUSwitchIORec:
TYPE =
RECORD [
DPData: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,DPRejectB: SwitchTypes.SwitchVal
,PhA: SwitchTypes.SwitchVal
,PhB: SwitchTypes.SwitchVal
,ResetAB: SwitchTypes.SwitchVal
,Vdd: SwitchTypes.SwitchVal
,Gnd: SwitchTypes.SwitchVal
,PadVdd: SwitchTypes.SwitchVal
,PadGnd: SwitchTypes.SwitchVal
,KBus: PACKED ARRAY [0 .. 32) OF SwitchTypes.SwitchVal
,EUSt3AisCBus2BA: SwitchTypes.SwitchVal
,EURes3BisPBus3AB: SwitchTypes.SwitchVal
,EUWriteToPBus3AB: SwitchTypes.SwitchVal
,EUAluOp2AB: PACKED ARRAY [0 .. 4) OF SwitchTypes.SwitchVal
,EUCondSel2AB: PACKED ARRAY [0 .. 4) OF SwitchTypes.SwitchVal
,EUCondition2B: SwitchTypes.SwitchVal
,DShiftAB: SwitchTypes.SwitchVal
,DExecuteAB: SwitchTypes.SwitchVal
,DNSelectAB: SwitchTypes.SwitchVal
,DHoldAB: SwitchTypes.SwitchVal
,DDataInAB: SwitchTypes.SwitchVal
,DDataOutAB: SwitchTypes.SwitchVal
];
EUSimpleIORef: TYPE = REF EUSimpleIORec;
EUSimpleIORec:
TYPE =
RECORD [
DPData: ARRAY [0..2) OF CARDINAL
,fill1: [0 .. 32767],
DPRejectB: BOOLEAN
,fill2: [0 .. 32767],
PhA: BOOLEAN
,fill3: [0 .. 32767],
PhB: BOOLEAN
,fill4: [0 .. 32767],
ResetAB: BOOLEAN
,fill5: [0 .. 32767],
Vdd: BOOLEAN
,fill6: [0 .. 32767],
Gnd: BOOLEAN
,fill7: [0 .. 32767],
PadVdd: BOOLEAN
,fill8: [0 .. 32767],
PadGnd: BOOLEAN
,KBus: ARRAY [0..2) OF CARDINAL
,fill10: [0 .. 32767],
EUSt3AisCBus2BA: BOOLEAN
,fill11: [0 .. 32767],
EURes3BisPBus3AB: BOOLEAN
,fill12: [0 .. 32767],
EUWriteToPBus3AB: BOOLEAN
,fill13: [0 .. 4095],
EUAluOp2AB: ALUOps
,fill14: [0 .. 4095],
EUCondSel2AB: CondSelects
,fill15: [0 .. 32767],
EUCondition2B: BOOLEAN
,fill16: [0 .. 32767],
DShiftAB: BOOLEAN
,fill17: [0 .. 32767],
DExecuteAB: BOOLEAN
,fill18: [0 .. 32767],
DNSelectAB: BOOLEAN
,fill19: [0 .. 32767],
DHoldAB: BOOLEAN
,fill20: [0 .. 32767],
DDataInAB: BOOLEAN
,fill21: [0 .. 32767],
DDataOutAB: BOOLEAN
];
EUDriveRef: TYPE = REF EUDriveRec;
EUDriveRec: TYPE = RECORD [driveRecordInitialPadding: DriveTagType, drive: PACKED ARRAY EUPort OF DriveLevel];
EUPort:
TYPE = {
DPData, DPRejectB, PhA, PhB, ResetAB, Vdd, Gnd, PadVdd, PadGnd, KBus, EUSt3AisCBus2BA, EURes3BisPBus3AB, EUWriteToPBus3AB, EUAluOp2AB, EUCondSel2AB, EUCondition2B, DShiftAB, DExecuteAB, DNSelectAB, DHoldAB, DDataInAB, DDataOutAB, EUPortTypePad22, EUPortTypePad23};
CreateEUIO:
PROC [ct: CellType, switch:
BOOL]
RETURNS [ioAsAny:
REF
ANY]
--IOCreator-- = {
args:
REF EUArgs ←
NARROW[ct.typeData];
{OPEN args;
ioAsAny ← IF switch THEN NEW[EUSwitchIORec] ELSE NEW[EUSimpleIORec];
};
};
CreateEUDrive:
PROC [ct: CellType]
RETURNS [driveAsAny:
REF
ANY]
--DriveCreator-- = {
args:
REF EUArgs ←
NARROW[ct.typeData];
{OPEN args;
driveAsAny ← NEW[EUDriveRec];
};
};
EUExpand:
PROC [thisCell: Cell, to: ExpansionReceiver]
--ExpandProc-- = {
args:
REF EUArgs ←
NARROW[thisCell.type.typeData];
{OPEN args;
PrivateLookupNode: PROC [name: ROPE] RETURNS [node: Node] = {node ← RoseCreate.LookupNode[from: thisCell, path: LIST[name]]};
DPData: Node ← PrivateLookupNode["DPData"];
DPRejectB: Node ← PrivateLookupNode["DPRejectB"];
PhA: Node ← PrivateLookupNode["PhA"];
PhB: Node ← PrivateLookupNode["PhB"];
ResetAB: Node ← PrivateLookupNode["ResetAB"];
Vdd: Node ← PrivateLookupNode["Vdd"];
Gnd: Node ← PrivateLookupNode["Gnd"];
PadVdd: Node ← PrivateLookupNode["PadVdd"];
PadGnd: Node ← PrivateLookupNode["PadGnd"];
KBus: Node ← PrivateLookupNode["KBus"];
EUSt3AisCBus2BA: Node ← PrivateLookupNode["EUSt3AisCBus2BA"];
EURes3BisPBus3AB: Node ← PrivateLookupNode["EURes3BisPBus3AB"];
EUWriteToPBus3AB: Node ← PrivateLookupNode["EUWriteToPBus3AB"];
EUAluOp2AB: Node ← PrivateLookupNode["EUAluOp2AB"];
EUCondSel2AB: Node ← PrivateLookupNode["EUCondSel2AB"];
EUCondition2B: Node ← PrivateLookupNode["EUCondition2B"];
DShiftAB: Node ← PrivateLookupNode["DShiftAB"];
DExecuteAB: Node ← PrivateLookupNode["DExecuteAB"];
DNSelectAB: Node ← PrivateLookupNode["DNSelectAB"];
DHoldAB: Node ← PrivateLookupNode["DHoldAB"];
DDataInAB: Node ← PrivateLookupNode["DDataInAB"];
DDataOutAB: Node ← PrivateLookupNode["DDataOutAB"];
others: SymbolTable ← RoseCreate.GetOthers[otherss, "EU"];
NodeCreateHack1: PROC [name: ROPE] RETURNS [node: Node] = {node ← to.class.NodeInstance[erInstance: to.instance, name: name, type: NumTypes.NumType[32], other: RoseCreate.GetOther[others, name]]};
ALULeft2AB: Node ← NodeCreateHack1["ALULeft2AB"];
ALURight2AB: Node ← NodeCreateHack1["ALURight2AB"];
Store2AB: Node ← NodeCreateHack1["Store2AB"];
CBusResult3BA: Node ← NodeCreateHack1["CBusResult3BA"];
[] ← to.class.CellInstance[erInstance: to.instance, instanceName: "compute", typeName: "EUCompute", other: RoseCreate.GetOther[others, "compute"], interfaceNodes: ""];
[] ← to.class.CellInstance[erInstance: to.instance, instanceName: "logger", typeName: EULogger[[logRef:logRef]].name, other: RoseCreate.GetOther[others, "logger"], interfaceNodes: ""];
};
};
RegisterCells[];
END.