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", 5],
"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)
];
ArbProps:
TYPE =
MACHINE
DEPENDENT
RECORD [
unused (0: 0..11): [0..4096),
arbNo (0: 12..14): [0..8),
hySelDec(0: 15..15): BOOL
];
MSRec:
TYPE =
RECORD [
Reset, Freeze: 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]
-- 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: BOOL = p[st.DBus][DSerialIn].b;
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;
};
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[maxDevices-1], 0, PriorityRecLen],
2 => BitOps.EBFW[st.ds.ArbProps, 0, ArbPropsLen],
3 => BitOps.EBFW[st.ds.BoardVersionShadow, 0, 2],
ENDCASE => FALSE)
ELSE TRUE)
};
p[st.DHybridSel].c ←
(
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;
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];
};