CacheMCtlSequencerBehaviour.mesa
Last Edited by: Barth, May 31, 1984 6:04:34 pm PDT
DIRECTORY BitOps, CacheMCtlSequencer, CacheMicroMachine, Dragon, RoseTypes;
CacheMCtlSequencerBehaviour: CEDAR PROGRAM
IMPORTS BitOps, CacheMCtlSequencer, CacheMicroMachine, Dragon
SHARES CacheMCtlSequencer =
BEGIN OPEN BitOps, CacheMCtlSequencer, CacheMicroMachine, Dragon, RoseTypes;
Behaviour: CellProc = {
newIO: MCtlSequencerIORef ← NARROW[cell.realCellStuff.newIO];
state: MCtlSequencerStateRef ← NARROW[cell.realCellStuff.state];
{
OPEN newIO, state;
PulseA: PROC [decode: ATOM, oldState: BOOL] RETURNS [line, newState: BOOL] = {
newState ← IF PhBh THEN Decode[decode] ELSE oldState;
line ← PhAh AND newState;
};
phC: BOOL ← PhBh OR phBLast OR PhAh;
IF PhBh THEN phBLast ← TRUE;
IF PhAh THEN phBLast ← FALSE;
Master sequencer
{
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;
likelySequence: BitWord ← IBIW[TRUE, 0, 7, 6]; -- start with only idle required.
IF fetchOrStore AND nVirtualMatch AND nVictimClean THEN likelySequence ← IBIW[TRUE, likelySequence, 7, 0];
IF (fetchOrStore AND nMapValid) OR (store AND NOT nMatchPageClean) THEN likelySequence ← IBIW[TRUE, likelySequence, 7, 1];
IF fetchOrStore AND nVirtualMatch THEN likelySequence ← IBIW[TRUE, likelySequence, 7, 2];
IF store AND NOT nMatchCellShared THEN likelySequence ← IBIW[TRUE, likelySequence, 7, 3];
IF ioFetch THEN likelySequence ← IBIW[TRUE, likelySequence, 7, 4];
IF ioStore THEN likelySequence ← IBIW[TRUE, likelySequence, 7, 5];
pWantsM ← ((fetchOrStore AND nVirtualMatch) OR (store AND NOT nMatchCellShared) OR ioFetch OR ioStore OR PCmdToMAB=StoreHold OR PCmdToMAB=FetchHold) AND NOT Decode[$SuppressPSample];
IF PhBh THEN {
Assert[NOT MoreThanOneOf[Decode[$MDone] OR Decode[$SetWantWS], mIdleAB]];
currentPDemandsBA ← currentPDemandsAB;
IF Decode[$MDone] THEN FOR i:CARDINAL IN [0..5] DO
IF EBFW[currentPDemandsAB, 7, i] THEN {
currentPDemandsBA ← IBIW[FALSE, currentPDemandsBA, 7, i];
EXIT;
};
ENDLOOP;
IF Decode[$SetWantWS] THEN currentPDemandsBA ← IBIW[store AND LatchSharedAB, currentPDemandsBA, 7, 3];
IF mIdleAB AND NOT Decode[$SuppressPSample] THEN {
currentPDemandsBA ← likelySequence;
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 nMapValid;
dirtyPageBA ← store AND (nMapValid OR NOT nMatchPageClean);
IsCleanBA ← (NOT nMatchPageClean) AND (NOT dirtyPageBA);
};
};
IF PhAh THEN {
currentPDemandsAB ← IF seqCheckFaultsBA AND faultBitsAB#None THEN 1 ELSE currentPDemandsBA;
IF seqSenseSharedBA THEN LatchSharedAB ← NOT MNSharedSenseBA;
nVirtualMatch ← nMatchPageClean ← nMatchCellShared ← nMapValid ← nRealMatch ← nVictimClean ← TRUE;
MDoneAB ← seqMDoneBA AND (ECFW[currentPDemandsBA, 7, 0, 6]=0 OR (seqCheckFaultsBA AND faultBitsAB#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 PhBh THEN {
fault: BOOL ← Decode[$CheckFaults] AND faultBitsAB#None;
holdingBA ← holdingAB AND NOT fault;
mIdleBA ← IF (Decode[$ReleaseMBus] AND ECFW[currentPDemandsBA, 7, 0, 6]=0) OR fault THEN TRUE ELSE mIdleAB;
MNewRqEnableBA ← mGntSenseAB;
MNewRqIBA ← (NOT newRqAB) AND mIdleBA AND pWantsM AND mRqAB AND (NOT holdingBA);
newRqBA ← newRqAB;
MRqIBA ← NOT mIdleBA OR pWantsM OR holdingBA;
};
IF PhAh THEN {
wonArbitration: BOOL ← MGntSense AND (NOT MNewRqEnableBA OR newRqBA);
mRqAB ← MRqIBA;
mGntSenseAB ← MGntSense;
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;
};
Current sequence
{
prioritySequence: BitWord ← BitWordZero;
slaveSequence: BitWord ← 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[currentPDemandsBA, 7, i] THEN {
prioritySequence ← IBIW[TRUE, 0, 7, i];
EXIT;
};
ENDLOOP;
SELECT prioritySequence FROM
040H => {GetAdrCmdBA ← VictimReal;
mCmdOutBA ← WriteQuad}; -- WriteQuad
020H => {GetAdrCmdBA ← RefVirtual;
mCmdOutBA ← IORead}; -- IORead, map operation
010H => {GetAdrCmdBA ← IF didRMBA THEN RefRealMap ELSE RefRealAssemble;
mCmdOutBA ← ReadQuad}; -- ReadQuad
008H => {GetAdrCmdBA ← RefRealAssemble;
mCmdOutBA ← WriteSingle};-- WriteSingle
004H => {GetAdrCmdBA ← RefVirtual;
mCmdOutBA ← IORead};-- IORead, I/O operation
002H => {GetAdrCmdBA ← RefVirtual;
mCmdOutBA ← IOWrite};-- IOWrite
001H => {GetAdrCmdBA ← RefVirtual;
mCmdOutBA ← NoOp};-- NoOp
ENDCASE => Assert[TRUE, "priority sequence is zero"];
IsNoOpBA ← prioritySequence=001H;
IF PhAh THEN {
mCmdOutAB ← mCmdOutBA;
seqForceIdleAB ← seqForceIdleBA;
ioDoneAB ← MCmdIn=IOReadDone OR MCmdIn=IOWriteDone;
IF seqDoneBA THEN currentSequenceAB ← IF MGntSense THEN prioritySequence ELSE slaveSequence;
};
IF PhBh THEN MCmdOutBA ← mCmdOutAB;
romSequence ← IF seqForceIdleAB AND NOT ioDoneAB THEN 1 ELSE currentSequenceAB;
};
Slave control
IF PhAh THEN {
slaveAB ← IF forceSlaveBA AND NOT ioDoneAB THEN TRUE ELSE NOT MGntSense;
};
IF PhBh THEN {
Assert[NOT MoreThanOneOf[Decode[$ForceSlave], ioDoneAB]];
IF Decode[$ForceSlave] THEN forceSlaveBA ← TRUE;
IF ioDoneAB THEN forceSlaveBA ← FALSE;
};
Cycle control
IF PhAh THEN {
cycleShifterAB ← SELECT TRUE FROM
NOT seqDoneBA AND seqSenseReadyBA AND NOT MReadySense => cycleShifterBA,
NOT seqDoneBA AND (NOT seqSenseReadyBA OR (seqSenseReadyBA AND MReadySense)) => WShift[cycleShifterBA, 7, -1],
seqDoneBA AND NOT (forceSlaveBA AND ioDoneAB) AND (NOT MGntSense OR (MGntSense AND NOT GetAddressDoneBA)) => IBIW[TRUE, 0, 7, 0],
seqDoneBA AND NOT (forceSlaveBA AND ioDoneAB) AND MGntSense AND GetAddressDoneBA => IBIW[TRUE, 0, 7, 1],
seqDoneBA AND forceSlaveBA AND ioDoneAB => IBIW[TRUE, 0, 7, 2],
ENDCASE => ERROR;
};
IF PhBh THEN {
cycleShifterBA ← cycleShifterAB;
};
ROM
{
seq: SequenceNumber;
cyc: CycleNumber;
FOR i:SequenceNumber IN SequenceNumber DO
IF EBFW[romSequence, 7, i] THEN {seq ← i; EXIT};
ENDLOOP;
FOR i:CycleNumber IN CycleNumber DO
IF EBFW[cycleShifterAB, 7, i] THEN {cyc ← i; EXIT};
ENDLOOP;
SetState[slave: slaveAB, sequence: seq, cycle: cyc];
};
IF PhBh THEN {
seqSenseSharedBA ← Decode[$SenseShared];
seqMDoneBA ← Decode[$MDone];
seqDoneBA ← Decode[$Done] OR Resetb;
seqForceIdleBA ← Decode[$ForceIdle];
seqSenseReadyBA ← Decode[$SenseReady];
seqMDataIToFaultsBA ← Decode[$MDataIToFaults];
seqCheckFaultsBA ← Decode[$CheckFaults];
seqDriveSharedBA ← Decode[$DriveShared];
seqMDataIDriveBA ← Decode[$MDataToMDataI];
seqDriveMDataDelayedBA ← Decode[$DriveMDataDelayed];
seqDriveMCmdBA ← Decode[$DriveMCmd];
seqDriveMCmdToDataTransportBA ← Decode[$DriveMCmdToDataTransport];
seqDriveMCmdToNoOpBA ← Decode[$DriveMCmdToNoOp];
seqDCheckParityBA ← Decode[$DCheckParity];
seqStopPipeNoReadyBA ← Decode[$StopPipeNoReady];
};
MData interface
IF PhAh THEN {
IF seqMDataIToFaultsBA THEN faultBitsAB ← LOOPHOLE[ECFD[MDataI, 32, 29, 3]];
MFaultAB ← IF seqCheckFaultsBA THEN faultBitsAB ELSE None;
};
IF PhBh AND Decode[$MapBitsToMDataI] 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
};
Match control
IF PhBh AND Decode[$SampleRealMatch] THEN MatchRealBA ← NOT nRealMatch;
MNSharedDriveLow ← phC AND seqDriveSharedBA AND MatchRealBA;
MNSharedDriveHigh ← PhBh AND Decode[$PrechargeMNShared];
MBus strobes
MDataIDrive ← phC AND seqMDataIDriveBA;
MDataPipeBypass ← PhBh AND Decode[$MDataIToMData];
MDataPipeTransfer ← PhBh AND NOT (Decode[$MDataIToMData] OR stopPipeAB);
IF PhAh THEN {
driveMDataDelayedAB ← seqDriveMDataDelayedBA;
stopPipeAB ← seqStopPipeNoReadyBA AND NOT MReadySense;
};
IF PhBh THEN seqDriveMDataBA ← (Decode[$DriveMData] OR driveMDataDelayedAB) AND (mGntSenseAB OR MatchRealBA);
MDataDrive ← phC AND seqDriveMDataBA;
MCmdDrive ← phC AND seqDriveMCmdBA;
MCmdDriveToDataTransport ← phC AND seqDriveMCmdToDataTransportBA;
MCmdDriveToNoOp ← phC AND seqDriveMCmdToNoOpBA;
Parity
IF PhAh THEN dCheckParityAB ← seqDCheckParityBA;
IF PhBh AND (Decode[$CheckParity] OR dCheckParityAB) THEN parityBA ← ParityOut;
IF PhAh AND parityBA THEN parityErrorAB ← TRUE;
MNErrorDriveLow ← parityErrorAB;
Reset
IF Resetb THEN {
holdingAB ← FALSE;
mIdleAB ← TRUE;
parityErrorAB ← FALSE;
forceSlaveBA ← FALSE;
};
[CAMMDataIToMatchReg, pCAMMDataIToMatchReg] ← PulseA[$MDataIToMatchReg, pCAMMDataIToMatchReg];
[CAMGetAdrRefresh, pCAMGetAdrRefresh] ← PulseA[$GetAdrRefresh, pCAMGetAdrRefresh];
[CAMGetAddress, pCAMGetAddress] ← PulseA[$GetAddress, pCAMGetAddress];
CAMPageAccessToMDataI ← PhBh AND Decode[$PageAccessToMDataI];
CAMLowBitsAccessToMDataI ← PhBh AND (Decode[$LowBitsAccessToMDataI] OR Decode[$LowBitsZeroToMDataI]);
[CAMAccessToMatch, pCAMAccessToMatch] ← PulseA[$AccessToMatch, pCAMAccessToMatch];
[CAMMatchToAccess, pCAMMatchToAccess] ← PulseA[$MatchToAccess, pCAMMatchToAccess];
[CAMVirtualAddressToAccess, pCAMVirtualAddressToAccess] ← PulseA[$VirtualAddressToAccess, pCAMVirtualAddressToAccess];
[CAMDriveCAMAccess, pCAMDriveCAMAccess] ← PulseA[$DriveCAMAccess, pCAMDriveCAMAccess];
[RAMMDataIToMRAMReg, pRAMMDataIToMRAMReg] ← PulseA[$MDataIToMRAMReg, pRAMMDataIToMRAMReg];
[RAMMBitsToMRAMReg, pRAMMBitsToMRAMReg] ← PulseA[$MBitsToMRAMReg, pRAMMBitsToMRAMReg];
[RAMMRAMRegToMDataI, pRAMMRAMRegToMDataI] ← PulseA[$MRAMRegToMDataI, pRAMMRAMRegToMDataI];
[RAMMRAMRegToMBits, pRAMMRAMRegToMBits] ← PulseA[$MRAMRegToMBits, pRAMMRAMRegToMBits];
[RAMMRAMRegToMBitsNoOrphan, pRAMMRAMRegToMBitsNoOrphan] ← PulseA[$MRAMRegToMBitsNoOrphan, pRAMMRAMRegToMBitsNoOrphan];
RAMPBitsToMRAMReg ← PhBh AND Decode[$PBitsToMRAMReg];
RAMLeftPBitsToMRAMReg ← PhBh AND Decode[$LeftPBitsToMRAMReg];
[RAMMRAMRegToPBits, pRAMMRAMRegToPBits] ← PulseA[$MRAMRegToPBits, pRAMMRAMRegToPBits];
[FlagSetShared, pFlagSetShared] ← PulseA[$SetShared, pFlagSetShared];
[FlagRPDirtyVPValid, pFlagRPDirtyVPValid] ← PulseA[$RPDirtyVPValid, pFlagRPDirtyVPValid];
[FlagFlagLatch, pFlagFlagLatch] ← PulseA[$FlagLatch, pFlagFlagLatch];
[FlagResetVPValid, pFlagResetVPValid] ← PulseA[$ResetVPValid, pFlagResetVPValid];
[FlagSetFlags, pFlagSetFlags] ← PulseA[$SetFlags, pFlagSetFlags];
[FlagSetTIP, pFlagSetTIP] ← PulseA[$SetTIP, pFlagSetTIP];
[FlagResetTIP, pFlagResetTIP] ← PulseA[$ResetTIP, pFlagResetTIP];
[FlagResetMaster, pFlagResetMaster] ← PulseA[$ResetMaster, pFlagResetMaster];
IF PhBh THEN EntryMDataIToMAdrCtr ← Decode[$MDataIToMAdrCtr];
IF PhBh THEN EntryGetAddress ← Decode[$GetAddress];
IF PhBh THEN EntryGetAdrRefresh ← Decode[$GetAdrRefresh];
IF PhBh THEN EntryRefresh ← Decode[$Refresh];
IF PhBh THEN EntryMAdrCtrToMAdr ← Decode[$MAdrCtrToMAdr];
EntryIncMAdrCtr ← PhBh AND Decode[$IncMAdrCtr] AND NOT stopPipeAB;
EntryZeroMAdrCtr ← PhBh AND Decode[$ZeroMAdrCtr];
EntryPAdrToMAdrCtr ← PhBh AND Decode[$PAdrToMAdrCtr];
EntryLowBitsAccessToMDataI ← PhBh AND Decode[$LowBitsAccessToMDataI];
EntryLowBitsZeroToMDataI ← PhBh AND Decode[$LowBitsZeroToMDataI];
IF PhBh THEN EntrySelRealData ← Decode[$SelRealData];
IF PhBh THEN EntrySelPageFlag ← Decode[$SelPageFlag];
IF PhBh THEN EntrySelVictimData ← Decode[$SelVictimData];
IF PhBh THEN EntrySelectVictimOrOrphan ← Decode[$SelectVictimOrOrphan];
EntryVirtualAccess ← PhBh AND Decode[$VirtualAccess];
EntrynVirtualAccess ← PhBh AND Decode[$nVirtualAccess];
IF PhBh THEN EntryShiftVictim ← Decode[$ShiftVictim];
IF PhBh THEN pEntryFinishSharedStore ← Decode[$FinishSharedStore];
IF PhAh THEN EntryFinishSharedStore ← pEntryFinishSharedStore;
ShiftEqual ← PhBb;
nShiftEqual ← NOT ShiftEqual;
ShiftFeedBack ← PhAb AND NOT (DoShiftBA OR DoExecuteBA);
nShiftFeedBack ← NOT ShiftFeedBack;
ShiftShift ← PhAb AND DoShiftBA;
nShiftShift ← NOT ShiftShift;
ShiftExecute ← PhAb AND DoExecuteBA;
nShiftExecute ← NOT ShiftExecute;
{
aL: CARDINAL = 26;
IF ShiftExecute THEN {
assembly: BitDWord;
assembly ← IBID[mIdleAB, assembly, aL, 0];
assembly ← IBID[holdTypeBA, assembly, aL, 1];
assembly ← IBID[holdingAB, assembly, aL, 2];
assembly ← IBID[forceSlaveBA, assembly, aL, 3];
assembly ← IBID[slaveAB, assembly, aL, 4];
assembly ← MWTD[currentPDemandsBA, 7, 0, 7, assembly, aL, 5, 7];
assembly ← MWTD[currentSequenceAB, 7, 0, 7, assembly, aL, 12, 7];
assembly ← MWTD[cycleShifterAB, 7, 0, 7, assembly, aL, 19, 7];
nshiftData ← DNOT[assembly, aL];
};
IF ShiftShift THEN {
nshiftData ← MDTD[DNOT[shiftData, aL], aL, 1, aL-1, nshiftData, aL, 0, aL-1];
nshiftData ← IBID[NOT ShiftDataToSequencer, nshiftData, aL, aL-1];
};
IF ShiftFeedBack THEN nshiftData ← DNOT[shiftData, aL];
IF ShiftEqual THEN {
shiftData ← DNOT[nshiftData, aL];
ShiftDataToEntryCtl ← EBFD[shiftData, aL, 0];
};
};
};
};
CacheMCtlSequencer.RegisterBehaviour[Behaviour];
END.