<> <> <> <> <<>> <> <<>> DIRECTORY Core, CoreClasses, CoreCreate, Dyn, Ports, Rope, Rosemary, RosemaryUser, PBusConex, PBusEmul; PBusConexImpl: CEDAR PROGRAM IMPORTS CoreClasses, CoreCreate, Ports, PBusEmul, Rosemary EXPORTS PBusConex ~ BEGIN OPEN PBusConex; <> PBusDef: PUBLIC PROC [] RETURNS [ct: CellType] ~ { <> public: Wire _ CoreCreate.WireList[ LIST[ "PMode", CoreCreate.Seq["PByteSel",4], CoreCreate.Seq["PCmd",4], CoreCreate.Seq["PFaultCode",3], "PFault", "PReject", "PhB", "PhA", CoreCreate.Seq["PData",32], "PReschedule", "PReset", "CkIn" ]]; <> ct _ CoreClasses.CreateUnspecified[public: public]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: PBusConnexion]; <> <<>> Ports.InitPorts[ct, l, drive,"PMode"]; Ports.InitPorts[ct, ls, drive,"PByteSel"]; Ports.InitPorts[ct, ls, drive,"PCmd"]; Ports.InitPorts[ct, ls, none,"PFaultCode"]; Ports.InitPorts[ct, l, none,"PFault"]; Ports.InitPorts[ct, l, none,"PReject"]; Ports.InitPorts[ct, l, drive,"PhB"]; Ports.InitPorts[ct, l, drive,"PhA"]; Ports.InitPorts[ct, ls, drive,"PData"]; Ports.InitPorts[ct, l, none,"PReschedule"]; Ports.InitPorts[ct, l, none,"PReset"]; Ports.InitPorts[ct, l, none,"CkIn"]; }; PBusInit: PUBLIC Rosemary.InitProc = { <<--PROC [cellType: Core.CellType, p: Ports.Port, oldStateAny: REF ANY _ NIL] RETURNS [stateAny: REF ANY _ NIL]-- >> <> pbusemul: PBusEmulState_ IF oldStateAny=NIL THEN NEW[PBusEmulRec] ELSE NARROW[oldStateAny, PBusEmulState]; <> pbusemul.PByteSel _ NEW[Ports.LevelSequenceRec[4]]; pbusemul.PCmd _ NEW[Ports.LevelSequenceRec[4]]; pbusemul.PFaultCode _ NEW[Ports.LevelSequenceRec[3]]; pbusemul.PDataIn _ NEW[Ports.LevelSequenceRec[32]]; pbusemul.PDataOut _ NEW[Ports.LevelSequenceRec[32]]; <> pbusemul.PMode _ L; Ports.SetLS[pbusemul.PByteSel, L]; Ports.SetLS[pbusemul.PCmd, L]; Ports.SetLS[pbusemul.PDataIn, L]; Ports.SetLS[pbusemul.PDataOut, L]; pbusemul.PhB _ L; pbusemul.PhA _ L; <> [pbusemul.PMODE] _ Ports.PortIndexes[cellType.public,"PMode"]; [pbusemul.PBYTESEL] _ Ports.PortIndexes[cellType.public,"PByteSel"]; [pbusemul.PCMD] _ Ports.PortIndexes[cellType.public,"PCmd"]; [pbusemul.PFAULTCODE] _ Ports.PortIndexes[cellType.public,"PFaultCode"]; [pbusemul.PFAULT] _ Ports.PortIndexes[cellType.public,"PFault"]; [pbusemul.PREJECT] _ Ports.PortIndexes[cellType.public,"PReject"]; [pbusemul.PHB] _ Ports.PortIndexes[cellType.public,"PhB"]; [pbusemul.PHA] _ Ports.PortIndexes[cellType.public,"PhA"]; [pbusemul.PDATA] _ Ports.PortIndexes[cellType.public,"PData"]; [pbusemul.PRESCHEDULE] _ Ports.PortIndexes[cellType.public,"PReschedule"]; [pbusemul.PRESET] _ Ports.PortIndexes[cellType.public,"PReset"]; [pbusemul.CKIN] _ Ports.PortIndexes[cellType.public,"CkIn"]; <<>> pbusemul.numClockEdges _ 2; --number of clock edges since beginning pbusemul.cycleCount _ 0; --is used for loops inside procs pbusemul.prevClock _ L; --is used for detecting clock edges pbusemul.testProcList _ NIL; stateAny_ pbusemul; }; PBusEval: PUBLIC Rosemary.EvalProc = { <<--PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL]-->> pbusemul: PBusEmulState _ NARROW[stateAny]; <<>> <> IF clockEval AND pbusemul.prevClock=L AND p[pbusemul.CKIN].l=H THEN { SELECT (pbusemul.numClockEdges+1) MOD 4 FROM 0 => pbusemul.PhB _ L; 2 => pbusemul.PhA _ L; ENDCASE; }; IF ~clockEval THEN { <> IF p[pbusemul.CKIN].l=H THEN { Ports.CopyLS[from: p[pbusemul.PFAULTCODE].ls, to: pbusemul.PFaultCode]; pbusemul.PFault _ p[pbusemul.PFAULT].l; pbusemul.PReject _ p[pbusemul.PREJECT].l; Ports.CopyLS[from: p[pbusemul.PDATA].ls, to: pbusemul.PDataIn]; pbusemul.PReschedule _ p[pbusemul.PRESCHEDULE].l; pbusemul.PReset _ p[pbusemul.PRESET].l; }; <<>> <> IF pbusemul.prevClock=H AND p[pbusemul.CKIN].l=L AND pbusemul.cycle3ForRead THEN { PBusEmul.Emul[pbusemul]; pbusemul.cycle3ForRead _ FALSE }; <> IF pbusemul.prevClock=L AND p[pbusemul.CKIN].l=H THEN { pbusemul.cycle3ForRead _ pbusemul.cycleCount=3; -- AND pbusemul.PCmd[3]=L; pbusemul.numClockEdges _ pbusemul.numClockEdges+1; SELECT pbusemul.numClockEdges MOD 4 FROM 0 => pbusemul.PhA _ H; 2 => pbusemul.PhB _ H; ENDCASE; p[pbusemul.PDATA].d _ none; IF (pbusemul.PhA=H) OR (pbusemul.PhB=H AND pbusemul.PCmd[3]=H) THEN { p[pbusemul.PDATA].d _ drive; }; IF NOT pbusemul.cycle3ForRead THEN PBusEmul.Emul[pbusemul] }; <> pbusemul.prevClock _ p[pbusemul.CKIN].l }; <> p[pbusemul.PMODE].l _ pbusemul.PMode; Ports.CopyLS[from: pbusemul.PByteSel, to: p[pbusemul.PBYTESEL].ls]; Ports.CopyLS[from: pbusemul.PCmd, to: p[pbusemul.PCMD].ls]; p[pbusemul.PHB].l _ pbusemul.PhB; p[pbusemul.PHA].l _ pbusemul.PhA; IF (pbusemul.PhA=H) OR (pbusemul.PhB=H AND pbusemul.PCmd[3]=H) THEN { Ports.CopyLS[from: pbusemul.PDataOut, to: p[pbusemul.PDATA].ls]; }; }; PBusConnexion: Core.ROPE = Rosemary.Register[roseClassName: "PBusDef", init: PBusInit, evalSimple: PBusEval, scheduleIfClockEval: TRUE]; END. <<>> <<>> <<>> <<>>