<> <> <> <> DIRECTORY Arbiter, BitOps, CoreClasses, CoreCreate, CoreFlat, CoreOps, Logic, Ports, Rope, Rosemary; ArbiterImpl: CEDAR PROGRAM IMPORTS BitOps, CoreCreate, CoreClasses, CoreFlat, CoreOps, Logic, Ports, Rosemary EXPORTS Arbiter = BEGIN OPEN Arbiter, CoreCreate; <> <> <<>> ArbInFrameInterface: Wire = WireList[LIST[ "nBusyIn", -- down the left side "nBusyOut", "nStopAct", "nBSStopOut", "nBSharedOut", "nBOwnerOut", "nStartGrant", Seq["nOtherArbIn", maxArbiters-1, Seq[size: 3]], Seq["nArbReqOut", 3], Seq["nGrant", maxDevices], -- left to right across top Seq["nRequestOut", maxDevices, Seq[size: 2]], "nSStopIn", "nOwnerIn", "nSharedIn", "nLongGrant", "nHiPGrant", "nOwnerOut", -- down the right side Seq["nSharedOut", maxDevices], Seq["nSStopOut", maxDevices], Seq["DBus", 7], Seq["TInv", 2], Seq["TRec2v", 3], "RecAdj", Seq["TIOBus", 6], "nBOwnerIn", -- left to right across bottom Seq["nBSharedIn", maxArbiters], Seq["nBSStopIn", maxArbiters], Seq["BdVersion", 2], Seq["SlotNo", 4], "DBdSel", Seq["nDHybridSel", 5], "Clock", "CKOut", "Vdd", "Gnd", "Gnd2V" ]]; ArbInFrameCT: PUBLIC PROC RETURNS [ ct: CoreCreate.CellType ] = { inst: CoreCreate.CellInstance; instances: CellInstances _ LIST[]; publics: Wire = ArbInFrameInterface; internals: Wire = WireList[LIST[ "Rst", "Freeze", Seq["DPriority", maxDevices, Seq[size: 9]], Seq["ArbNo", 3], Seq["ArbRovers6", 8, Seq[size: 3]], ]]; arbCT: CellType _ CoreFlat.CellTypeCutLabels[on: ArbExceptDBusCodeCT[], l1: "TopLevel"]; arbDBusCT: CellType _ CoreFlat.CellTypeCutLabels[on: ArbDBusCodeCT[], l1: "TopLevel"]; ossIn: Wire _ CoreOps.FindWire[arbCT.public, "OSSIn"]; ossOut: Wire _ CoreOps.FindWire[arbCT.public, "OSSOut"]; pas: LIST OF PA _ LIST[ [public: "Ck", actual: "CKOut"], [public: ossIn[nOwnerOut], actual: "nOwnerOut"], [public: ossOut[nBOwnerOut], actual: "nBOwnerOut"], [public: ossIn[nBOwnerIn], actual: "nBOwnerIn"], [public: ossOut[nOwnerIn], actual: "nOwnerIn"], [public: ossIn[nSharedOut], actual: "nSharedOut"], [public: ossOut[nBSharedOut], actual: "nBSharedOut"], [public: ossIn[nBSharedIn], actual: "nBSharedIn"], [public: ossOut[nSharedIn], actual: "nSharedIn"], [public: ossIn[nSStopOut], actual: "nSStopOut"], [public: ossOut[nBSStopOut], actual: "nBSStopOut"], [public: ossIn[nBSStopIn], actual: "nBSStopIn"], [public: ossOut[nSStopIn], actual: "nSStopIn"]]; inst _ InstanceList[ type: arbCT, pas: pas, name: "ArbExcDBus" ]; instances _ CONS[inst, instances]; inst _ InstanceList[ type: arbDBusCT, pas: LIST[ [public: "Ck", actual: "Clock"], [public: "CkOut", actual: "CKOut"]], name: "ArbDBus" ]; instances _ CONS[inst, instances]; inst _ InstanceList[ type: CoreFlat.CellTypeCutLabels[on: Logic.Inv[], l1: "TopLevel"], pas: LIST [ [public: "I", actual: CoreOps.FindWire[publics, "TInv"][0]], [public: "X", actual: CoreOps.FindWire[publics, "TInv"][1]] ], name: "TestInverter"]; instances _ CONS[inst, instances]; inst _ InstanceList[ type: CoreFlat.CellTypeCutLabels[on: Logic.Rec2V[], l1: "TopLevel"], pas: LIST [ [public: "I", actual: CoreOps.FindWire[publics, "TRec2v"][0]], [public: "Vth", actual: CoreOps.FindWire[publics, "TRec2v"][1]], [public: "X", actual: CoreOps.FindWire[publics, "TRec2v"][2]] ], name: "TestRec2v"]; ct _ CoreCreate.Cell[public: publics, onlyInternal: internals, instances: instances, name: "ArbInFrame"]; }; <<>> <> <<>> ArbExceptDBusName: ROPE = Rosemary.Register[roseClassName: "ArbExceptDBus", init: ArbExceptDBusInit, evalSimple: ArbExceptDBusSimple]; ArbExceptDBusInterface: Wire = WireList[LIST[ <> Seq["nRequestOut", maxDevices, Seq[size: 2]], -- request ports, radial Seq["nGrant", maxDevices], -- grant ports, radial "nHiPGrant", -- status, bussed "nLongGrant", <> Seq["nArbReqOut", 3], -- this arbiter's request to others Seq["nOtherArbIn", maxArbiters-1, Seq[size: 3]], -- requests from other arbiters "nBusyOut", "nBusyIn", "nStartGrant", -- for logic analyzer trigger "nStopAct", -- DynaBus Stop <> Seq["ArbRovers6", 8, Seq[size: 3]], -- not wired out to real pins <<>> <> WireList[LIST["nOwnerOut", "nBOwnerIn", Seq["nSharedOut", 8], Seq["nBSharedIn", 8], Seq["nSStopOut", 8], Seq["nBSStopIn", 8]], "OSSIn"], <> WireList[LIST["nBOwnerOut", "nOwnerIn", "nBSharedOut", "nSharedIn", "nBSStopOut","nSStopIn"], "OSSOut"], <> Seq["DPriority", maxDevices, Seq[size: 9]], Seq["ArbNo", 3], "Rst", <> "Ck", "Vdd", "Gnd" ]]; ArbExceptDBusCodeCT: PUBLIC PROC RETURNS [ ct: CoreCreate.CellType ] = { dreq, dgrant, arbReqOut, otherArbIn, dPriority, ossIn, ossOut, arbRovers6: NAT; ct _ CoreClasses.CreateUnspecified[name: ArbExceptDBusName, public: ArbExceptDBusInterface]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: ArbExceptDBusName]; [] _ CoreFlat.CellTypeCutLabels[ct, Logic.logicCutSet]; dreq _ Ports.PortIndex[ct.public, "nRequestOut"]; dgrant _ Ports.PortIndex[ct.public, "nGrant"]; FOR d: Devices IN Devices DO [] _ Ports.InitPort[ct.public[dreq][d], c, aggregate, driveWeak]; [] _ Ports.InitPort[ct.public[dgrant][d], b, aggregate, driveWeak]; ENDLOOP; Ports.InitPorts[ct, b, drive, "nHiPGrant", "nLongGrant"]; arbReqOut _ Ports.PortIndex[ct.public, "nArbReqOut"]; FOR j: NAT IN [0..3) DO [] _ Ports.InitPort[ct.public[arbReqOut][j], b, aggregate, driveWeak]; ENDLOOP; otherArbIn _ Ports.PortIndex[ct.public, "nOtherArbIn"]; FOR j: Arbiters IN [0..maxArbiters-1) DO [] _ Ports.InitPort[ct.public[otherArbIn][j], c, aggregate, driveWeak]; ENDLOOP; Ports.InitPorts[ct, b, driveWeak, "nBusyOut", "nStartGrant", "nBusyIn", "nStopAct"]; ossIn _ Ports.PortIndex[ct.public, "OSSIn"]; ossOut _ Ports.PortIndex[ct.public, "OSSOut"]; FOR d: Devices IN Devices DO [] _ Ports.InitPort[ct.public[ossIn][nSharedOut][d], b, aggregate, driveWeak]; [] _ Ports.InitPort[ct.public[ossIn][nSStopOut][d], b, aggregate, driveWeak]; ENDLOOP; FOR a: Arbiters IN Arbiters DO [] _ Ports.InitPort[ct.public[ossIn][nBSharedIn][a], b, aggregate, driveWeak]; [] _ Ports.InitPort[ct.public[ossIn][nBSStopIn][a], b, aggregate, driveWeak]; ENDLOOP; [] _ Ports.InitPort[ct.public[ossIn][nOwnerOut], b, aggregate, driveWeak]; [] _ Ports.InitPort[ct.public[ossIn][nBOwnerIn], b, aggregate, driveWeak]; [] _ Ports.InitPort[ct.public[ossOut][nBOwnerOut], b, aggregate, drive]; [] _ Ports.InitPort[ct.public[ossOut][nOwnerIn], b, aggregate, drive]; [] _ Ports.InitPort[ct.public[ossOut][nBSharedOut], b, aggregate, drive]; [] _ Ports.InitPort[ct.public[ossOut][nSharedIn], b, aggregate, drive]; [] _ Ports.InitPort[ct.public[ossOut][nBSStopOut], b, aggregate, drive]; [] _ Ports.InitPort[ct.public[ossOut][nSStopIn], b, aggregate, drive]; arbRovers6 _ Ports.PortIndex[ct.public, "ArbRovers6"]; FOR pr: Priority IN Priority DO [] _ Ports.InitPort[ct.public[arbRovers6][pr], c, aggregate, drive]; ENDLOOP; dPriority _ Ports.PortIndex[ct.public, "DPriority"]; FOR d: Devices IN Devices DO [] _ Ports.InitPort[ct.public[dPriority][d], c, aggregate, none]; ENDLOOP; Ports.InitPorts[ct, c, none, "ArbNo"]; Ports.InitPorts[ct, b, none, "Rst"]; Ports.InitPorts[ct, b, none, "Ck", "Vdd", "Gnd"]; }; ArbExceptDBusState: TYPE = REF ArbExceptDBusStateRec; ArbExceptDBusStateRec: TYPE = RECORD [ nRequestOut, nGrant, nHiPGrant, nLongGrant, nArbReqOut, nOtherArbIn, nBusyOut, nBusyIn, nStartGrant, nStopAct, ArbRovers6, OSSIn, OSSOut, DPriority, ArbNo, Rst, Ck: NAT _ LAST[NAT], lastCk, lastDCk: BOOL _ TRUE, sm, ss: ArbSharedMSRec, m, s: ArbCoreMSRec <<.. master (loads during clock low) / slave (transfers out when clock goes high)>> <> ]; ArbExceptDBusInit: Rosemary.InitProc = { st: ArbExceptDBusState = (IF oldStateAny # NIL THEN NARROW[oldStateAny] ELSE NEW[ArbExceptDBusStateRec]); {OPEN st; [nRequestOut, nGrant, nHiPGrant, nLongGrant, nArbReqOut, nOtherArbIn] _ Ports.PortIndexes[cellType.public, "nRequestOut", "nGrant", "nHiPGrant", "nLongGrant", "nArbReqOut", "nOtherArbIn"]; [nBusyOut, nBusyIn, nStartGrant, nStopAct] _ Ports.PortIndexes[cellType.public, "nBusyOut", "nBusyIn", "nStartGrant", "nStopAct"]; [ArbRovers6] _ Ports.PortIndexes[cellType.public, "ArbRovers6"]; [OSSIn, OSSOut] _ Ports.PortIndexes[cellType.public, "OSSIn", "OSSOut"]; [DPriority, ArbNo, Rst, Ck] _ Ports.PortIndexes[cellType.public, "DPriority", "ArbNo", "Rst", "Ck"]; }; stateAny _ st; }; ArbExceptDBusSimple: PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL] -- Rosemary.EvalProc -- = { st: ArbExceptDBusState _ NARROW[stateAny]; ArbShared[p, st, clockEval]; ArbCore[p, st, clockEval]; st.lastCk _ p[st.Ck].b; }; DynaBusDrive: PROC [ p: Ports.Port, value: BOOL ] = { p.b _ NOT value; p.d _ IF value THEN drive ELSE driveWeak; }; ArbSharedMSRec: TYPE = RECORD [ OwnerOut: BOOL _ FALSE, BOwnerOut: BOOL _ FALSE, BOwnerIn: BOOL _ FALSE, OwnerIn: BOOL _ FALSE, SharedOut: ARRAY Devices OF BOOL _ ALL[FALSE], BSharedOut: BOOL _ FALSE, BSharedIn: ARRAY Arbiters OF BOOL _ ALL[FALSE], SharedIn: BOOL _ FALSE, SStopOut: ARRAY Devices OF BOOL _ ALL[FALSE], BSStopOut: BOOL _ FALSE, BSStopIn: ARRAY Arbiters OF BOOL _ ALL[FALSE], SStopIn: BOOL _ FALSE ]; ArbShared: PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL] -- Rosemary.EvalProc -- = { st: ArbExceptDBusState _ NARROW[stateAny]; IF p[st.Ck].b AND NOT st.lastCk THEN st.ss _ st.sm; IF NOT p[st.Ck].b THEN { st.sm.OwnerOut _ NOT p[st.OSSIn][nOwnerOut].b; st.sm.BOwnerOut _ st.ss.OwnerOut; st.sm.BOwnerIn _ NOT p[st.OSSIn][nBOwnerIn].b; st.sm.OwnerIn _ st.ss.BOwnerIn; st.sm.BSharedOut _ FALSE; st.sm.BSStopOut _ FALSE; FOR d: Devices IN Devices DO st.sm.SharedOut[d] _ NOT p[st.OSSIn][nSharedOut][d].b; st.sm.BSharedOut _ st.sm.BSharedOut OR st.ss.SharedOut[d]; st.sm.SStopOut[d] _ NOT p[st.OSSIn][nSStopOut][d].b; st.sm.BSStopOut _ st.sm.BSStopOut OR st.ss.SStopOut[d]; ENDLOOP; st.sm.SharedIn _ FALSE; st.sm.SStopIn _ FALSE; FOR a: Arbiters IN Arbiters DO st.sm.BSharedIn[a] _ NOT p[st.OSSIn][nBSharedIn][a].b; st.sm.SharedIn _ st.sm.SharedIn OR st.ss.BSharedIn[a]; st.sm.BSStopIn[a] _ NOT p[st.OSSIn][nBSStopIn][a].b; st.sm.SStopIn _ st.sm.SStopIn OR st.ss.BSStopIn[a]; ENDLOOP; }; DynaBusDrive[p[st.OSSOut][nBOwnerOut], st.ss.BOwnerOut]; DynaBusDrive[p[st.OSSOut][nOwnerIn], st.ss.OwnerIn]; DynaBusDrive[p[st.OSSOut][nBSharedOut], st.ss.BSharedOut]; DynaBusDrive[p[st.OSSOut][nSharedIn], st.ss.SharedIn]; DynaBusDrive[p[st.OSSOut][nBSStopOut], st.ss.BSStopOut]; DynaBusDrive[p[st.OSSOut][nSStopIn], st.ss.SStopIn]; <> p[st.OSSIn][nOwnerOut].b _ TRUE; p[st.OSSIn][nBOwnerIn].b _ TRUE; FOR d: Devices IN Devices DO p[st.OSSIn][nSharedOut][d].b _ TRUE; p[st.OSSIn][nSStopOut][d].b _ TRUE; ENDLOOP; FOR a: Arbiters IN Arbiters DO p[st.OSSIn][nBSharedIn][a].b _ TRUE; p[st.OSSIn][nBSStopIn][a].b _ TRUE; ENDLOOP; }; OtherArbiters: TYPE = [0..LAST[Arbiters]); OtherDevices: TYPE = [0..LAST[Devices]); DevRqInfo: TYPE = RECORD [type: DevReqType _ L, len: PacketLength _ long5]; ArbCoreMSRec: TYPE = RECORD [ <> <<>> <> OtherArbInBI: ARRAY [0..maxArbiters-1) OF [0..8) _ ALL[0], BusyInBI: BOOL _ FALSE, StopActBI: BOOL _ FALSE, RequestOutBI: ARRAY Devices OF [0..4) _ ALL[0], ArbReset: BOOL _ FALSE, <> LongGrantBO: BOOL _ FALSE, HiPGrantBO: BOOL _ FALSE, GrantBO: ARRAY Devices OF BOOL _ ALL[FALSE], ArbReqOutBO: [0..8) _ 0, BusyOutBO: BOOL _ TRUE, StartGrantBO: BOOL _ TRUE, <> LGrantHL: DevReqType, RqCtrs: ARRAY Devices OF ARRAY DevReqType OF ReqCount, LongFIFO: ARRAY Devices OF ARRAY ReqCount OF BOOL _ ALL[ALL[FALSE]], <<>> <> RqPrior1: ARRAY Devices OF Priority, RqInfo1: ARRAY Devices OF DevRqInfo, Hold: ARRAY Devices OF BOOL _ ALL[TRUE], DevRovers1: ARRAY Priority OF Devices _ ALL[0], <> ArbReq2: Priority, AmongBest2: ARRAY Devices OF BOOL _ ALL[TRUE], DRQInfo2: ARRAY Devices OF DevRqInfo, ClaimsHi2: ARRAY OtherDevices OF BOOL _ ALL[TRUE], <> <<>> <> ThisArbIn3: Priority, BestDev3: ARRAY Devices OF BOOL, -- at most one true LongGrant3: PacketLength, HiPGrant3: DevReqType, ArbRovers3: ARRAY Priority OF Arbiters, -- pipe delay of arbRovers AClaimsHi3: ARRAY OtherArbiters OF BOOL _ ALL[TRUE], <<>> <> LLGrant4: BOOL _ TRUE, -- not latched in hardware LclGrant4: BOOL _ TRUE, NoHold4: BOOL _ TRUE, GntPoss4: BOOL _ TRUE, DNewGrant4: ARRAY Devices OF BOOL _ ALL[TRUE], Grant4: ARRAY Devices OF BOOL _ ALL[TRUE], BstArbClaim4: Priority, AmgBest4: ARRAY Arbiters OF BOOL _ ALL[TRUE], ClaimsHi4: ARRAY OtherArbiters OF BOOL _ ALL[TRUE], <> LclGrant5: BOOL _ TRUE, GGrant5: BOOL _ TRUE, BestArb5: ARRAY OtherArbiters OF BOOL _ ALL[TRUE], BstArbClaim5: Priority, <> ArbRovers6: ARRAY Priority OF Arbiters, <> BusyOut: BOOL _ TRUE, -- not latched in hardware GCtr: ARRAY [0..2) OF BOOL _ ALL[TRUE] ]; ArbCore: PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL] -- Rosemary.EvalProc -- = { st: ArbExceptDBusState _ NARROW[stateAny]; IF p[st.Ck].b THEN { IF NOT st.lastCk THEN st.s _ st.m; -- positive-going clock edge } ELSE -- clock low, compute flipflop master stages { BusIn: PROC = { FOR a: Arbiters IN [0..maxArbiters-1) DO st.m.OtherArbInBI[a] _ 7-p[st.nOtherArbIn][a].c; ENDLOOP; st.m.BusyInBI _ NOT p[st.nBusyIn].b; st.m.StopActBI _ NOT p[st.nStopAct].b; FOR d: Devices IN Devices DO st.m.RequestOutBI[d] _ 3-p[st.nRequestOut][d].c; ENDLOOP; st.m.ArbReset _ p[st.Rst].b AND NOT st.s.StopActBI; }; BusOut: PROC = { FOR dev: Devices IN Devices DO st.m.GrantBO[dev] _ st.m.Grant4[dev]; ENDLOOP; st.m.HiPGrantBO _ st.m.HiPGrant3 = H; st.m.LongGrantBO _ st.m.LongGrant3 = long5; st.m.ArbReqOutBO _ (7-st.m.ArbReq2); st.m.BusyOutBO _ st.m.BusyOut; st.m.StartGrantBO _ st.m.LclGrant4; }; NvrMind: PROC [ p: Priority ] RETURNS [ Priority ] = { RETURN[(IF (p <= HoldPriority) THEN HoldPriority ELSE NoRequestPriority)]; }; RealReq: PROC [ p: Priority ] RETURNS [ BOOL ] = { RETURN[(p # HoldPriority) AND (p # NoRequestPriority)]; }; Pipe0: PROC = { FOR dev: Devices IN Devices DO reqCode: DevReqCode; pr: PriorityRec; TRUSTED { reqCode _ LOOPHOLE[st.s.RequestOutBI[dev]]; pr _ LOOPHOLE[p[st.DPriority][dev].c]; }; FOR drt: DevReqType IN DevReqType DO up: [0..1] = (SELECT TRUE FROM drt=L AND ((reqCode = reqL) OR ((reqCode = reqH) AND NOT pr.nFIFOEna)) => 1, drt=H AND ((reqCode = reqH) AND pr.nFIFOEna) => 1, ENDCASE => 0); down: [0..1] = (IF st.s.DNewGrant4[dev] AND drt = st.s.LGrantHL THEN 1 ELSE 0); st.m.RqCtrs[dev][drt] _ (IF st.s.ArbReset THEN 0 ELSE MAX[MIN[st.s.RqCtrs[dev][drt]+up, LAST[ReqCount]]-down, 0] ); ENDLOOP; -- drt FOR q: ReqCount IN ReqCount DO looksLong: BOOL = (st.s.RequestOutBI[dev] MOD 2 = 1); occ: INT = st.s.RqCtrs[dev][L]-1; st.m.LongFIFO[dev][q] _ (occ < q AND looksLong) -- fill -- OR (occ <= q AND looksLong AND st.s.DNewGrant4[dev]) -- fill -- OR (occ >= q AND st.s.LongFIFO[dev][q] AND NOT st.s.DNewGrant4[dev]) -- hold -- OR (occ > q AND (q < LAST[ReqCount]) AND st.s.LongFIFO[dev][q+1] AND st.s.DNewGrant4[dev]) -- shift -- ; ENDLOOP; -- q ENDLOOP; -- dev st.m.LGrantHL _ st.s.HiPGrant3; }; EncodeUnary8: PROC [ a: ARRAY [0..8) OF BOOL ] RETURNS [ c: [0..8) ] = { FOR cv: [0..8) IN [0..8) DO IF a[cv] THEN {c _ cv; RETURN}; ENDLOOP; c _ 0; }; EncodeUnary7: PROC [ a: ARRAY [0..7) OF BOOL ] RETURNS [ c: [0..8) ] = { FOR cv: [0..7) IN [0..7) DO IF a[cv] THEN {c _ cv+1; RETURN}; ENDLOOP; c _ 0; }; Pipe1: PROC = { FOR dev: Devices IN Devices DO <> pr: PriorityRec; TRUSTED { pr _ LOOPHOLE[p[st.DPriority][dev].c] }; SELECT TRUE FROM st.m.RqCtrs[dev][H] > 0 => { st.m.RqPrior1[dev] _ pr.hiP; st.m.RqInfo1[dev] _ [H, IF pr.hiLong THEN long5 ELSE short2]; }; st.m.RqCtrs[dev][L] > 0 => { st.m.RqPrior1[dev] _ pr.loP; st.m.RqInfo1[dev] _ [L, IF pr.loLong THEN long5 ELSE short2]; }; ENDCASE => { st.m.RqPrior1[dev] _ NoRequestPriority; st.m.RqInfo1[dev] _ []; }; IF (NOT pr.nFIFOEna) AND (NOT st.m.LongFIFO[dev][0]) THEN st.m.RqInfo1[dev].len _ short2; st.m.Hold[dev] _ (SELECT st.s.RequestOutBI[dev] FROM ORD[DevReqCode[release]] => FALSE, ORD[DevReqCode[seize]] => TRUE, ENDCASE => st.s.Hold[dev]); ENDLOOP; -- dev FOR pr: Priority IN Priority DO st.m.DevRovers1[pr] _ (SELECT TRUE FROM st.s.ArbReset => 0, st.s.LclGrant4 AND pr=st.s.BstArbClaim4 => EncodeUnary8[st.s.DNewGrant4], ENDCASE => st.m.DevRovers1[pr]); ENDLOOP; }; Pipe2: PROC = { minP: Priority; anyHold: BOOL; <> anyHold _ FALSE; minP _ NoRequestPriority; FOR dev: Devices IN Devices DO minP _ MIN[minP, st.s.RqPrior1[dev]]; IF st.s.Hold[dev] THEN { anyHold _ TRUE; minP _ MIN[minP, HoldPriority]; }; ENDLOOP; FOR dev: OtherDevices IN OtherDevices DO st.m.ClaimsHi2[dev] _ (st.s.DevRovers1[st.s.RqPrior1[dev]] <= dev); ENDLOOP; st.m.ArbReq2 _ (SELECT TRUE FROM NOT st.s.LclGrant4 => minP, anyHold => HoldPriority, ENDCASE => NoRequestPriority ); FOR dev: Devices IN Devices DO st.m.AmongBest2[dev] _ st.s.RqPrior1[dev] <= minP; ENDLOOP; st.m.DRQInfo2 _ st.s.RqInfo1; }; Pipe3: PROC = { HotDevice: PROC [ dev: Devices ] RETURNS [ hot: BOOL ] = INLINE { hot _ st.s.AmongBest2[dev] AND (dev > 0) AND st.s.ClaimsHi2[dev-1]; }; anyHi, ffzHi, ffzLo: BOOL _ FALSE; TRUSTED { st.m.LongGrant3 _ LOOPHOLE[0]; st.m.HiPGrant3 _ LOOPHOLE[0]; }; FOR dev: Devices IN Devices DO anyHi _ anyHi OR HotDevice[dev]; ENDLOOP; FOR dev: Devices IN Devices DO st.m.BestDev3[dev] _ (NOT ffzHi AND HotDevice[dev]) OR (NOT anyHi AND NOT ffzLo AND st.s.AmongBest2[dev]); IF st.m.BestDev3[dev] THEN [len: st.m.LongGrant3, type: st.m.HiPGrant3] _ st.s.DRQInfo2[dev]; ffzHi _ ffzHi OR HotDevice[dev]; ffzLo _ ffzLo OR st.s.AmongBest2[dev]; ENDLOOP; FOR a: OtherArbiters IN OtherArbiters DO st.m.AClaimsHi3[a] _ (st.s.ArbRovers6[st.s.ArbReq2] <= a); ENDLOOP; st.m.ThisArbIn3 _ (IF st.s.LclGrant4 THEN NvrMind[st.s.ArbReq2] ELSE st.s.ArbReq2); st.m.ArbRovers3 _ st.s.ArbRovers6; }; Pipe4: PROC = { oap, oapFiltered: ARRAY OtherArbiters OF Priority; otherWins: BOOL _ FALSE; <<>> <> st.m.NoHold4 _ (NOT st.s.LclGrant5) OR (st.s.ThisArbIn3 > HoldPriority); st.m.BstArbClaim4 _ st.s.ThisArbIn3; FOR a: OtherArbiters IN OtherArbiters DO oap[a] _ 7-st.s.OtherArbInBI[a]; oapFiltered[a] _ (IF st.s.BestArb5[a] THEN NoRequestPriority ELSE oap[a]); otherWins _ otherWins OR (oapFiltered[a] < st.s.ThisArbIn3) OR <> ((oapFiltered[a] = st.s.ThisArbIn3) AND st.s.AClaimsHi3[a]); <> st.m.BstArbClaim4 _ MIN[st.m.BstArbClaim4, oapFiltered[a]]; st.m.NoHold4 _ st.m.NoHold4 AND ((NOT st.s.BestArb5[a]) OR (oap[a] > HoldPriority)); ENDLOOP; <> st.m.GntPoss4 _ NOT st.m.GGrant5 AND NOT st.s.BusyInBI AND NOT st.s.StopActBI; st.m.LclGrant4 _ st.m.GntPoss4 AND RealReq[st.s.ThisArbIn3] AND NOT otherWins AND st.m.NoHold4; st.m.LLGrant4 _ st.m.LclGrant4 AND (st.s.LongGrant3 = long5); <> FOR dev: Devices IN Devices DO st.m.DNewGrant4[dev] _ st.s.BestDev3[dev] AND st.m.LclGrant4; st.m.Grant4[dev] _ st.m.DNewGrant4[dev] OR (NOT st.m.GntPoss4 AND st.s.Grant4[dev]); ENDLOOP; <> FOR a: Arbiters IN Arbiters DO st.m.AmgBest4[a] _ (IF a=0 THEN st.s.ThisArbIn3 ELSE oapFiltered[a-1]) <= st.m.BstArbClaim4; ENDLOOP; FOR a: OtherArbiters IN OtherArbiters DO st.m.ClaimsHi4[a] _ (st.s.ArbRovers3[oapFiltered[a]] <= a); ENDLOOP; }; Pipe5: PROC = { AmgBest: PROC [ a: OtherArbiters ] RETURNS [ BOOL ] = INLINE { RETURN[st.s.AmgBest4[a+1]]; -- [0] is this arbiter }; anyHi, ffzHi: BOOL _ FALSE; ffzLo: BOOL _ st.s.AmgBest4[0]; st.m.LclGrant5 _ st.s.LclGrant4; st.m.GGrant5 _ RealReq[st.s.BstArbClaim4] AND st.s.NoHold4 AND st.s.GntPoss4; FOR a: OtherArbiters IN OtherArbiters DO -- this arbiter never ClaimsHi anyHi _ anyHi OR (AmgBest[a] AND st.s.ClaimsHi4[a]); ENDLOOP; FOR a: OtherArbiters IN OtherArbiters DO st.m.BestArb5[a] _ (st.m.GGrant5 AND NOT ffzHi AND (AmgBest[a] AND st.s.ClaimsHi4[a])) OR (st.m.GGrant5 AND NOT anyHi AND NOT ffzLo AND AmgBest[a]); ffzHi _ ffzHi OR (AmgBest[a] AND st.s.ClaimsHi4[a]); ffzLo _ ffzLo OR AmgBest[a]; ENDLOOP; st.m.BstArbClaim5 _ st.s.BstArbClaim4; }; Pipe6: PROC = { FOR pr: Priority IN Priority DO st.m.ArbRovers6[pr] _ (SELECT TRUE FROM st.s.ArbReset => p[st.ArbNo].c, (st.s.GGrant5 AND pr = st.s.BstArbClaim5) => EncodeUnary7[st.s.BestArb5], ENDCASE => st.s.ArbRovers6[pr]); ENDLOOP; }; GCtr: PROC = { FOR i: [0..2) IN [0..2) DO st.m.GCtr[i] _ (SELECT TRUE FROM st.m.LLGrant4 => TRUE, i < 1 => st.s.GCtr[i+1], ENDCASE => FALSE); ENDLOOP; st.m.BusyOut _ st.m.LLGrant4 OR st.s.GCtr[0]; }; BusIn; Pipe5; -- Pipe4 before Pipe4 because Pipe4 needs st.m.GGrant5 Pipe4; -- Pipe4 before Pip11 and Pipe2 because both need st.m.LclGrant4 <> Pipe0; -- Pipe0 before Pipe1 because Pipe1 needs st.m.RqCtrs and st.m.LongFIFO Pipe1; Pipe2; Pipe3; Pipe6; GCtr; BusOut; }; -- clock low FOR dev: Devices IN Devices DO DynaBusDrive[p[st.nGrant][dev], st.s.GrantBO[dev]]; ENDLOOP; DynaBusDrive[p[st.nHiPGrant], st.s.HiPGrantBO]; DynaBusDrive[p[st.nLongGrant], st.s.LongGrantBO]; FOR i: NAT IN [0..3) DO DynaBusDrive[p[st.nArbReqOut][i], BitOps.EBFW[st.s.ArbReqOutBO, i, 3]]; ENDLOOP; DynaBusDrive[p[st.nBusyOut], st.s.BusyOutBO]; DynaBusDrive[p[st.nStartGrant], st.s.StartGrantBO]; FOR pr: Priority IN Priority DO -- debugging output p[st.ArbRovers6][pr].c _ st.s.ArbRovers6[pr]; ENDLOOP; <> p[st.nBusyIn].b _ TRUE; p[st.nStopAct].b _ TRUE; FOR a: Arbiters IN [0..maxArbiters-1) DO p[st.nOtherArbIn][a].c _ 7; ENDLOOP; FOR d: Devices IN Devices DO p[st.nRequestOut][d].c _ 3; ENDLOOP; }; <> ArbDBusName: ROPE = Rosemary.Register[roseClassName: "ArbDBusCode", init: ArbDBusInit, evalSimple: ArbDBusSimple]; ArbPropsLen: NAT = 4; ArbDBusInterface: Wire = WireList[LIST[ <> Seq["DBus", 7], Seq["SlotNo", 4], Seq["BdVersion", 2], Seq["nDHybridSel", 5], "DBdSel", <> Seq["DPriority", maxDevices, Seq[size: 9]], Seq["ArbNo", 3], "CkOut", "Freeze", "Rst", <> "Ck", "Vdd", "Gnd" ]]; ArbDBusCodeCT: PUBLIC PROC RETURNS [ ct: CoreCreate.CellType ] = { dBus, dPriority: NAT; ct _ CoreClasses.CreateUnspecified[name: ArbDBusName, public: ArbDBusInterface]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: ArbDBusName]; [] _ CoreFlat.CellTypeCutLabels[ct, Logic.logicCutSet]; dBus _ Ports.PortIndex[ct.public, "DBus"]; FOR j: NAT IN [DShiftCK..DSerialOut] DO [] _ Ports.InitPort[ct.public[dBus][j], b, aggregate, none]; ENDLOOP; Ports.InitPorts[ct, c, none, "SlotNo", "BdVersion"]; Ports.InitPorts[ct, b, drive, "DBdSel"]; Ports.InitPorts[ct, c, drive, "nDHybridSel"]; dPriority _ Ports.PortIndex[ct.public, "DPriority"]; FOR d: NAT IN Devices DO [] _ Ports.InitPort[ct.public[dPriority][d], c, aggregate, drive]; ENDLOOP; Ports.InitPorts[ct, c, drive, "ArbNo"]; Ports.InitPorts[ct, b, drive, "CkOut"]; Ports.InitPorts[ct, b, drive, "Rst"]; Ports.InitPorts[ct, b, drive, "Freeze"]; Ports.InitPorts[ct, b, none, "Ck", "Vdd", "Gnd"]; }; ArbiterState: TYPE = REF ArbiterStateRec; ArbiterStateRec: TYPE = RECORD [ DBus, SlotNo, BdVersion, nDHybridSel, DBdSel, DPriority, ArbNo, Rst, Freeze, CkOut, Ck: NAT _ LAST[NAT], lastCk, lastDCk : BOOL _ TRUE, m, s: MSRec, -- sync with Ck dm, ds: ArbDMSRec -- asynch state <<.. master (loads during clock low) / slave (transfers out when clock goes high)>> <> ]; standardDevPriority: BitOps.BitWord _ 71H; ArbDBusInit: Rosemary.InitProc = { st: ArbiterState = (IF oldStateAny # NIL THEN NARROW[oldStateAny] ELSE NEW[ArbiterStateRec]); st.ds.DevPriority _ st.dm.DevPriority _ ALL[standardDevPriority]; -- saves a lot of initialization st.ds.ArbProps _ st.dm.ArbProps _ LOOPHOLE[ArbProps[arbNo: 0, hySelDec: TRUE]]; [st.DBus] _ Ports.PortIndexes[cellType.public, "DBus"]; [st.SlotNo, st.BdVersion, st.nDHybridSel, st.DBdSel] _ Ports.PortIndexes[cellType.public, "SlotNo", "BdVersion", "nDHybridSel", "DBdSel"]; [st.DPriority, st.ArbNo, st.Rst, st.Freeze] _ Ports.PortIndexes[cellType.public, "DPriority", "ArbNo", "Rst", "Freeze"]; [st.CkOut, st.Ck] _ Ports.PortIndexes[cellType.public, "CkOut", "Ck"]; stateAny _ st; }; DBusAddr: TYPE = MACHINE DEPENDENT RECORD [ board (0: 0..3): [0..16), hybrid (0: 4..7): [0..16), interface (0: 8..10): [0..8), chip (0: 11..12): [0..4), path (0: 13..15): [0..8) ]; ArbProps: TYPE = MACHINE DEPENDENT RECORD [ unused (0: 0..11): [0..4096) _ 0, arbNo (0: 12..14): [0..8), hySelDec(0: 15..15): BOOL ]; MSRec: TYPE = RECORD [ Reset, Freeze: ARRAY [0..2) OF BOOL _ ALL[FALSE] ]; ArbDMSRec: TYPE = RECORD [ DBAddr: BitOps.BitWord _ 0, -- has structure DBusAddr SignatureShadow: BitOps.BitWord _ 0, DevPriority: ARRAY Devices OF BitOps.BitWord _ ALL[0], ArbProps: BitOps.BitWord _ 0, -- has structure ArbProps BoardVersionShadow: BitOps.BitWord _ 0 ]; ArbDBusSimple: PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL] -- Rosemary.EvalProc -- = { st: ArbiterState _ NARROW[stateAny]; dba: DBusAddr; thisBd: BOOL; IF p[st.DBus][DShiftCK].b AND NOT st.lastDCk THEN st.ds _ st.dm; TRUSTED {dba _ LOOPHOLE[st.ds.DBAddr]}; thisBd _ NOT p[st.DBus][DAddress].b AND (dba.board = p[st.SlotNo].c); IF NOT p[st.DBus][DShiftCK].b THEN { -- DShiftCK low, compute DBus master stages dsi: BOOL = p[st.DBus][DSerialIn].b; st.dm _ st.ds; SELECT TRUE FROM p[st.DBus][DAddress].b => { st.dm.DBAddr _ BitOps.IBIW[ source: dsi, container: BitOps.WShift[st.ds.DBAddr, 1, 16], bitPosition: 15]; st.dm.SignatureShadow _ 5041H; -- type 1, revision 1 }; thisBd AND (dba.hybrid = 0) -- the arbiter itself -- => { st.dm.BoardVersionShadow _ BitOps.WShift[st.ds.BoardVersionShadow, 1, 2]; SELECT dba.path FROM 0 => st.dm.SignatureShadow _ BitOps.IBIW[ source: dsi, container: BitOps.WShift[st.ds.SignatureShadow, 1, 16], bitPosition: 15, containerWidth: 16]; 1 => FOR d: Devices IN Devices DO st.dm.DevPriority[d] _ BitOps.IBIW[ source: (IF d=LAST[Devices] THEN dsi ELSE BitOps.EBFW[st.ds.DevPriority[d+1], 0, PriorityRecLen]), container: BitOps.WShift[st.ds.DevPriority[d], 1, PriorityRecLen], bitPosition: PriorityRecLen-1, containerWidth: PriorityRecLen]; ENDLOOP; 2 => st.dm.ArbProps _ BitOps.IBIW[ source: dsi, container: BitOps.WShift[st.ds.ArbProps, 1, ArbPropsLen], bitPosition: ArbPropsLen-1, containerWidth: ArbPropsLen]; ENDCASE => NULL; }; thisBd -- other hybrid on this board -- => st.dm.BoardVersionShadow _ p[st.BdVersion].c; ENDCASE => NULL; }; p[st.DBus][DSerialOut].d _ (IF (thisBd AND (dba.hybrid = 0)) THEN drive ELSE driveWeak); TRUSTED { p[st.DBus][DSerialOut].b _ (IF (thisBd AND (dba.hybrid = 0)) THEN (SELECT dba.path FROM 0 => BitOps.EBFW[st.ds.SignatureShadow, 0, 16], 1 => BitOps.EBFW[st.ds.DevPriority[maxDevices-1], 0, PriorityRecLen], 2 => BitOps.EBFW[st.ds.ArbProps, 0, ArbPropsLen], 3 => BitOps.EBFW[st.ds.BoardVersionShadow, 0, 2], ENDCASE => FALSE) ELSE TRUE) }; p[st.nDHybridSel].c _ 01FH - (SELECT BitOps.EBFW[st.ds.ArbProps, ArbPropsLen-1, ArbPropsLen] FROM TRUE -- decoded hybrid select -- => (IF thisBd AND dba.hybrid IN [1..5] THEN BitOps.IBIW[source: TRUE, container: 0, bitPosition: dba.hybrid-1, containerWidth: 5] ELSE 0), FALSE -- encoded -- => BitOps.ECFW[container: st.ds.DBAddr, fieldPosition: 4, fieldWidth: 5], ENDCASE => ERROR); p[st.DBdSel].b _ thisBd; p[st.ArbNo].c _ BitOps.ECFW[st.ds.ArbProps, 0, 3, ArbPropsLen]; FOR d: Devices IN Devices DO p[st.DPriority][d].c _ BitOps.ECFW[ container: st.ds.DevPriority[d], fieldPosition: 0, fieldWidth: PriorityRecLen, containerWidth: PriorityRecLen]; ENDLOOP; st.lastDCk _ p[st.DBus][DShiftCK].b; IF p[st.Ck].b AND NOT st.lastCk THEN st.s _ st.m; IF NOT p[st.Ck].b THEN { st.m.Freeze[0] _ p[st.DBus][DShiftCK].b; st.m.Reset[0] _ p[st.DBus][DShiftCK].b; st.m.Freeze[1] _ st.s.Freeze[0]; st.m.Reset[1] _ st.s.Reset[0]; }; p[st.CkOut].b _ st.lastCk _ p[st.Ck].b; p[st.Rst].b _ st.s.Reset[1]; p[st.Freeze].b _ st.s.Freeze[1]; }; END.