PORTS [
Timing and housekeeping interface (16)
PhA, nPhA, PhB, nPhB<BOOL,
Vdd, Gnd<BOOL,
PadVdd, PadGnd<BOOL,
Processor interface (47)
PData=INT[32],
PParityB=BOOL,
PCmdA<EnumType["Dragon.PBusCommands"],
PRejectB>BOOL, -- Tristate
PFaultB>EnumType["Dragon.PBusFaults"], -- Tristate
PnPError>BOOL,
PWriteEnable<INT[4],
PInternalParity<BOOL,
Main memory interface (49)
MHold, MnReset<BOOL,
MnRq>BOOL,
IMnMRq>BOOL,
MnGnt<BOOL,
MnNewRq>BOOL, -- Tristate
MnAdCycle=BOOL,
MTransport=INT[36],
MParity=BOOL,
MnShared=BOOL,
MnAbort>BOOL, -- Tristate
MnHousekeepingInProgress=BOOL,
MnError>BOOL, -- Tristate
MnDV=BOOL,
Serial debugging interface (5)
DShift<BOOL,
DExecute<BOOL,
DnSelect<BOOL,
DDataIn<BOOL,
DDataOut>BOOL -- Tristate
]
State
pCmdAB: Dragon.PBusCommands,
pAddressAB: BitDWord,
pDataBA: BitDWord,
rejectAB, rejectBA: BitDWord,
RequestMatchAB: BOOL,
IOReferenceAB, CacheStoreReferenceAB, CacheReferenceAB, FetchReferenceAB, HoldReferenceAB, StoreReferenceAB: BOOL, -- temps
mCmdBA: MBusCommands,
mAddressBA: BitDWord,
mCycleBA, mCycleAB: CARDINAL,
busMasterBA, busMasterAB: BOOL,
mCmdValidBA, mCmdValidAB: BOOL,
mMatch, virtualMatch: BOOL,
MDoneAB, MHeldAB: BOOL,
MFaultAB: Dragon.PBusFaults,
realEntry, virtualEntry: EntryIndex,
realQuadIndex, virtualQuadIndex: QuadIndex,
realWordIndex, virtualWordIndex: WordIndex,
AddressMatch, AddressMask: BitDWord,
BlockMask: BitDWord,
HouseKeepingAddress, HouseKeepingMask: BitDWord,
entries: SEQUENCE length: CARDINAL OF CacheEntry
EvalSimple
mTransport: BitMWord;
wordOrder:
ARRAY [0..4)
OF
ARRAY [0..4)
OF [0..4) =
[[0, 1, 2, 3], [1, 0, 3, 2], [2, 3, 0, 1], [3, 2, 1, 0]];
FindEntry:
PROC
RETURNS [found:
BOOL ←
FALSE] = {
mMatch ← FALSE;
realQuadIndex ← ECFD[mAddressBA, 32, 28, 2];
realWordIndex ← ECFD[mAddressBA, 32, 30, 2];
FOR e: EntryIndex
IN EntryIndex
DO
IF entries[e].RPValid
AND entries[e].RealAddress=
DAND[mAddressBA,
ILID[0FFFFFFF0H, BitDWordZero, 32, 0, 32]]
AND entries[e].quadData[realQuadIndex].Valid
THEN {
realEntry ← e;
found ← TRUE;
RETURN;
};
ENDLOOP;
};
TRUSTED {mTransport ← DESCRIPTOR [MTransport]};
IF
NOT MnReset
THEN {
FOR e: EntryIndex
IN EntryIndex
DO
entries[e].VPValid ← FALSE;
entries[e].RPValid ← FALSE;
ENDLOOP;
AddressMatch ← BitDWordZero; -- at power up match all addresses so that minimal systems do not require D bus
AddressMask ← BitDWordZero;
BlockMask ← ILID[000003F0H, BitDWordZero, 32, 0, 32]; -- set to maximum page size, adjust if power up page size should be different or quads per entry or words per quad changes
mCmdValidBA ← FALSE;
MDoneAB ← FALSE;
pCmdAB ← NoOp;
rejectAB ← FALSE;
rejectBA ← FALSE;
RETURN;
};
virtualMatch ← FALSE;
FOR e: EntryIndex
IN EntryIndex
DO
IF entries[e].VPValid
AND entries[e].VirtualAddress=
DAND[pAddressAB,
ILID[0FFFFFFF0H, BitDWordZero, 32, 0, 32]]
AND entries[e].quadData[quadIndex].Valid
THEN {
virtualEntry ← e;
virtualMatch ← TRUE;
};
ENDLOOP;
IF PhA
THEN {
forceSlave: BOOL ← FALSE; -- true if IOMumbleFlow is outstanding
rejectAB ← rejectBA;
PRejectB ← FALSE;
PFaultB ← None;
IF
NOT rejectBA
THEN {
pCmdAB ← PCmdA;
pAddressAB ← PData;
virtualQuadIndex ← ECFD[pAddressAB, 32, 28, 2];
virtualWordIndex ← ECFD[pAddressAB, 32, 30, 2];
};
IOReferenceAB ← pCmdAB=IOFetch OR pCmdAB=IOStore OR pCmdAB=IOFetchHold OR pCmdAB=IOStoreHold;
CacheStoreReferenceAB ← pCmdAB=Store OR pCmdAB=StoreHold;
CacheReferenceAB ← pCmdAB=Fetch OR pCmdAB=FetchHold OR CacheStoreReferenceAB;
FetchReferenceAB ← pCmdAB=Fetch OR pCmdAB=FetchHold OR pCmdAB=IOFetch OR pCmdAB=IOFetchHold;
HoldReferenceAB ← pCmdAB=FetchHold OR pCmdAB=StoreHold OR pCmdAB=IOFetchHold OR pCmdAB=IOStoreHold;
StoreReferenceAB ← CacheStoreReferenceAB OR pCmdAB=IOStore OR pCmdAB=IOStoreHold;
RequestMatchAB ← DAND[pAddressAB, AddressMask] = AddressMatch;
busMasterAB ← busMasterBA AND NOT forceSlave;
MHeldAB ← ;
MDoneAB ← ;
MFaultAB ← ;
mCmdValidAB ← mCmdValidBA;
IF mCmdValidBA
THEN {
mCycleAB ← mCycleBA + 1;
SELECT mCmdBA
FROM
ReadQuad, ReadQuadObsolete =>
SELECT mCycleAB
FROM
0 => NULL;
1 => NULL;
2 =>
IF busMasterAB
THEN
NULL
ELSE {
IF FindEntry[]
THEN {
MnShared ← FALSE;
entries[realEntry].quadData[realQuadIndex].Shared ← TRUE;
IF entries[realEntry].quadData[realQuadIndex].Master
THEN {
MnAbort ← FALSE;
mMatch ← TRUE;
};
};
};
3 =>
IF mMatch
THEN {
MnAbort ← TRUE;
MnDV ← FALSE;
MDTM[entries[realEntry].quadData[realQuadIndex].Data[wordOrder[ realWordIndex][0]], 32, 0, 32, mTransport, 36, 4, 32];
};
4 =>
IF mMatch
THEN {
MnDV ← TRUE;
MDTM[entries[realEntry].quadData[realQuadIndex].Data[wordOrder[ realWordIndex][1]], 32, 0, 32, mTransport, 36, 4, 32];
MParity ← entries[realEntry].quadData[realQuadIndex].Parity[wordOrder[ realWordIndex][0]];
};
5 =>
IF mMatch
THEN {
MDTM[entries[realEntry].quadData[realQuadIndex].Data[wordOrder[ realWordIndex][2]], 32, 0, 32, mTransport, 36, 4, 32];
MParity ← entries[realEntry].quadData[realQuadIndex].Parity[wordOrder[ realWordIndex][1]];
};
6 =>
IF mMatch
THEN {
MDTM[entries[realEntry].quadData[realQuadIndex].Data[wordOrder[ realWordIndex][3]], 32, 0, 32, mTransport, 36, 4, 32];
MParity ← entries[realEntry].quadData[realQuadIndex].Parity[wordOrder[ realWordIndex][2]];
};
7 => {
IF mMatch THEN MParity ← entries[realEntry].quadData[realQuadIndex].Parity[wordOrder[ realWordIndex][3]];
mCmdValidAB ← FALSE;
};
ENDCASE => ERROR;
ENDCASE;
};
};
IF PhB
THEN {
IF StoreReferenceAB
AND
NOT rejectAB
THEN {
pDataBA ← PData;
pParityBA ← PParityB;
};
rejectBA ←
NOT MDoneAB
AND RequestMatchAB
AND
(IOReferenceAB
OR (HoldReferenceAB
AND
NOT MHeldAB)
OR
(CacheReferenceAB
AND
NOT virtualMatch) OR
(NOT virtualMatch OR NOT
(NOT (RefMatchesLastRefReg AND ECFW[PAdr2831AB, 4, 0, 2]=LastQuad) OR EBFW[ValidWordsAB, 4, ECFW[PAdr2831AB, 4, 2, 2]]))) OR
(CacheStoreReferenceAB
AND
(NOT entries[virtualEntry].RPDirty OR entries[virtualEntry].quadData[virtualQuadIndex].Shared)));
PRejectB ← RequestMatchAB AND (rejectBA OR (MDoneAB AND MFaultAB#None));
PFaultB ← IF MDoneAB THEN MFaultAB;
decide if m action required to satisfy P request
IF
NOT rejectBA
THEN
SELECT pCmdAB
FROM
Store, StoreHold => {
entries[virtualEntry].quadData[virtualQuadIndex].Data[ virtualWordIndex] ← pDataBA;
entries[virtualEntry].quadData[virtualQuadIndex].Parity[ virtualWordIndex] ← pParityBA;
};
Fetch, FetchHold => {
pDataBA ← entries[virtualEntry].quadData[virtualQuadIndex].Data[ virtualWordIndex];
pParityBA ← entries[virtualEntry].quadData[virtualQuadIndex].Parity[ virtualWordIndex];
};
ENDCASE;
mCycleBA ← mCycleAB;
IF
NOT MnAdCycle
AND
NOT busMasterAB
THEN {
mCmdBA ← LOOPHOLE[ECFM[mTransport, 36, 4, 4]];
mAddressBA ← MMTD[mTransport, 36, 0, 4, mAddressBA, 32, 0, 4];
mAddressBA ← MMTD[mTransport, 36, 8, 28, mAddressBA, 32, 4, 28];
mCmdValidBA ← TRUE;
mCycleBA ← 0;
};
busMasterBA ← NOT MnGnt;
IF mCmdValidAB
THEN {
SELECT mCmdBA
FROM
WriteQuad, WriteQuadObsolete =>
SELECT mCycleBA
FROM
0 => NULL;
1 =>
IF busMasterAB
THEN
NULL
ELSE {
IF FindEntry[]
THEN {
mMatch ← TRUE;
entries[realEntry].quadData[realQuadIndex].Data[wordOrder[ realWordIndex][0]] ← MMTD[mTransport, 36, 4, 32, BitDWordZero, 32, 0, 32];
};
};
2 =>
IF mMatch
THEN {
entries[realEntry].quadData[realQuadIndex].Data[wordOrder[ realWordIndex][1]] ← MMTD[mTransport, 36, 4, 32, BitDWordZero, 32, 0, 32];
entries[realEntry].quadData[realQuadIndex].Parity[wordOrder[ realWordIndex][0]] ← MParity;
};
3 =>
IF mMatch
THEN {
entries[realEntry].quadData[realQuadIndex].Data[wordOrder[ realWordIndex][2]] ← MMTD[mTransport, 36, 4, 32, BitDWordZero, 32, 0, 32];
entries[realEntry].quadData[realQuadIndex].Parity[wordOrder[ realWordIndex][1]] ← MParity;
};
4 =>
IF mMatch
THEN {
entries[realEntry].quadData[realQuadIndex].Data[wordOrder[ realWordIndex][3]] ← MMTD[mTransport, 36, 4, 32, BitDWordZero, 32, 0, 32];
entries[realEntry].quadData[realQuadIndex].Parity[wordOrder[ realWordIndex][2]] ← MParity;
};
5 => {
IF mMatch THEN entries[realEntry].quadData[realQuadIndex].Parity[ wordOrder[realWordIndex][3]] ← MParity;
mCmdValidBA ← FALSE;
};
ENDCASE => ERROR;
ENDCASE;
};
};