DIRECTORY Arbiter, Commander, CommandTool, Convert, Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, IO, Ports, Random, Rope, Rosemary; ArbRandReq: CEDAR PROGRAM IMPORTS Commander, CommandTool, Convert, CoreClasses, CoreCreate, CoreFlat, CoreOps, IO, Ports, Random, Rosemary EXPORTS Arbiter = BEGIN OPEN Arbiter, CoreCreate; logicCutSet: Rope.ROPE = "Logic"; -- should be Logic.logicCutSet, actually ArbRandReqName: Rope.ROPE = Rosemary.Register[roseClassName: "ArbRandReq", init: ArbRandReqInit, evalSimple: ArbRandReqSimple]; ArbRandReqInterface: Wire = WireList[LIST[ Seq["nDReq", 2], -- radial lines "nDGrant", "nBDLong", -- bussed lines "nBDHi", "nStartGrant", "nDOwner", "nSysOwner", "nDShared", "nSysShared", "nDStop", "nSysStop", "nDReset", Seq["DPriority", 9], "nDynaBusBusy", "nHolding", "Ck", "Vdd", "Gnd" ]]; ArbRandReq: PUBLIC PROC RETURNS [ ct: CoreCreate.CellType ] = { ct _ CoreOps.CreateCellType[ class: CoreClasses.unspecifiedCellClass, public: ArbRandReqInterface, name: "ArbRandReq" ]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: ArbRandReqName]; [] _ CoreFlat.CellTypeCutLabels[ct, logicCutSet]; Ports.InitPorts[ct, c, drive, "nDReq"]; Ports.InitPorts[ct, b, none, "nDGrant", "nBDLong", "nBDHi", "nStartGrant"]; Ports.InitPorts[ct, b, driveWeak, "nDOwner", "nDShared", "nDStop"]; Ports.InitPorts[ct, b, none, "nSysOwner", "nSysShared", "nSysStop"]; Ports.InitPorts[ct, c, none, "DPriority"]; Ports.InitPorts[ct, b, none, "nDynaBusBusy", "nHolding"]; Ports.InitPorts[ct, b, none, "Ck", "Vdd", "Gnd"]; }; ArbRandReqState: TYPE = REF ArbRandReqStateRec _ NIL; ArbRandReqStateRec: TYPE = RECORD [ nDReq, nDGrant, nBDLong, nBDHi, nStartGrant, nDOwner, nSysOwner, nDShared, nSysShared, nDStop, nSysStop, nDReset, DPriority, nDynaBusBusy, nHolding, Ck: NAT _ LAST[NAT], random: Random.RandomStream, m, s: ArbReqMSRec, lastCk: BOOL _ FALSE ]; probTable: ARRAY Arbiter.ReqCount OF INT _ [1, 4, 8, 16, 32, 64, 1]; maxCntLatency: INT _ 9; -- might be 8, certainly isn't 7 maxGrantLatency: INT _ 7; -- might be smaller defaultProbs: REF ProbabilitiesRec _ NEW[ProbabilitiesRec _ [ request: ALL[30], hold: 100 ]]; lastGenSeed: INT _ 1354117939; genRS: Random.RandomStream _ NIL; SetupSeed: PROC [ seed: INT _ 0 ] RETURNS [ IO.ROPE ] = { IF seed = 0 THEN seed _ lastGenSeed; genRS _ Random.Create[seed: seed]; lastGenSeed _ genRS.seed; RETURN[IO.PutFR["New random number seed is %d.\n", IO.int[lastGenSeed]]]; }; ArbRandReqInit: PROC [ cellType: Core.CellType, p: Ports.Port, oldStateAny: REF ANY _ NIL, steady: BOOL _ FALSE ] RETURNS [ stateAny: REF ANY _ NIL ] -- Rosemary.InitProc -- = { st: ArbRandReqState _ NEW[ArbRandReqStateRec _ [ random: genRS ]]; [st.nDReq, st.nDGrant, st.nBDLong, st.nBDHi, st.nStartGrant ] _ Ports.PortIndexes[cellType.public, "nDReq", "nDGrant", "nBDLong", "nBDHi", "nStartGrant"]; [st.nDOwner, st.nSysOwner, st.nDShared, st.nSysShared, st.nDStop, st.nSysStop] _ Ports.PortIndexes[cellType.public, "nDOwner", "nSysOwner", "nDShared", "nSysShared", "nDStop", "nSysStop"]; [st.nDReset, st.DPriority, st.nDynaBusBusy, st.nHolding, st.Ck] _ Ports.PortIndexes[cellType.public, "nDReset", "DPriority", "nDynaBusBusy", "nHolding", "Ck"]; stateAny _ NEW[RequesterStateRec _ [probs: defaultProbs, state: st]]; }; ArbRandReqSimple: PROC [ p: Ports.Port, stateAny: REF ANY, clockEval: BOOL ] -- Rosemary.EvalProc -- = { rs: REF RequesterStateRec = NARROW[stateAny]; st: ArbRandReqState = NARROW[rs.state]; ArbReqMain[p, stateAny, clockEval]; st.lastCk _ p[st.Ck].b; }; holdPipeLen: NAT _ 8; ArbReqMSRec: TYPE = RECORD [ reset, grant, startGrant: BOOL _ FALSE, long, prevLong: BOOL _ FALSE, grantType, prevGrantType: DevReqType, holding: BOOL _ FALSE, drc: Arbiter.DevReqCode, rqCnt: ARRAY DevReqType OF ReqCount _ ALL[0], grantCycles: INT _ 0, go: ARRAY DevReqType OF BOOL _ ALL[FALSE], delayUntilDemand: INT _ 0, busBusy, busWasBusy: BOOL _ TRUE, cyclesSinceIdle: INT _ 0, lenFIFO: ARRAY ReqCount OF PacketLength _ ALL[short2], holdPipe: ARRAY [0..10) OF BOOL _ ALL[TRUE] ]; ArbReqMain: PROC [ p: Ports.Port, stateAny: REF ANY, clockEval: BOOL ] -- Rosemary.EvalProc -- = { ProbBool: PROC [ x: INT ] RETURNS [ b: BOOL ] = { b _ (x < 10000000) AND (st.random.ChooseInt[1, x] <= 1); }; rs: REF RequesterStateRec = NARROW[stateAny]; st: ArbRandReqState = NARROW[rs.state]; IF p[st.Ck].b THEN { IF NOT st.lastCk THEN st.s _ st.m -- positive clock edge } ELSE { -- Clock is low, load master latches dPriority: PriorityRec; TRUSTED { dPriority _ LOOPHOLE[p[st.DPriority].c] }; st.m.reset _ NOT p[st.nDReset].b; st.m.grant _ NOT p[st.nDGrant].b; st.m.startGrant _ NOT p[st.nStartGrant].b; st.m.long _ NOT p[st.nBDLong].b; st.m.prevLong _ st.s.long; st.m.grantType _ (IF NOT p[st.nBDHi].b THEN H ELSE L); st.m.prevGrantType _ st.s.grantType; st.m.busBusy _ NOT p[st.nDynaBusBusy].b; st.m.busWasBusy _ st.s.busBusy; st.m.holding _ NOT p[st.nHolding].b; IF st.s.reset THEN { -- we're being reset st.m.rqCnt _ ALL[0]; st.m.drc _ release; st.m.grantCycles _ 0; st.m.holdPipe _ ALL[FALSE]; } ELSE { st.m.delayUntilDemand _ (SELECT TRUE FROM st.s.rqCnt = ALL[0] => maxCntLatency, st.s.startGrant => maxGrantLatency, ENDCASE => MAX[0, st.s.delayUntilDemand-1]); IF p[st.nDReset].b AND NOT st.s.reset AND NOT st.s.busBusy AND NOT st.s.busWasBusy AND NOT st.s.holding AND (st.s.delayUntilDemand = 0) THEN ERROR; st.m.holdPipe[0] _ ProbBool[(SELECT st.s.holdPipe[0] FROM FALSE => rs.probs.hold, TRUE => 2, ENDCASE => ERROR)]; FOR i: NAT IN [1..10) DO st.m.holdPipe[i] _ st.s.holdPipe[i-1]; ENDLOOP; st.m.rqCnt _ st.s.rqCnt; SELECT TRUE FROM st.s.grantCycles > 1 => { IF st.s.startGrant OR NOT st.s.grant THEN ERROR; st.m.grantCycles _ st.s.grantCycles-1; }; st.s.grant => { IF NOT st.s.startGrant THEN ERROR; IF st.m.rqCnt[st.s.prevGrantType] <= 0 THEN ERROR; st.m.rqCnt[st.s.prevGrantType] _ st.s.rqCnt[st.s.prevGrantType]-1; IF NOT dPriority.nFIFOEna THEN { IF st.s.prevGrantType # L THEN ERROR; IF st.s.prevLong # (st.s.lenFIFO[0] = long5) THEN ERROR; } ELSE { expectedLong: BOOL = (SELECT TRUE FROM st.s.prevGrantType = H AND dPriority.hiLong => TRUE, st.s.prevGrantType = L AND dPriority.loLong => TRUE, ENDCASE => FALSE); IF st.s.prevLong # expectedLong THEN ERROR; }; st.m.grantCycles _ IF st.s.prevLong THEN 5 ELSE 2; }; ENDCASE => st.m.grantCycles _ 0; FOR i: ReqCount IN ReqCount DO st.m.lenFIFO[i] _ (SELECT TRUE FROM st.s.grant AND st.s.grantCycles <=1 AND i st.s.lenFIFO[i+1], st.s.grant AND st.s.grantCycles <=1 => long5, ENDCASE => st.s.lenFIFO[i]); ENDLOOP; st.m.cyclesSinceIdle _ (IF st.s.rqCnt = ALL[0] THEN 0 ELSE st.s.cyclesSinceIdle+1); FOR rType: DevReqType IN DevReqType DO st.m.go[rType] _ ProbBool[probTable[st.m.rqCnt[rType]]*rs.probs.request[rType]]; ENDLOOP; SELECT TRUE FROM st.s.holdPipe[0] => st.m.drc _ seize; st.s.holdPipe[1] AND NOT st.s.holdPipe[0] => st.m.drc _ release; st.s.go[H] AND dPriority.nFIFOEna AND st.m.rqCnt[H] < LAST[Arbiter.ReqCount]-1 => { st.m.drc _ reqH; st.m.rqCnt[H] _ st.m.rqCnt[H]+1; }; st.s.go[H] AND NOT dPriority.nFIFOEna AND st.m.rqCnt[L] < LAST[Arbiter.ReqCount]-1 => { st.m.drc _ reqH; st.m.lenFIFO[st.m.rqCnt[L]] _ long5; st.m.rqCnt[L] _ st.m.rqCnt[L]+1; }; st.s.go[L] AND st.m.rqCnt[L] < LAST[Arbiter.ReqCount]-1 => { st.m.drc _ reqL; st.m.lenFIFO[st.m.rqCnt[L]] _ short2; st.m.rqCnt[L] _ st.m.rqCnt[L]+1; }; ENDCASE => st.m.drc _ release; }; }; p[st.nDReq].c _ 3-ORD[st.s.drc]; -- inverts p[st.nDOwner].b _ NOT FALSE; p[st.nDOwner].d _ IF p[st.nDOwner].b THEN driveWeak ELSE drive; p[st.nDShared].b _ NOT FALSE; p[st.nDShared].d _ IF p[st.nDShared].b THEN driveWeak ELSE drive; p[st.nDStop].b _ NOT FALSE; p[st.nDStop].d _ IF p[st.nDStop].b THEN driveWeak ELSE drive; p[st.nDynaBusBusy].d _ IF st.s.grantCycles > 0 THEN drive ELSE driveWeak; p[st.nDynaBusBusy].b _ NOT (st.s.grantCycles > 0); p[st.nHolding].d _ IF st.s.holdPipe[holdPipeLen] THEN drive ELSE driveWeak; p[st.nHolding].b _ NOT st.s.holdPipe[holdPipeLen]; }; ArbRandReqSeedProc: PROC [ cmd: Commander.Handle ] RETURNS [ result: REF _ NIL, msg: Rope.ROPE _ NIL ] -- Commander.CommandProc -- = { seed: INT _ 0; argv: CommandTool.ArgumentVector = CommandTool.Parse[cmd]; IF argv.argc > 1 THEN seed _ Convert.IntFromRope[ argv[1] ! Convert.Error => CONTINUE ]; cmd.out.PutRope[SetupSeed[seed]]; }; Commander.Register["ArbRandReqSeed", ArbRandReqSeedProc, "Reseeds the random number generator for the Arbiter simulation. Usage is\n ArbRandReqSeed n\n where n is an integer. 0 recovers the previous seed."]; END. ΚArbRandReq.mesa McCreight May 22, 1987 6:44:52 pm PDT Last Edited by: McCreight September 25, 1987 6:45:57 pm PDT P a r a m e t e r s b has an 1-in-x chance of being true, except if x >= 10000000 Κ .˜šœ™Jšœ%™%Icode™;—J˜šΟk ˜ Jšœ\œ ˜~J˜—šΟn œœ˜šœNœ˜pJšœ˜—J˜Jšœœ˜J˜Jšœœ Οc(˜JJ˜Jšžœœf˜J˜šžœœ˜*JšœŸ˜ Jšœ ˜ Jšœ Ÿ˜Jšœ˜Jšœ˜J˜ J˜ J˜ J˜ J˜ J˜ Jšœ ˜ J˜Jšœ˜Jšœ ˜ J˜J˜J˜—šž œœœœ ˜?˜J˜(J˜J˜J˜—J˜HJ˜1Jšœ'˜'JšœK˜KJšœC˜CJšœD˜DJšœ*˜*Jšœ9˜9Jšœ1˜1J˜—J˜Jšœœœœ˜5šœœœ˜#šœ,˜,Jšœ;˜;Jš œ,žœœœœ˜@—J˜J˜Jšœœ˜J˜J˜—Jšœ™˜Jšœ œœœ˜DJšœœŸ ˜8JšœœŸ˜-J˜—J˜šœœœ˜=Jšœ œ˜Jšœ ˜ Jšœ˜—J˜J˜Jšœ œ˜Jšœœ˜!J˜š ž œœ œœœœ˜9Jšœ œ˜$J˜"J˜Jšœœ*œ˜IJ˜—˜J˜—šžœœ8œœœ œœœ œœœŸœ˜±šœœ˜0J˜ J˜—šœ?˜?JšœZ˜Z—šœP˜PJšœk˜k—šœA˜AJšœ]˜]—Jšœ œ7˜EJ˜—˜J˜—š žœœœœ œŸœ˜hJšœœœ ˜-Jšœœ ˜'Jšœ#˜#Jšœ˜J˜J˜J˜—šœ œ˜J˜—šœ œœ˜Jšœœœ˜'Jšœœœ˜J˜%Jšœ œœ˜J˜Jšœœ œ œ˜-Jšœ œ˜Jš œœ œœœœ˜*Jšœœ˜Jšœœœ˜!Jšœœ˜Jšœ œ œœ ˜6Jš œ œ œœœœ˜+J˜J˜J˜—Jš ž œœœœ œŸœ˜b˜š žœœœœœ˜1Jšœ=™=Jšœœ"˜8Jšœ˜J˜—Jšœœœ ˜-Jšœœ ˜'šœ œ˜Jšœœ œ Ÿ˜8J˜—šœŸ$˜+Jšœ˜Jšœœ˜4Jšœ œ˜!Jšœ œ˜!Jšœœ˜*Jšœ œ˜ J˜Jš œœœœœ˜6J˜$Jšœœ˜(Jšœ˜Jšœœ˜$J˜šœ œŸ˜)Jšœ œ˜J˜J˜Jšœœœ˜J˜—šœ˜šœœœ˜)Jšœ œ˜%J˜#Jšœœ˜,J˜—š œœœ œœ ˜:Jšœœ˜Jšœœœœ˜