{
sample: BOOL ← MIdleAB AND NOT ReallySuppressPSampleAB;
store: BOOL ← PCmdToMAB=Store OR PCmdToMAB=StoreHold;
fetchOrStore: BOOL ← PCmdToMAB=Fetch OR PCmdToMAB=FetchHold OR store;
ioFetch: BOOL ← PCmdToMAB=IOFetch OR PCmdToMAB=IOFetchHold;
ioStore: BOOL ← PCmdToMAB=IOStore OR PCmdToMAB=IOStoreHold;
PWantsM ← ((fetchOrStore AND nVQMatchB) OR (store AND ((NOT nQuadSharedB) OR nPageDirtyB)) OR ioFetch OR ioStore OR PCmdToMAB=StoreHold OR PCmdToMAB=FetchHold) AND NOT ReallySuppressPSampleAB;
ZapABit ← PhAb AND MIsDoneAB AND (NOT EBFW[CurrentPDemandsBA, 7, 0] OR OneDirtyBA);
Assert[NOT MoreThanOneOf[ZapABit, SetWantWSA]];
IF PhAb THEN CurrentPDemandsAB ← CurrentPDemandsBA;
IF ZapABit
THEN
FOR i:
CARDINAL
IN [0..5]
DO
IF
EBFW[CurrentPDemandsBA, 7, i]
THEN {
CurrentPDemandsAB ← IBIW[FALSE, CurrentPDemandsBA, 7, i];
EXIT;
};
ENDLOOP;
IF SetWantWSA THEN CurrentPDemandsAB ← IBIW[store AND LatchSharedBA, CurrentPDemandsBA, 7, 3];
IF PhAb AND CheckFaultsAB AND FaultBitsBA#Dragon.None THEN CurrentPDemandsAB ← 1;
IF PhBb AND NOT sample THEN CurrentPDemandsBA ← CurrentPDemandsAB;
IF PhBb
AND sample
THEN {
CurrentPDemandsBA ← IBIW[TRUE, 0, 7, 6]; -- start with only idle required.
IF fetchOrStore AND nVirtualBlockMatchB AND SomeDirtyBA THEN CurrentPDemandsBA ← IBIW[TRUE, CurrentPDemandsBA, 7, 0];
IF (fetchOrStore AND nMapValidB) OR (store AND nPageDirtyB) THEN CurrentPDemandsBA ← IBIW[TRUE, CurrentPDemandsBA, 7, 1];
IF fetchOrStore AND nVQMatchB THEN CurrentPDemandsBA ← IBIW[TRUE, CurrentPDemandsBA, 7, 2];
IF store AND NOT nQuadSharedB THEN CurrentPDemandsBA ← IBIW[TRUE, CurrentPDemandsBA, 7, 3];
IF ioFetch THEN CurrentPDemandsBA ← IBIW[TRUE, CurrentPDemandsBA, 7, 4];
IF ioStore THEN CurrentPDemandsBA ← IBIW[TRUE, CurrentPDemandsBA, 7, 5];
HoldTypeBA ← PCmdToMAB=StoreHold OR PCmdToMAB=FetchHold OR PCmdToMAB=IOFetchHold OR PCmdToMAB=IOStoreHold;
NotHoldTypeBA ← NOT (PCmdToMAB=NoOp OR PCmdToMAB=StoreHold OR PCmdToMAB=FetchHold OR PCmdToMAB=IOFetchHold OR PCmdToMAB=IOStoreHold);
DidRMBA ← fetchOrStore AND nMapValidB;
DirtyPageBA ← store AND (nMapValidB OR nPageDirtyB);
IsCleanBA ← nPageDirtyB AND NOT DirtyPageBA;
};
};
IF SenseSharedB THEN LatchSharedBA ← MSharedSense;
IF PhAb THEN nVQMatchB ← nQuadSharedB ← nPageDirtyB ← nMapValidB ← nVirtualBlockMatchB ← TRUE;
IF PhBb THEN nRQMatchA ← nRealBlockMatchA ← TRUE;
IF PhAb THEN MDoneAB ← MIsDoneAB AND (ECFW[CurrentPDemandsAB, 7, 0, 6]=0 OR (CheckFaultsAB AND FaultBitsBA#Dragon.None));
Bus arbitration
MIdleAB indicates that the low level M controller has finished with the last request from P that caused it to become active and so the M bus should be given up.
Holding indicates that a series of XHold commands are in progress on P and so the M bus should not be given up.
IF PhBb
THEN {
fault: BOOL ← CheckFaultsAB AND FaultBitsBA#Dragon.None;
HoldingBA ← HoldingAB AND NOT fault;
MIdleBA ← IF (ReleaseMBusBA AND ECFW[CurrentPDemandsAB, 7, 0, 6]=0) OR EarlyIdleAB OR fault THEN TRUE ELSE MIdleAB;
MGntBA ← MGntAB;
MNewRqIBA ← (NOT NewRqAB) AND MIdleBA AND PWantsM AND MRqAB AND (NOT HoldingBA);
NewRqBA ← NewRqAB;
MRqIBA ← NOT MIdleBA OR PWantsM OR HoldingBA;
};
IF PhAb
THEN {
wonArbitration: BOOL ← MGntSenseA AND (NOT MGntBA OR NewRqBA);
MRqAB ← MRqIBA;
MGntAB ← MGntSenseA;
MIdleAB ← IF (wonArbitration OR HoldingBA) AND NOT ECFW[CurrentPDemandsBA, 7, 0, 6]=0 THEN FALSE ELSE MIdleBA;
HoldingAB ← IF wonArbitration AND HoldTypeBA THEN TRUE ELSE IF NotHoldTypeBA THEN FALSE ELSE HoldingBA;
MHeldAB ← HoldingBA AND HoldingAB;
NewRqAB ← MNewRqIBA;
};
MNewRqEnableC ← PhC AND MGntBA;
Current sequence
{
prioritySequence: BitWord ← BitWordZero;
slaveSequence: BitWord ←
IF ForceIdleAB
THEN 1
ELSE
SELECT MCmdIn
FROM
ReadQuad => 020H,
WriteQuad => 010H,
WriteSingle => 08H,
ChangeFlags => 04H,
IOReadDone, IOWriteDone, DataTransport, IORead, IOWrite, Reserve9, Reserve10, Reserve11, Reserve12, Reserve13, Reserve14, NoOp => 01H,
ENDCASE => ERROR;
FOR i:
CARDINAL
IN [0..6]
DO
IF
EBFW[CurrentPDemandsAB, 7, i]
THEN {
prioritySequence ← IBIW[TRUE, 0, 7, i];
EXIT;
};
ENDLOOP;
CmdOutAB ←
SELECT prioritySequence
FROM
040H => WriteQuad,
020H => IORead,
010H => ReadQuad,
008H => WriteSingle,
004H => IORead,
002H => IOWrite,
001H => NoOp,
ENDCASE => NoOp;
IF PhBb AND DoneAB THEN CurrentSequenceBA ← IF MGntAB THEN prioritySequence ELSE slaveSequence;
IF PhBb
THEN {
GetAdrCmdBA ←
SELECT prioritySequence
FROM
040H => VictimReal,
020H => RefVirtual,
010H => IF DidRMBA THEN RefRealMap ELSE RefRealAssemble,
008H => RefRealAssemble,
004H => RefVirtual,
002H => RefVirtual,
001H => RefVirtual,
ENDCASE => RefVirtual;
};
};
IF PhAb
THEN MCmdOutAB ←
SELECT
TRUE
FROM
MCmdDriveToDataTransportAB => DataTransport,
MCmdDriveToNoOpAB => NoOp,
ENDCASE => CmdOutBA;
IF PhBb
THEN {
CmdOutBA ← CmdOutAB;
IODoneCommandBA ← MCmdIn=IOReadDone OR MCmdIn=IOWriteDone;
};
ROMSequenceBA ← IF (ForceSlaveBA AND NOT IODoneCommandBA) OR Resetb THEN 1 ELSE CurrentSequenceBA;
Slave control
IF ForceSlaveBA THEN ForceSlave ← TRUE;
IF PhBb THEN ROMSlaveBA ← IF ForceSlave AND NOT IODoneCommandBA THEN TRUE ELSE NOT MGntAB;
Assert[NOT MoreThanOneOf[ForceSlaveBA, IODoneCommandBA]];
IF PhAb AND IODoneCommandBA THEN ForceSlave ← FALSE;
IF PhBb THEN MasterBA ← MGntBA AND NOT ForceSlave;
Cycle control
IF PhBb THEN ContinueBA ← NOT SenseReadyBA OR MCmdIn=DataTransport;
IF Resetb
THEN ROMCycleBA ← 20H
ELSE
IF PhBb
THEN ROMCycleBA ←
SELECT
TRUE
FROM
NOT DoneAB AND NOT ContinueBA => CycleShifterAB,
NOT DoneAB AND ContinueBA => WShift[CycleShifterAB, 7, -1],
DoneAB AND NOT (ForceSlave AND IODoneCommandBA) => IBIW[TRUE, 0, 7, 1],
DoneAB AND (ForceSlave AND IODoneCommandBA) => IBIW[TRUE, 0, 7, 2],
ENDCASE => ERROR;
IF PhAb THEN CycleShifterAB ← ROMCycleBA;
Fault and Map Bits
IF MDataIToFaultsB THEN FaultBitsBA ← LOOPHOLE[ECFD[MDataI, 32, 29, 3]];
IF PhAb THEN MFaultAB ← IF CheckFaultsAB THEN FaultBitsBA ELSE Dragon.None;
IF MapBitsToMDataIA
THEN {
MDataI ← IBID[DidRMBA, MDataI, 32, 24]; -- read the map
MDataI ← IBID[DirtyPageBA, MDataI, 32, 25]; -- set the dirty bit
MDataI ← ICID[0, MDataI, 32, 26, 6]; -- zero the rest of the bits
};
Parity
IF BCheckParityB THEN ParityBA ← MRamRegParityOut AND (MatchRealQuadAB OR MasterEnableMBusDriveAB);
IF PhAb AND ParityBA THEN MNErrorDriveLow ← TRUE;
IF ACheckParityA THEN ParityAB ← MRamRegParityOut AND ContinueBA;
IF PhBb AND ParityAB THEN MNErrorDriveLow ← TRUE;
M bus control
EnableMBusDrive ← MatchRealQuadAB OR MasterEnableMBusDriveAB;
IF SampleRealMatchA
THEN {
MatchRealQuadAB ← NOT nRQMatchA;
MatchRealBlockAB ← NOT nRealBlockMatchA;
};
IF NOT PhC THEN MCmdDriveEnable ← MDataDriveEnable ← DriveSharedHighEnable ← DriveSharedLowEnable ← FALSE;
IF MCmdDriveA AND EnableMBusDrive THEN MCmdDriveEnable ← TRUE;
IF (MDataDriveA AND EnableMBusDrive) OR MDataDriveDelayedA THEN MDataDriveEnable ← TRUE;
IF DriveSharedHighA THEN DriveSharedHighEnable ← TRUE;
IF DriveSharedLowA AND EnableMBusDrive THEN DriveSharedLowEnable ← TRUE;
MCmdDriveC ← PhC AND MCmdDriveEnable;
MDataDriveC ← PhC AND MDataDriveEnable;
MNSharedDriveHighC ← PhC AND DriveSharedHighEnable;
MNSharedDriveLowC ← PhC AND DriveSharedLowEnable;
Reset
IF Resetb
THEN {
HoldingAB ← FALSE;
MIdleAB ← TRUE;
MNErrorDriveLow ← FALSE;
ForceSlave ← FALSE;
};