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; 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"]; 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; shifter: Word = DoubleWordShiftLeft[Left, Right, fd.shift]; mask: Word _ SingleWordShiftRight[OnesWord, 32-fd.mask]; IF fd.insert THEN mask _ DragAnd[mask, SingleWordShiftLeft[OnesWord, fd.shift]]; out _ DragAnd[mask, shifter]; IF fd.insert THEN out _ DragOr[out, DragAnd[DragNot[mask], Right]]; result _ WordToCard[out]; END; 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_DragonRoseExtras.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_DragonRoseExtras.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 [ aluLeft, aluRight, aluOut: Dragon.HexWord, result2BA, result3AB, cBusResult3BA: Dragon.HexWord, store2AB, store2BA, store3AB: Dragon.HexWord, 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. 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, 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; IF PhA THEN { cReg: DragOpsCross.ProcessorRegister; DragonRosemary.Assert[aAdr>=0 AND aAdr<164]; 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; 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]; }; 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"]; }; IF PhB THEN { c32, cx: BOOL; rejectBA _ DPRejectB; 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]]; 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}; 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 ; store2BA _ store2AB; 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"]; 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. Μ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 Signal Type decls explicitly requested CEDAR: From here on, the code is copied from LizardHeartImpl, which in turn purports to be identical to the manual. The shifter output has the input double word shifted left by fd.shift bits The default mask has fd.mask 1s right-justified in the word fd.insert => clear rightmost fd.shift bits of the mask 1 bits in the mask select the shifter output fd.backR => 0 bits in the mask select bits from Right to OR in to the result Returns a+b+carry and c32, where a and b are considered to be signed numbers Pipeline registers 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 Bits and pieces for the ALU and the Field Unit Other pieces from the Control pipeline PhiA phase. Note that rejectBA alone inhibits almost any state change during PhiA No simultaneous bypass control signals on Always send address to Cache during PhiA -- 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) PhiB phase. Most of the computations take place during PhiB 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 PBus: notice that in case of reject during a store, we keep sending the data even though it is useless save the address in cBusResult3BA, done normally since NOT EURes3BisPBus3AB; Data pipe Alu and Field Unit computation Set Default values of state Condition and trap generation Κβ˜Icodešœ ™ KšœC™CKšœ6™6Kšœ™Kšœ)™)K˜K˜šΟk ˜ Kšœ œqœz˜ϊ—K˜šΠblœœ˜KšœLœo˜ΔKšœ˜ —K˜šœœ˜ Kšœ œ˜—K˜šœ™Kšœœ˜Kšœ œ˜'K˜—K˜šΟn œœ˜Kš˜˜:Kšœ œ˜K˜cK˜)Kšœœ˜K˜K˜—Kšœ˜—K˜CK˜šœ™Jšœ œ+œ˜AJšœ œ)œ˜=J˜JšŸœœœ0˜QJ˜šŸœœ.˜;Jšœ˜!Jšœœ!˜+Jšœ6œ˜AJ˜!J˜#J˜ J™l˜;J™J—˜8J™;—šœ œ?˜PJ™7—˜J™,—šœ œ2˜CJ™L—J˜Jšœ˜—J˜J™LšŸ œœ œ˜4Jšœœ˜+š Ÿœœœœœ˜*Jš œœœœœœœ˜)—Jšœœ˜ Jšœœœ˜Jšœœ ˜Jšœœ˜ J˜šœœ ˜Jš˜Jšœœ ˜Jšœœ ˜J˜Jš œœœœœœ˜,Jšœ œ˜%Jšœ˜—Jšœœ ˜&—J˜šŸ œœœ˜BJšœœœ˜+J˜J˜—šŸœœ3˜?Jšœ˜"šœœœ˜*Jšœœœœ ˜NJšœœœœ ˜OJšœœœœ ˜OJšœœ˜——J˜šŸœœœ ˜7Jšœ œœ˜=—J˜š œœœœœ˜CJšœ œœ˜>J˜—šŸ œœœ˜7šœ!˜(Jšœœ/˜D——šŸœœœœ˜IJš œœœ œœ#˜l—J˜šŸ œœ"œ˜7Jšœœ!˜2Jšœœ œ(˜W—šŸœœœœ˜HJš œœœ œœ$˜m—J˜Jšœœœœ˜J˜š Ÿ œœ œœœΟcœ˜_Jšœœ˜+šœ%œ˜-šœœœ˜J˜>J˜,J˜—J˜,J˜—J˜——K˜Kšœ œ ˜K˜KšŸœœœO˜qK˜Kšœœœ˜6šœœœ˜%Kšœœœ œ˜7K˜!K˜K˜K˜K˜K˜K˜Kšœœœ œ˜6K˜'K˜(K˜(Kšœ œœ œ˜;Kšœœœ œ˜=K˜%K˜ K˜"K˜"K˜K˜!K˜"Kšœœœ œ˜?Kšœ œœ œ˜Kšœ œœœ˜'šŸœœœœ˜AKšœ˜š œœœ%œœ˜GKšœœœ˜3Kšœ˜—˜:Kšœ œ˜K˜`K˜(Kšœœ˜K˜ K˜Kšœ œ˜%—Kšœœ˜,Kšœ˜—K˜šŸ œœœœ˜@Kš œœœœœ˜1Kšœ+œ-˜bKšœœ˜—K˜KšŸœœœN˜„K˜Kšœœœ˜4šœœœ˜$Kšœœœ œ˜5Kšœ œœ œ˜Kšœœ˜>šœœ˜;šœœ˜%J˜šœ œ$œ˜8J˜—šœœœ œ˜Jšœ œ˜šœ ˜Jšœœ˜šœ&˜-šœ˜šœ˜"J˜-J˜ Jšœœ˜,—Jš œ%œœœœ˜>———J˜J˜—šœœ˜ Jšœ œ˜Jš œ œ œ œœœ#˜[J˜——Kšœ˜—Kšœ˜—K˜Kšœœœ˜2Kšœœœ œ˜šœœœœ˜5Kšœ˜š œœœœœ˜;Kšœœœ˜3Kšœ˜—˜4K˜K˜4K˜ Kšœœ˜K˜K˜Kšœ œ˜—Kšœœ˜ Kšœ˜—K˜šŸœœœœ˜4Kš œœœœœ˜+Kšœ+œ'˜\Kšœœ˜—K˜KšŸ œœœH˜rK˜Kšœœœ˜(šœœœ˜Kšœœœ œ˜7K˜!K˜K˜K˜K˜K˜K˜K˜Kšœœœ œ˜6K˜'K˜(K˜(Kšœ œœ œ˜;Kšœœœ œ˜=K˜%K˜ K˜"K˜"K˜K˜!K˜"K˜—K˜Kšœœœ˜(šœœœ˜Kšœœœ˜ K˜Kšœ ˜K˜Kšœ˜ K˜Kšœ˜ K˜Kšœ ˜K˜Kšœ˜ K˜Kšœ˜ K˜Kšœ˜K˜Kšœ˜Kšœœœ˜K˜Kšœ˜K˜Kšœ˜K˜Kšœ˜K˜K˜K˜K˜K˜Kšœ˜K˜Kšœ ˜K˜Kšœ ˜K˜Kšœ ˜K˜Kšœ ˜K˜Kšœ ˜K˜Kšœ ˜K˜—K˜Kšœ œœ ˜"Kš œ œœ2œœœ ˜nšœœ˜K˜ˆ—K˜šŸ œœœœ œœ  œ˜Zšœœ œ˜'Kšœœ˜ Kš œ œœœœœ˜DK˜—K˜—K˜š Ÿ œœœœœ œ˜Ušœœ œ˜'Kšœœ˜ Kšœ œ ˜K˜—K˜—K˜šŸœœ) œ˜Išœœ œ˜2Kšœœ˜ Kš ŸœœœœDœ ˜}K˜+K˜1K˜%K˜%K˜-K˜%K˜%K˜+K˜+K˜'K˜=K˜?K˜?K˜3K˜7K˜9K˜/K˜3K˜3K˜-K˜1K˜3K˜:KšŸœœœœš˜ΔK˜1K˜3K˜-K˜7K˜§K˜ΈK˜—K˜—K˜K˜K˜Kšœ˜—…—^v€$