ArbiterImpl.mesa
Copyright c 1986 by Xerox Corporation. All rights reserved.
McCreight May 27, 1987 11:41:13 am PDT
Last Edited by: McCreight January 19, 1988 2:00:02 pm PST
Don Curry September 7, 1988 8:11:41 pm PDT
DIRECTORY Arbiter, BitOps, CoreClasses, CoreCreate, CoreFlat, CoreOps, CoreProperties, Logic, Ports, Rope, Rosemary;
ArbiterImpl: CEDAR PROGRAM
IMPORTS BitOps, CoreCreate, CoreClasses, CoreFlat, CoreOps, CoreProperties, Logic, Ports, Rosemary
EXPORTS Arbiter
= BEGIN OPEN Arbiter, CoreCreate;
ArbNov87A: PUBLIC BOOLFALSE; -- 19 Jan 88
implement the first fabricated version, or the current version.
This comes in three parts. The first makes the record cell for ArbInFrame. The second is the functional specification for ArbExceptDBus. And the third is the functional specification for DBusSect.
ArbInFrame
ArbInFrameInterface: Wire = WireList[LIST[
"nBusyIn", -- down the left side
"nBusyOut",
"nStopAct",
"nBSStopOut",
"nBSharedOut",
"nBOwnerOut",
"nStartGrant",
Seq["OtherArbIn", maxArbiters-1, Seq[size: 3]],
Seq["ArbReqOut", 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 [arbNo: INT ← 0, pra: PRAALL[DefaultPriority]]
RETURNS [ ct: CoreCreate.CellType ] = {
inst: CoreCreate.CellInstance;
instances: CellInstances ← LIST[];
publics: Wire = ArbInFrameInterface;
internals: Wire = WireList[LIST[
"Rst",
Seq["DPriority", maxDevices, Seq[size: 9]],
Seq["ArbNo", 3],
Seq["ArbRovers6", 8, Seq[size: 3]],
]];
arbCT: CellType ← ArbExceptDBusCodeCT[];
arbDBusCT: CellType ← ArbDBusCodeCT[arbNo, pra];
ossIn: Wire ← CoreOps.FindWire[arbCT.public, "OSSIn"];
ossOut: Wire ← CoreOps.FindWire[arbCT.public, "OSSOut"];
pas: LIST OF PALIST[
[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: Logic.Inv[],
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: Logic.Rec2V[],
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"];
instances ← CONS[inst, instances];
ct ← CoreCreate.Cell[public: publics, onlyInternal: internals, instances: instances,
name: "ArbInFrame"];
};
ArbExceptDBus
ArbExceptDBusName: ROPE = Rosemary.Register[roseClassName: "ArbExceptDBus", init: ArbExceptDBusInit, evalSimple: ArbExceptDBusSimple, scheduleIfClockEval: TRUE];
ArbExceptDBusInterface: Wire = WireList[LIST[
Requesting devices
Seq["nRequestOut", maxDevices, Seq[size: 2]], -- request ports, radial
Seq["nGrant", maxDevices], -- grant ports, radial
"nHiPGrant", -- status, bussed
"nLongGrant",
Backpanel
Seq["ArbReqOut", 3], -- this arbiter's request to others
Seq["OtherArbIn", 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
OSSIn
WireList[LIST["nOwnerOut", "nBOwnerIn",
Seq["nSharedOut", 8], Seq["nBSharedIn", 8],
Seq["nSStopOut", 8], Seq["nBSStopIn", 8]], "OSSIn"],
OSSOut
WireList[LIST["nBOwnerOut", "nOwnerIn",
"nBSharedOut", "nSharedIn",
"nBSStopOut","nSStopIn"], "OSSOut"],
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, 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, "ArbReqOut"];
FOR j: NAT IN [0..3) DO
[] ← Ports.InitPort[ct.public[arbReqOut][j], b, aggregate, driveWeak];
ENDLOOP;
otherArbIn ← Ports.PortIndex[ct.public, "OtherArbIn"];
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, ArbReqOut, OtherArbIn,
nBusyOut, nBusyIn, nStartGrant, nStopAct,
ArbRovers6,
OSSIn, OSSOut,
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..
];
ArbExceptDBusInit: Rosemary.InitProc = {
st: ArbExceptDBusState = (IF oldStateAny # NIL THEN NARROW[oldStateAny] ELSE NEW[ArbExceptDBusStateRec]);
{OPEN st;
[nRequestOut, nGrant, nHiPGrant, nLongGrant, ArbReqOut, OtherArbIn] ← Ports.PortIndexes[cellType.public, "nRequestOut", "nGrant", "nHiPGrant", "nLongGrant", "ArbReqOut", "OtherArbIn"];
[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] RETURNS [ stateValue: Ports.LevelSequence ← NIL ]-- Rosemary.EvalProc -- = {
st: ArbExceptDBusState ← NARROW[stateAny];
ArbShared[p, st, clockEval];
ArbCore[p, st, clockEval];
IF ~clockEval THEN 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: BOOLFALSE,
BOwnerOut: BOOLFALSE,
BOwnerIn: BOOLFALSE,
OwnerIn: BOOLFALSE,
SharedOut: ARRAY Devices OF BOOLALL[FALSE],
BSharedOut: BOOLFALSE,
BSharedIn: ARRAY Arbiters OF BOOLALL[FALSE],
SharedIn: BOOLFALSE,
SStopOut: ARRAY Devices OF BOOLALL[FALSE],
BSStopOut: BOOLFALSE,
BSStopIn: ARRAY Arbiters OF BOOLALL[FALSE],
SStopIn: BOOLFALSE
];
ArbShared: PROC [p: Ports.Port, stateAny: REF ANY, clockEval: BOOL] -- Rosemary.EvalProc -- = {
st: ArbExceptDBusState ← NARROW[stateAny];
SELECT TRUE FROM
clockEval => NULL;
p[st.Ck].b AND NOT st.lastCk => st.ss ← st.sm;
NOT p[st.Ck].b => {
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;
};
ENDCASE => NULL;
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];
Passive pull-up
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 [
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,
RequestOutBI: ARRAY Devices OF [0..4) ← ALL[0],
ArbReset: BOOLFALSE,
Bus out
LongGrantBO: BOOLFALSE,
HiPGrantBO: BOOLFALSE,
GrantBO: 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
LongGrant3: PacketLength,
HiPGrant3: 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],
Grant4: ARRAY Devices OF BOOLALL[TRUE],
BstArbClaim4: Priority,
AmgBest4: ARRAY Arbiters OF BOOLALL[TRUE],
ClaimsHi4: ARRAY OtherArbiters OF BOOLALL[TRUE],
StopAct4: BOOLTRUE, -- 19 Jan 88
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, clockEval: BOOL] -- Rosemary.EvalProc -- = {
st: ArbExceptDBusState ← NARROW[stateAny];
SELECT TRUE FROM
clockEval => NULL;
p[st.Ck].b AND NOT st.lastCk => st.s ← st.m; -- positive-going clock edge
NOT p[st.Ck].b => { -- clock low
BusIn: PROC = {
FOR a: Arbiters IN [0..maxArbiters-1) DO
st.m.OtherArbInBI[a] ← p[st.OtherArbIn][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 ← 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
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.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;
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.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: 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] ← 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 -- ; -- 5 Oct 87
st.m.LclGrant4 ← st.m.GntPoss4 AND NOT st.s.StopActBI AND RealReq[st.s.ThisArbIn3] AND NOT otherWins AND st.m.NoHold4; -- 5 Oct 87
st.m.LLGrant4 ← st.m.LclGrant4 AND (st.s.LongGrant3 = long5);
IF NOT ArbNov87A THEN st.m.StopAct4 ← st.s.StopActBI; -- 19 Jan 88
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.Grant4[dev] ← st.m.DNewGrant4[dev] OR (NOT st.m.GntPoss4 AND st.s.Grant4[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 AND (ArbNov87A OR NOT st.s.StopAct4 -- 19 Jan 88 -- );
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
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
ENDCASE => NULL;
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.ArbReqOut][i], NOT BitOps.EBFW[st.s.ArbReqOutBO, i, 3]];
DynaBusDrive inverts; for this signal we don't want that
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.OtherArbIn][a].c ← 7;
ENDLOOP;
FOR d: Devices IN Devices DO
p[st.nRequestOut][d].c ← 3;
ENDLOOP;
};
ArbDBus
ArbDBusName: ROPE = Rosemary.Register[roseClassName: "ArbDBusCode", init: ArbDBusInit, evalSimple: ArbDBusSimple, scheduleIfClockEval: TRUE];
ArbPropsLen: NAT = 4;
ArbDBusInterface: Wire = WireList[LIST[
DBus
Seq["DBus", 7],
Seq["SlotNo", 4],
Seq["BdVersion", 2],
Seq["nDHybridSel", 5],
"DBdSel",
Interface to Arbiter
Seq["DPriority", maxDevices, Seq[size: 9]],
Seq["ArbNo", 3],
"CkOut",
"Rst",
Misc
"Ck", "Vdd", "Gnd"
]];
ArbDBusCodeCT: PUBLIC PROC [arbNo: INT ← 0, pra: PRAALL[DefaultPriority]] 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, none, "Ck", "Vdd", "Gnd"];
ct.properties ← CoreProperties.PutProp[ct.properties, $arbNo, NEW[INT ← arbNo]];
ct.properties ← CoreProperties.PutProp[ct.properties, $pra, NEW[PRA ← pra]];
};
ArbiterDBusState: TYPE = REF ArbiterDBusStateRec;
ArbiterDBusStateRec: TYPE = RECORD [
DBus, SlotNo, BdVersion, nDHybridSel, DBdSel,
DPriority, ArbNo, Rst,
CkOut, Ck: NATLAST[NAT],
lastCk, lastDCk : BOOLTRUE,
m, s: MSRec, -- sync with Ck
dm, ds: ArbDMSRec -- asynch state
.. master (loads during clock low) / slave (transfers out when clock goes high)
State kept in master/slave form to avoid feedback races..
];
ArbDBusInit: Rosemary.InitProc = {
st: ArbiterDBusState = (IF oldStateAny # NIL THEN NARROW[oldStateAny] ELSE NEW[ArbiterDBusStateRec]);
r: REF ANY;
arbNo: INT ← 0;
pra: PRAALL[DefaultPriority];
r ← CoreProperties.GetProp[cellType.properties, $arbNo];
IF r # NIL AND ISTYPE[r, REF INT] THEN arbNo ← NARROW[r, REF INT]^;
r ← CoreProperties.GetProp[cellType.properties, $pra];
IF r # NIL AND ISTYPE[r, REF PRA] THEN pra ← NARROW[r, REF PRA]^;
FOR d: Devices IN Devices DO
st.ds.DevPriority[d] ← st.dm.DevPriority[d] ← pra[d]; -- saves a lot of DBus initialization
ENDLOOP;
st.ds.ArbProps ← st.dm.ArbProps ← LOOPHOLE[ArbProps[arbNo: arbNo, 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] ← Ports.PortIndexes[cellType.public, "DPriority", "ArbNo", "Rst"];
[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: ARRAY [0..2) OF BOOLALL[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] RETURNS [ stateValue: Ports.LevelSequence ← NIL ]-- Rosemary.EvalProc -- = {
st: ArbiterDBusState ← NARROW[stateAny];
dba: DBusAddr;
thisBd: BOOL;
TRUSTED {dba ← LOOPHOLE[st.ds.DBAddr]};
thisBd ← NOT p[st.DBus][DAddress].b AND (dba.board = p[st.SlotNo].c);
SELECT TRUE FROM
clockEval => NULL;
p[st.DBus][DShiftCK].b AND NOT st.lastDCk => {
st.lastDCk ← TRUE;
st.ds ← st.dm;
};
NOT p[st.DBus][DShiftCK].b => { -- DShiftCK low, compute DBus master stages
dsi: BOOL = p[st.DBus][DSerialIn].b;
st.lastDCk ← FALSE;
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;
}; -- DShiftCK low
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[0], 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;
SELECT TRUE FROM
clockEval => NULL;
p[st.Ck].b AND NOT st.lastCk => {
st.lastCk ← TRUE;
st.s ← st.m;
};
NOT p[st.Ck].b => {
st.lastCk ← FALSE;
st.m.Reset[0] ← NOT p[st.DBus][nDReset].b;
st.m.Reset[1] ← st.s.Reset[0];
};
ENDCASE => NULL;
p[st.CkOut].b ← p[st.Ck].b;
p[st.Rst].b ← st.s.Reset[1];
};
END.