<> <> Directory Dragon; Imports BitOps; Open BitOps; Cedar EntriesPerCache: INT = 50; QuadsPerEntry: INT = 4; WordsPerQuad: INT = 4; EntryIndex: TYPE = [0..EntriesPerCache); QuadIndex: TYPE = [0..QuadsPerEntry); WordIndex: TYPE = [0..WordsPerQuad); MBusCommands: TYPE = MACHINE DEPENDENT {ReadQuad(0), WriteQuad(1), ReadQuadObsolete(2), WriteQuadObsolete(3), IORead(4), IOWrite(5), Reserve6(6), WriteSingle(7), IOReadFlow(8), IOWriteFlow(9), MapRefDirty(10), Reserve11(11), MapRef(12), Reserve13(13), Done(14), Reserve15(15)}; CacheEntry: TYPE = RECORD[ VirtualAddress: BitDWord, RealAddress: BitDWord, VPValid: BOOL, RPValid: BOOL, RPDirty: BOOL, quadData: ARRAY QuadIndex OF QuadState ]; QuadState: TYPE = RECORD[ Master: BOOL, Shared: BOOL, Valid: BOOL, Data: ARRAY WordIndex OF BitDWord, Parity: ARRAY WordIndex OF BOOL ]; ; CELLTYPE "DataCache" PORTS [ <<144 - (16+47+49+5) => 27>> <<>> <> PhA, nPhA, PhB, nPhB> PData=INT[32], PParityB=BOOL, PCmdABOOL, -- Tristate PFaultB>EnumType["Dragon.PBusFaults"], -- Tristate PnPError>BOOL, PWriteEnable> MHold, MnResetBOOL, IMnMRq>BOOL, MnGntBOOL, -- Tristate MnAdCycle=BOOL, MTransport=INT[36], MParity=BOOL, MnShared=BOOL, MnAbort>BOOL, -- Tristate MnHousekeepingInProgress=BOOL, MnError>BOOL, -- Tristate MnDV=BOOL, <> DShiftBOOL -- 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 Initializer state: DataCacheStateRef _ NEW [DataCacheStateRec[EntriesPerCache]]; cell.realCellStuff.state _ state; 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; <> 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; }; }; ENDCELLTYPE