ArbiterImpl:
CEDAR
PROGRAM
IMPORTS BitOps, CoreCreate, CoreClasses, CoreFlat, CoreOps, CoreProperties, Logic, Ports, Rosemary
EXPORTS Arbiter
= BEGIN OPEN Arbiter, CoreCreate;
ArbNov87A:
PUBLIC BOOL ←
FALSE;
-- 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:
PRA ←
ALL[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
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: 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",
]];
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: 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)
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: 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];
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: BOOL ← FALSE,
StopActBI: BOOL ← FALSE,
RequestOutBI: ARRAY Devices OF [0..4) ← ALL[0],
ArbReset: BOOL ← FALSE,
Bus out
LongGrantBO: BOOL ← FALSE,
HiPGrantBO: BOOL ← FALSE,
GrantBO: ARRAY Devices OF BOOL ← ALL[FALSE],
ArbReqOutBO: [0..8) ← 0,
BusyOutBO: BOOL ← TRUE,
StartGrantBO: BOOL ← TRUE,
Pipe stage 0
LGrantHL: DevReqType,
RqCtrs: ARRAY Devices OF ARRAY DevReqType OF ReqCount,
LongFIFO: ARRAY Devices OF ARRAY ReqCount OF BOOL ← ALL[ALL[FALSE]],
Pipe Stage 1
RqPrior1: ARRAY Devices OF Priority,
RqInfo1: ARRAY Devices OF DevRqInfo,
Hold: ARRAY Devices OF BOOL ← ALL[TRUE],
DevRovers1: ARRAY Priority OF Devices ← ALL[0],
Pipe Stage 2
ArbReq2: Priority,
AmongBest2: ARRAY Devices OF BOOL ← ALL[TRUE],
DRQInfo2: ARRAY Devices OF DevRqInfo,
ClaimsHi2:
ARRAY OtherDevices
OF
BOOL ←
ALL[
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 BOOL ← ALL[TRUE],
Pipe Stage 4
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],
StopAct4: BOOL ← TRUE, -- 19 Jan 88
Pipe Stage 5
LclGrant5: BOOL ← TRUE,
GGrant5: BOOL ← TRUE,
BestArb5: ARRAY OtherArbiters OF BOOL ← ALL[TRUE],
BstArbClaim5: Priority,
Pipe Stage 6
ArbRovers6: ARRAY Priority OF Arbiters,
Grant cycle counter
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];
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: 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;
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: 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 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",
]];
ArbDBusCodeCT:
PUBLIC
PROC [arbNo:
INT ← 0, pra:
PRA ←
ALL[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: 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)
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: PRA ← ALL[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 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]
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.