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: BOOLFALSE;
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.STREAMNIL;
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.STREAMIO.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.STREAMIO.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.