<> <> <> 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 ] = { <= 10000000>> 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.