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 = { 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 = { 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. ώPBusConexImpl.mesa Copyright Σ 1987, 1988 by Xerox Corporation. All rights reserved. Created by Jean Gastinel, May 26, 1988 7:46:11 pm PDT Pradeep Sindhu May 4, 1988 9:59:24 pm PDT This program emulates a part of the PBus interface. Presently it manages only simple Read and Write on the PBus. Here are the 3 procs Here is where the name and the size of public wires must be given This creates a celltype Now the type of each pins --PROC [cellType: Core.CellType, p: Ports.Port, oldStateAny: REF ANY _ NIL] RETURNS [stateAny: REF ANY _ NIL]-- Init the state Create the pointers on different sequences Init the value of the outputs Take the indice of each pins --PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL]-- Falling edges of PhA, PhB are treated like clocks; rising edges like normal signals. On Clock high capture inputs in internal state On Clock high to low check the data On Clock low to high do the computation Advance clock Always assign the values of variables to the output wires: Κ]˜™Icode™BK™5K™)K™—K™qK™šΟk ˜ Kšœ]˜]K˜—KšΠbl œœ˜K˜Kšœ3˜:Kšœ ˜K˜šœ˜Kšœ ˜—head™KšΟnœœœœ˜2˜K™Ašœ#˜#šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ K˜—K˜K˜—K™Kšœ3˜3K˜KšœG˜GK˜K™K™Kšœ&˜&Kšœ,˜,Kšœ'˜'Kšœ,˜,Kšœ&˜&Kšœ'˜'Kšœ$˜$Kšœ$˜$Kšœ(˜(Kšœ+˜+Kšœ&˜&Kšœ$˜$K˜K˜—KšŸœœ˜&KšΟcp™pK™Kš œœ œœœœœ˜lK™*Kšœœ˜3Kšœœ˜/Kšœœ˜5Kšœœ˜3Kšœœ˜4K˜K™Kšœ˜Kšœ"˜"Kšœ˜Kšœ!˜!Kšœ"˜"Kšœ˜Kšœ˜K˜K™Kšœ œ/˜>Kšœ œ2˜DKšœ œ.˜Kšœ  œ5˜JKšœ œ0˜@Kšœ œ.˜