<> <> <> <> Imports Atom, BitOps, CacheOps, Dragon; Cedar iBufMaxWords: NAT = 32; iBufMaxBytes: NAT = 4*iBufMaxWords; IFCState: TYPE = {pendingJump, fetchingFirst, fetchingMore, full, faulted}; ; IFetcherControl: CELL [ <<>> <> <<>> <> PreLengthAB >INT[3], InstReadyAB >BOOL, PreFetchFaultedBA >BOOL, GetNextInstB > <

> IPData =INT[32], -- driven on PhA IPParityB EnumType["Dragon.PBusCommands"], IPRejectB > NoneValidAB >BOOL, FetchFinishedB >BOOL, FlushB >BOOL, Take1B >BOOL, Take2B >BOOL, Take3B >BOOL, Take5B >BOOL, <<>> PreOpA > <> DHold0BA, DHold1AB > PhA preFetchPCWord[b]+1, ENDCASE => preFetchPCWord[b]; firstByteOffset[a] _ firstByteOffset[b]; pParityErrorAB _ (NOT DHold0BA AND successfulFetchBA) AND (CacheOps.Parity32[pDataBA] # pParityBA); NoneValidAB _ NHas1A; noRoomForMoreAB _ NoRoomForMoreA; END; -- of PhA evaluation IF PhB THEN BEGIN Dragon.Assert[NOT (IPFaultB # None AND NOT IPRejectB)]; Dragon.Assert[NOT (GetNextInstB AND JumpB)]; Dragon.Assert[NOT (GetNextInstB AND NOT InstReadyAB)]; PreFetchFaultedBA _ state[a] = faulted AND NOT InstReadyAB AND NOT JumpB; IF pParityErrorAB THEN IPNPErrorB _ FALSE; pDataBA _ BitOps.ExtractLongFDouble[container: IPData, containerWidth: 32, fieldPosition: 0, fieldWidth: 32]; -- latch for parity check pParityBA _ IPParityB; FetchFinishedB _ successfulFetchBA _ NOT DHold1AB AND NOT IPRejectB AND NOT JumpB AND state[a] IN [fetchingFirst..fetchingMore]; state[b] _ SELECT TRUE FROM DHold1AB => state[a], JumpB AND IPRejectB => pendingJump, NOT IPRejectB AND (JumpB OR state[a] = pendingJump) => fetchingFirst, state[a] IN [fetchingFirst..fetchingMore] AND IPFaultB # None => faulted, IPRejectB, state[a] = faulted => state[a], NOT noRoomForMoreAB => fetchingMore, ENDCASE => full; newFetchBA _ NOT IPRejectB AND state[b] IN [fetchingFirst..fetchingMore]; IF (FlushB _ NOT DHold1AB AND JumpB) THEN BEGIN firstByteOffset[b] _ BitOps.ExtractLongFDouble[container: XBus, containerWidth: 32, fieldPosition: 0, fieldWidth: 32] MOD 4; preFetchPCWord[b] _ BitOps.ExtractLongFDouble[container: XBus, containerWidth: 32, fieldPosition: 0, fieldWidth: 32]/4; END ELSE BEGIN firstByteOffset[b] _ firstByteOffset[a]; preFetchPCWord[b] _ preFetchPCWord[a]; END; Take1B _ GetNextInstB OR ((state[a]=fetchingFirst AND NOT IPRejectB) AND (firstByteOffset[a]>=1)); Take2B _ (GetNextInstB AND (PreLengthAB>=2)) OR ((state[a]=fetchingFirst AND NOT IPRejectB) AND (firstByteOffset[a]>=2)); Take3B _ (GetNextInstB AND (PreLengthAB>=3)) OR ((state[a]=fetchingFirst AND NOT IPRejectB) AND (firstByteOffset[a]>=3)); Take5B _ GetNextInstB AND (PreLengthAB>=5); END; -- of PhB evaluation ENDCELL; IFetcherArray: CELL [ <<>> <> IPDataB > PreOpA >INT[8], PreAlphaA >INT[8], PreBetaA >INT[8], PreGammaA >INT[8], PreDeltaA >INT[8], NHas1A >BOOL, Has2A >BOOL, Has3A >BOOL, Has5A >BOOL, NoRoomForMoreA >BOOL, <> PhA > EvalSimple iBufBytes: [0..iBufMaxBytes) _ 4*iBufWords; IF PhA THEN BEGIN FOR i: [0..iBufMaxBytes) IN [0..iBufBytes) DO Dragon.Assert[NOT validBA[i] OR validBA[i+3-(i MOD 4)]]; <<.. if any byte of a buffer word is valid, the last one is.>> ENDLOOP; FOR i: [0..iBufMaxBytes) IN [0..iBufBytes) DO SELECT TRUE FROM firstBA[i] => BEGIN PreOpA _ BitOps.WAND[PreOpA, byteBA[i]]; NHas1A _ FALSE; END; firstBA[(i+iBufBytes-1) MOD iBufBytes] => BEGIN PreAlphaA _ BitOps.WAND[PreAlphaA, byteBA[i]]; Has2A _ Has2A AND validBA[i]; END; firstBA[(i+iBufBytes-2) MOD iBufBytes] => BEGIN PreBetaA _ BitOps.WAND[PreBetaA, byteBA[i]]; Has3A _ Has3A AND validBA[i]; END; firstBA[(i+iBufBytes-3) MOD iBufBytes] => BEGIN PreGammaA _ BitOps.WAND[PreGammaA, byteBA[i]]; Has5A _ Has5A AND validBA[i]; END; firstBA[(i+iBufBytes-4) MOD iBufBytes] => BEGIN PreDeltaA _ BitOps.WAND[PreDeltaA, byteBA[i]]; Has5A _ Has5A AND validBA[i]; END; ENDCASE => NULL; ENDLOOP; FOR i: NAT _ 3, i+4 WHILE i < iBufBytes DO NoRoomForMoreA _ NoRoomForMoreA AND (validBA[i] OR validBA[(i+5) MOD iBufBytes]); <<.. at least one byte of the buffer must remain invalid, so that we can identify the start and end of the data. One fetch could already be in progress (storing into (i-4...i] ), so in the worst case we are deciding whether another one (into (i..i+4] ) can also finish without wiping out the invalid gap.>> ENDLOOP; validAB _ validBA; FOR i: [0..iBufMaxBytes) IN [0..iBufBytes) DO SELECT i FROM 0 => firstAB[i] _ firstBA[i] OR NoneValidAB; ENDCASE => firstAB[i] _ firstBA[i]; ENDLOOP; END; -- of PhA evaluation IF PhB THEN BEGIN IF FlushB THEN BEGIN r: REF = Atom.GetProp[$Cluster, $IBufWords]; iBufWords _ IF r#NIL THEN NARROW[r, REF INT]^ ELSE 8; iBufBytes _ 4*iBufWords; END; FOR i: [0..iBufMaxBytes) IN [0..iBufBytes) DO validBA[i] _ (validAB[i] <<.. was valid before>> OR (FetchFinishedB AND ((validAB[(i+iBufBytes-1-(i MOD 4)) MOD iBufBytes] AND NOT validAB[(i+3-(i MOD 4))]) OR (NoneValidAB AND i<4)))) <<.. becoming valid because memory read is finishing>> AND NOT FlushB AND NOT (Take1B AND firstAB[i]) AND NOT (Take2B AND firstAB[(i+iBufBytes-1) MOD iBufBytes]) AND NOT (Take3B AND firstAB[(i+iBufBytes-2) MOD iBufBytes]) AND NOT (Take5B AND firstAB[(i+iBufBytes-3) MOD iBufBytes]) AND NOT (Take5B AND firstAB[(i+iBufBytes-4) MOD iBufBytes]); <<.. becoming invalid because IFU has taken this byte>> <<>> IF FetchFinishedB AND ((validAB[(i+iBufBytes-1-(i MOD 4)) MOD iBufBytes] AND NOT validAB[(i+3-(i MOD 4))]) OR (NoneValidAB AND i<4)) THEN byteBA[i] _ BitOps.ECFD[IPDataB, 32, 8*(i MOD 4), 8]; ENDLOOP; FOR i: [0..iBufMaxBytes) IN [0..iBufBytes) DO firstBA[i] _ validBA[i] AND NOT validBA[(i+iBufBytes-1) MOD iBufBytes]; ENDLOOP; PreOpA _ PreAlphaA _ PreBetaA _ PreGammaA _ PreDeltaA _ LAST[Dragon.HexByte]; NHas1A _ Has2A _ Has3A _ Has5A _ NoRoomForMoreA _ TRUE; END; -- of PhB evaluation ENDCELL; Cedar PreFetcherState: TYPE = {pendingJump, fetching, waiting, faulted} _ faulted; ; IFetcher: CELL [ <<>> <> PreOpA >INT[8], PreAlphaA >INT[8], PreBetaA >INT[8], PreGammaA >INT[8], PreDeltaA >INT[8], PreLengthAB >INT[3], InstReadyAB >BOOL, PreFetchFaultedBA >BOOL, -- generated during PhB (there's no hurry) GetNextInstB > <

> IPData =INT[32], -- address PhA, data PhB IPCmdA >EnumType["Dragon.PBusCommands"], IPRejectB > DHold0BA > PhA