ArbiterImpl.mesa
Copyright c 1986 by Xerox Corporation. All rights reserved.
McCreight May 27, 1987 11:41:13 am PDT
DIRECTORY Arbiter, BitOps, CoreClasses, CoreCreate, CoreFlat, CoreOps, Ports, Rope, Rosemary;
ArbiterImpl: CEDAR PROGRAM
IMPORTS BitOps, CoreCreate, CoreClasses, CoreFlat, Ports, Rosemary
EXPORTS Arbiter
= BEGIN OPEN Arbiter, CoreCreate;
logicCutSet: Rope.ROPE = "Logic"; -- should be Logic.logicCutSet, actually
Arbiter
ArbiterName: ROPE = Rosemary.Register[roseClassName: "ArbiterTop", init: ArbiterInit, evalSimple: ArbiterSimple];
ArbiterInterface: Wire = WireList[LIST[
Requesting devices
Seq["nDReq", maxDevices, Seq[size: 2]], -- request ports, radial
Seq["nDGrant", maxDevices], -- grant ports, radial
"nBDHi", -- status, bussed
"nBDLong",
Backpanel
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
Debugging
Seq["ArbRovers6", 8, Seq[size: 3]], -- not wired out to real pins
OR'ing services
"nDOwner", "nBOwnerOut", "nBOwnerIn", "nSysOwner",
Seq["nDShared", 8], "nBSharedOut", Seq["nBSharedIn", 8], "nSysShared",
Seq["nDStop", 8], "nBStopOut", Seq["nBStopIn", 8], "nSysStop",
DBus
Seq["DPriority", maxDevices, Seq[size: 9]],
Seq["ArbNo", 3],
"Rst",
Misc
"Ck", "Vdd", "Gnd"
]];
ArbExceptDBusCodeCT: PUBLIC PROC RETURNS [ ct: CoreCreate.CellType ] = {
dreq, dgrant, arbReqOut, otherArbIn, dPriority, shared, stop, arbRovers6: NAT;
ct ← CoreClasses.CreateUnspecified[name: ArbiterName, public: ArbiterInterface];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: ArbiterName];
[] ← CoreFlat.CellTypeCutLabels[ct, logicCutSet];
dreq ← Ports.PortIndex[ct.public, "nDReq"];
dgrant ← Ports.PortIndex[ct.public, "nDGrant"];
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, "nBDHi", "nBDLong"];
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"];
shared ← Ports.PortIndex[ct.public, "nDShared"];
stop ← Ports.PortIndex[ct.public, "nDStop"];
FOR d: Devices IN Devices DO
[] ← Ports.InitPort[ct.public[shared][d], b, aggregate, driveWeak];
[] ← Ports.InitPort[ct.public[stop][d], b, aggregate, driveWeak];
ENDLOOP;
shared ← Ports.PortIndex[ct.public, "nBSharedIn"];
stop ← Ports.PortIndex[ct.public, "nBStopIn"];
FOR a: Arbiters IN Arbiters DO
[] ← Ports.InitPort[ct.public[shared][a], b, aggregate, driveWeak];
[] ← Ports.InitPort[ct.public[stop][a], b, aggregate, driveWeak];
ENDLOOP;
Ports.InitPorts[ct, b, driveWeak, "nDOwner", "nBOwnerIn"];
Ports.InitPorts[ct, b, drive, "nBOwnerOut", "nSysOwner"];
Ports.InitPorts[ct, b, drive, "nBSharedOut", "nSysShared"];
Ports.InitPorts[ct, b, drive, "nBStopOut", "nSysStop"];
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"];
};
ArbiterState: TYPE = REF ArbiterStateRec;
ArbiterStateRec: TYPE = RECORD [
nDReq, nDGrant, nBDHi, nBDLong, nArbReqOut, nOtherArbIn,
nBusyOut, nBusyIn, nStartGrant, nStopAct,
ArbRovers6,
nDOwner, nBOwnerOut, nBOwnerIn, nSysOwner,
nDShared, nBSharedOut, nBSharedIn, nSysShared,
nDStop, nBStopOut, nBStopIn, nSysStop,
DPriority, ArbNo, Rst,
Ck: NATLAST[NAT],
lastCk, lastDCk: BOOLTRUE,
sm, ss: ArbSharedMSRec,
m, s: ArbCoreMSRec
.. master (loads during clock low) / slave (transfers out when clock goes high)
State kept in master/slave form to avoid feedback races..
];
ArbiterInit: Rosemary.InitProc = {
st: ArbiterState = (IF oldStateAny # NIL THEN NARROW[oldStateAny] ELSE NEW[ArbiterStateRec]);
{OPEN st;
[nDReq, nDGrant, nBDHi, nBDLong, nArbReqOut, nOtherArbIn] ← Ports.PortIndexes[cellType.public, "nDReq", "nDGrant", "nBDHi", "nBDLong", "nArbReqOut", "nOtherArbIn"];
[nBusyOut, nBusyIn, nStartGrant, nStopAct] ← Ports.PortIndexes[cellType.public, "nBusyOut", "nBusyIn", "nStartGrant", "nStopAct"];
[ArbRovers6] ← Ports.PortIndexes[cellType.public, "ArbRovers6"];
[nDOwner, nBOwnerOut, nBOwnerIn, nSysOwner] ← Ports.PortIndexes[cellType.public, "nDOwner", "nBOwnerOut", "nBOwnerIn", "nSysOwner"];
[nDShared, nBSharedOut, nBSharedIn, nSysShared] ← Ports.PortIndexes[cellType.public, "nDShared", "nBSharedOut", "nBSharedIn", "nSysShared"];
[nDStop, nBStopOut, nBStopIn, nSysStop] ← Ports.PortIndexes[cellType.public, "nDStop", "nBStopOut", "nBStopIn", "nSysStop"];
[DPriority, ArbNo, Rst, Ck] ← Ports.PortIndexes[cellType.public, "DPriority", "ArbNo", "Rst", "Ck"];
};
stateAny ← st;
};
ArbiterSimple: PROC [p: Ports.Port, stateAny: REF ANY] -- Rosemary.EvalProc -- = {
st: ArbiterState ← NARROW[stateAny];
ArbShared[p, st];
ArbCore[p, st];
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 [
DOwner: BOOLFALSE,
BOwnerOut: BOOLFALSE,
BOwnerIn: BOOLFALSE,
SysOwner: BOOLFALSE,
DShared: ARRAY Devices OF BOOLALL[FALSE],
BSharedOut: BOOLFALSE,
BSharedIn: ARRAY Arbiters OF BOOLALL[FALSE],
SysShared: BOOLFALSE,
DStop: ARRAY Devices OF BOOLALL[FALSE],
BStopOut: BOOLFALSE,
BStopIn: ARRAY Arbiters OF BOOLALL[FALSE],
SysStop: BOOLFALSE
];
ArbShared: PROC [p: Ports.Port, stateAny: REF ANY] -- Rosemary.EvalProc -- = {
st: ArbiterState ← 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.DOwner ← NOT p[st.nDOwner].b;
st.sm.BOwnerOut ← st.ss.DOwner;
st.sm.BOwnerIn ← NOT p[st.nBOwnerIn].b;
st.sm.SysOwner ← st.ss.BOwnerIn;
st.sm.BSharedOut ← FALSE;
st.sm.BStopOut ← FALSE;
FOR d: Devices IN Devices DO
st.sm.DShared[d] ← NOT p[st.nDShared][d].b;
st.sm.BSharedOut ← st.sm.BSharedOut OR st.ss.DShared[d];
st.sm.DStop[d] ← NOT p[st.nDStop][d].b;
st.sm.BStopOut ← st.sm.BStopOut OR st.ss.DStop[d];
ENDLOOP;
st.sm.SysShared ← FALSE;
st.sm.SysStop ← FALSE;
FOR a: Arbiters IN Arbiters DO
st.sm.BSharedIn[a] ← NOT p[st.nBSharedIn][a].b;
st.sm.SysShared ← st.sm.SysShared OR st.ss.BSharedIn[a];
st.sm.BStopIn[a] ← NOT p[st.nBStopIn][a].b;
st.sm.SysStop ← st.sm.SysStop OR st.ss.BStopIn[a];
ENDLOOP;
};
DynaBusDrive[p[st.nBOwnerOut], st.ss.BOwnerOut];
DynaBusDrive[p[st.nSysOwner], st.ss.SysOwner];
DynaBusDrive[p[st.nBSharedOut], st.ss.BSharedOut];
DynaBusDrive[p[st.nSysShared], st.ss.SysShared];
DynaBusDrive[p[st.nBStopOut], st.ss.BStopOut];
DynaBusDrive[p[st.nSysStop], st.ss.SysStop];
Passive pull-up
p[st.nDOwner].b ← TRUE;
p[st.nBOwnerIn].b ← TRUE;
FOR d: Devices IN Devices DO
p[st.nDShared][d].b ← TRUE;
p[st.nDStop][d].b ← TRUE;
ENDLOOP;
FOR a: Arbiters IN Arbiters DO
p[st.nBSharedIn][a].b ← TRUE;
p[st.nBStopIn][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 [
The following assignment of state to pipe stage can be misleading for feedback loops.
Bus in
OtherArbInBI: ARRAY [0..maxArbiters-1) OF [0..8) ← ALL[0],
BusyInBI: BOOLFALSE,
StopActBI: BOOLFALSE,
DReqBI: ARRAY Devices OF [0..4) ← ALL[0],
Bus out
BDLongBO: BOOLFALSE,
BDHiBO: BOOLFALSE,
DGrantBO: ARRAY Devices OF BOOLALL[FALSE],
ArbReqOutBO: [0..8) ← 0,
BusyOutBO: BOOLTRUE,
StartGrantBO: BOOLTRUE,
Pipe stage 0
LGrantHL: DevReqType,
RqCtrs: ARRAY Devices OF ARRAY DevReqType OF ReqCount,
LongFIFO: ARRAY Devices OF ARRAY ReqCount OF BOOLALL[ALL[FALSE]],
Pipe Stage 1
RqPrior1: ARRAY Devices OF Priority,
RqInfo1: ARRAY Devices OF DevRqInfo,
Hold: ARRAY Devices OF BOOLALL[TRUE],
DevRovers1: ARRAY Priority OF Devices ← ALL[0],
Pipe Stage 2
ArbReq2: Priority,
AmongBest2: ARRAY Devices OF BOOLALL[TRUE],
DRQInfo2: ARRAY Devices OF DevRqInfo,
ClaimsHi2: ARRAY OtherDevices OF BOOLALL[TRUE],
device 0 never claims high
Pipe Stage 3
ThisArbIn3: Priority,
BestDev3: ARRAY Devices OF BOOL, -- at most one true
BDLong3: PacketLength,
BDHi3: DevReqType,
ArbRovers3: ARRAY Priority OF Arbiters, -- pipe delay of arbRovers
AClaimsHi3: ARRAY OtherArbiters OF BOOLALL[TRUE],
Pipe Stage 4
LLGrant4: BOOLTRUE, -- not latched in hardware
LclGrant4: BOOLTRUE,
NoHold4: BOOLTRUE,
GntPoss4: BOOLTRUE,
DNewGrant4: ARRAY Devices OF BOOLALL[TRUE],
DGrant4: ARRAY Devices OF BOOLALL[TRUE],
BstArbClaim4: Priority,
AmgBest4: ARRAY Arbiters OF BOOLALL[TRUE],
ClaimsHi4: ARRAY OtherArbiters OF BOOLALL[TRUE],
Pipe Stage 5
LclGrant5: BOOLTRUE,
GGrant5: BOOLTRUE,
BestArb5: ARRAY OtherArbiters OF BOOLALL[TRUE],
BstArbClaim5: Priority,
Pipe Stage 6
ArbRovers6: ARRAY Priority OF Arbiters,
Grant cycle counter
BusyOut: BOOLTRUE, -- not latched in hardware
GCtr: ARRAY [0..2) OF BOOLALL[TRUE]
];
ArbCore: PROC [p: Ports.Port, stateAny: REF ANY] -- Rosemary.EvalProc -- = {
st: ArbiterState ← 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.DReqBI[d] ← 3-p[st.nDReq][d].c;
ENDLOOP;
};
BusOut: PROC = {
FOR dev: Devices IN Devices DO
st.m.DGrantBO[dev] ← st.m.DGrant4[dev];
ENDLOOP;
st.m.BDHiBO ← st.m.BDHi3 = H;
st.m.BDLongBO ← st.m.BDLong3 = 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.DReqBI[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 p[st.Rst].b 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.DReqBI[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.BDHi3;
};
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
Warning: combinatorial from Pipe0
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.DReqBI[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
p[st.Rst].b => 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;
Find the minimum (best) priority request among all local device requests. Include any Hold as a request at HoldPriority. If we are recovering from a local grant, request either at HoldPriority or NoRequestPriority based on Hold.
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: BOOLFALSE;
TRUSTED {
st.m.BDLong3 ← LOOPHOLE[0];
st.m.BDHi3 ← 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.BDLong3, type: st.m.BDHi3] ← 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: BOOLFALSE;
See whether any other arbiter is making a higher-priority request than this one, or the same priority and between the rover and this arbiter.
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
Another arbiter has better priority
((oapFiltered[a] = st.s.ThisArbIn3) AND st.s.AClaimsHi3[a]);
The rover points ahead of another arbiter with equal priority
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;
Decide whether a grant will happen next cycle.
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.BDLong3 = long5);
Gate the individual device grant wires.
FOR dev: Devices IN Devices DO
st.m.DNewGrant4[dev] ← st.s.BestDev3[dev] AND st.m.LclGrant4;
st.m.DGrant4[dev] ← st.m.DNewGrant4[dev] OR (NOT st.m.GntPoss4 AND st.s.DGrant4[dev]);
ENDLOOP;
Pipe information forward to help change arbiter rover.
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: BOOLFALSE;
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
p[st.Rst].b => 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
Pipe4 before GCtr because GCtr needs st.m.LLGrant4
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.nDGrant][dev], st.s.DGrantBO[dev]];
ENDLOOP;
DynaBusDrive[p[st.nBDHi], st.s.BDHiBO];
DynaBusDrive[p[st.nBDLong], st.s.BDLongBO];
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;
Passive pull-up
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.nDReq][d].c ← 3;
ENDLOOP;
};
END.