<> <> <> <> <> 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]]; < 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]]; < 0 bits in the mask select bits from Right to OR in to the result>> 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, <<>> <> <> <> <<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>> <> 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]; }; <<-- 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"]; }; <<>> <<>> <> 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.