logicCutSet: Rope.ROPE = "Logic"; -- should be Logic.logicCutSet, actually
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",
]];
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: 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: 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 BOOL ← ALL[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];
};