ArbDBusImpl.mesa
Copyright c 1986 by Xerox Corporation. All rights reserved.
McCreight May 15, 1987 5:26:12 pm PDT
DIRECTORY Arbiter, BitOps, CoreClasses, CoreCreate, CoreFlat, CoreOps, Ports, Rope, Rosemary;
ArbDBusImpl: 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 DBus Interface
ArbDBusName: ROPE = Rosemary.Register[roseClassName: "ArbDBusCode", init: ArbDBusInit, evalSimple: ArbDBusSimple];
ArbDBusInterface: Wire = WireList[LIST[
DBus
Seq["DBus", 7],
Seq["SlotNo", 4],
Seq["BdVersion", 2],
Seq["DHybridSel", 15],
"DBdSel",
Interface to Arbiter
Seq["DPriority", maxDevices, Seq[size: 9]],
Seq["ArbNo", 3],
"Freeze",
"Rst",
Misc
"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, 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, "DHybridSel"];
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, "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, DHybridSel, DBdSel,
DPriority, ArbNo, Rst, Freeze,
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: ArbiterState = (IF oldStateAny # NIL THEN NARROW[oldStateAny] ELSE NEW[ArbiterStateRec]);
{OPEN st;
[DBus] ← Ports.PortIndexes[cellType.public, "DBus"];
[SlotNo, BdVersion, DHybridSel, DBdSel] ← Ports.PortIndexes[cellType.public, "SlotNo", "BdVersion", "DHybridSel", "DBdSel"];
[DPriority, ArbNo, Rst, Freeze] ← Ports.PortIndexes[cellType.public, "DPriority", "ArbNo", "Rst", "Freeze"];
[Ck] ← Ports.PortIndexes[cellType.public, "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)
];
MSRec: TYPE = RECORD [
Reset, Freeze: ARRAY [0..2) OF BOOLALL[FALSE]
];
ArbDMSRec: TYPE = RECORD [
DBAddr: CARDINAL ← 0, -- has structure DBusAddr
SignatureShadow: CARDINAL ← 0,
DevPriority: ARRAY Devices OF PriorityRec,
ArbNo: [0..8) ← 0,
BoardVersionShadow: [0..3) ← 0
];
ArbDBusSimple: PROC [p: Ports.Port, stateAny: REF ANY] -- 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: [0..2) = (IF p[st.DBus][DSerialIn].b THEN 1 ELSE 0);
st.dm ← st.ds;
SELECT TRUE FROM
p[st.DBus][DAddress].b => {
st.dm.DBAddr ← BitOps.WShift[st.ds.DBAddr, 1, 16]+dsi;
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.WShift[st.ds.SignatureShadow, 1, 16]+dsi;
1 =>
FOR d: Devices IN Devices DO
TRUSTED { st.dm.DevPriority[d] ← LOOPHOLE[BitOps.WShift[LOOPHOLE[st.ds.DevPriority[d], BitOps.BitWord], 1, PriorityRecLen]+
(IF d=LAST[Devices] THEN dsi ELSE
(IF BitOps.EBFW[LOOPHOLE[st.ds.DevPriority[d+1], BitOps.BitWord], 0, PriorityRecLen] THEN 1 ELSE 0))] };
ENDLOOP;
2 => st.dm.ArbNo ← BitOps.WShift[st.ds.ArbNo, 1, 3]+dsi;
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[LOOPHOLE[st.ds.DevPriority[maxDevices-1], BitOps.BitWord], 0, PriorityRecLen],
2 => BitOps.EBFW[st.ds.ArbNo, 0, 3],
3 => BitOps.EBFW[st.ds.BoardVersionShadow, 0, 2],
ENDCASE => FALSE)
ELSE TRUE)
};
p[st.DHybridSel].c ← (IF thisBd AND dba.hybrid>0
THEN BitOps.IBIW[source: TRUE, container: 0,
bitPosition: dba.hybrid-1, containerWidth: 15]
ELSE 0);
p[st.DBdSel].b ← thisBd;
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];
};
st.lastCk ← p[st.Ck].b;
p[st.Rst].b ← st.s.Reset[1];
p[st.Freeze].b ← st.s.Freeze[1];
};
END.