-- File: [Indigo]<Sakura>Dragon>DragonCacheControlImpl.sak -- Dragon Cache -- 18-Feb-82 15:50:59 DIRECTORY DragonCacheControl, Inline, SakuraRT; DragonCacheImpl: MONITOR IMPORTS Inline, SakuraRT EXPORTS DragonCacheControl = { -- The functionality of Dragon cache chip is described under the following --conventions: there are two main processes, a process to watch the processor bus --commands (PbusFetch), and a process to watch the memory bus commands --(BackDoor, backdoor operations). Furthermore, PbusFetch cooperates with --several other processes to allow overlapping of pipline operations: MProc is a --process that is invoked from PbusFetch and invokes Mbus operations directly. --Operations associated with Pbus commands are all split into two parts so that --they can be piplined. All the front parts of these operations are inside --PbusFetch, so they do not constitute independent processes. The latter parts --are all independent processes. They are FetchTransport, StoreTransport, and --DoMapOpTransport. -- Communications among processes: --Communication between PbusFetch and MProc is done through two global --variables: DoMProc and MProcDone. The communication between PbusFetch --and transport processes, FetchTransport, StoreTransport, and --DoMapOpTransport, is done by global variables, FetchTransportGo, --StoreTransportGo, and DoMapOpTransportGo, and ~Reject for the other --direction. -- i) Fetch --Match on Pbus --IF success THEN Fetch --ELSE { -- IF Victim dirty THEN WriteQuad Victim; -- Partial Match on Pbus -- IF ~ success THEN ReadMap; -- ReadQuad}; --ii) Store --Match on Pbus --IF success THEN -- IF ~Shared THEN -- IF RpDirty THEN Store to Ram -- ELSE {SetRpDirty; Store to Ram} -- ELSE -- IF RpDirty THEN WriteSingle -- ELSE {SetRpDirty; WriteSingle} --ELSE { -- IF Victim dirty THEN WriteQuad Victim; -- PartialMatch; -- IF ~success THEN ReadMap; -- ReadQuad; -- GO TO ii) Store} Cell: TYPE = RECORD [ vp: LONG CARDINAL, rp: LONG CARDINAL, bl: [0..37B], D: ARRAY [0..3] OF LONG CARDINAL, VpValid, RpValid, RpDirty, CEDirty, Shared, TIP: BOOLEAN]; PbusType: TYPE = RECORD [ body: SELECT kind: {Instruction, Data} FROM Instruction => [vp: LONG CARDINAL -- actually 25 bits --, bl: [0..37B], word: [0..3]], Data => [data: LONG CARDINAL] ENDCASE]; MbusType: TYPE = RECORD [ body: SELECT kind: {Instruction, MapCommand, Data} FROM Instruction => [command: MbusCommand, rp: LONG CARDINAL -- actually 25 bits --, bl: [0..37B], word: [0..3]], MapCommand => [command: MbusCommand, mapop: MapOpKind, fault: BOOLEAN, vp: LONG CARDINAL], Data => [data: LONG CARDINAL] ENDCASE]; MbusCommand: TYPE = {ReadQuad, WriteQuad, WriteSingle, NotReady, ReadMap, DoMapOp, SetRpDirty, SetRpDirtyDone}; MapOpKind: TYPE = {SetMap, SetMapFlags, GetMapFlags}; MProcType: TYPE = PROC; -- Constants DataArraySize: CARDINAL = 64; -- Global variables FetchTransportGo, StoreTransportGo, DoMapOpTransportGo, Grant, Holding, MShared, DoMProc, MProcDone, PRq, NewRq, MRq, Orph, MCMD: BOOLEAN; Instruction, Reqbus: {Fetch, FetchHold, Store, MapOp, Noop}; DataIndex, VictimIndex: CARDINAL; RqVP, MVP: LONG CARDINAL; RqBL, PBL, MBL: [0..37B]; RqData: LONG CARDINAL; PWord, MWord: [0..3]; PResult: LONG CARDINAL; PRP, MRP: LONG CARDINAL; Pbus: PbusType; Mbus: MbusType; Data: ARRAY [0..DataArraySize) OF Cell; MOp: MProcType; MOResult: LONG CARDINAL; MRdData: LONG CARDINAL; MWData: LONG CARDINAL; MInst: MbusCommand; MapOp: MapOpKind; PageFault: SIGNAL = CODE; WriteViolation: SIGNAL = CODE; Cache: PUBLIC DEVICE = { IN PDataIn, MDataIn: LONG CARDINAL, CMDIn, RQ, SharedIn: BOOLEAN OUT Exception, Reject, SharedOut, CMDOut: BOOLEAN, PDataOut, MDataOut: LONG CARDIANL GUARDIAN {} CONTROL { -- PbusFetch process procedures PbusFetch: PROC = { success: BOOLEAN; DO --A (Phase A) IF RQ AND ~Reject THEN { Exception ← FALSE; WITH b: Pbus SELECT FROM Instruction => {RqVP ← b.vp; RqBL ← b.bl; PWord ← b.word}; ENDCASE => ERROR; Instruction ← Reqbus; --M (Phase B) [success, DataIndex] ← FullMatch[RqVP, RqBL]; { ENABLE { PageFault => {Pbus ← [Data[-1]]; Exception ← TRUE}; WriteViolation => {Pbus ← [Data[0]]; Exception ← TRUE}}; SELECT Instruction FROM Fetch => CallFetch[]; FetchHold => CallFetchHold[! PageFault => {Pbus ← [Data[-1]]; Holding ← FALSE; Exception ← TRUE}; WriteViolation => {Pbus ← [Data[0]]; Exception ← TRUE}]; Store => CallStore[]; MapOp => CallMapOp[]; Noop => NULL; ENDCASE} }; ENDLOOP}; CallFetch: PROC = { success: BOOLEAN; -- Started at Phase B IF success THEN { --hit Reject ← FALSE; FetchTransportGo ← TRUE; Holding ← FALSE} ELSE { Reject ← TRUE; Holding ← FALSE; --R (Phase A) Holding ← TRUE; --T (Phase B) PRq ← TRUE; WaitForGrant[]; WriteBackVictimIfDirty[]; [success, PRP] ← PartialMatch[RqVP]; --Clock (Phase B) IF ~success THEN CallMProc[ReadMap]; CallMProc[ReadQuad]; PRq ← FALSE; Reject ← FALSE; [success, DataIndex] ← FullMatch[RqVP, RqBL]; IF ~success THEN ERROR; -- This is a description error FetchTransportGo ← TRUE} }; CallFetchHold: PROC = { -- Started at Phase B IF ~Holding THEN { Reject ← TRUE; PRq ← TRUE; WaitForGrant[]; --Clock (Phase B) Holding ← TRUE}; CallFetch[]}; CallStore: PROC = { success: BOOLEAN; Reject ← TRUE; -- Clock (A) WITH b: Pbus SELECT FROM Data => RqData ← b.data; ENDCASE => ERROR; IF ~success THEN { PRq ← TRUE; WaitForGrant[]; WriteBackVictimIfDirty[]; --Clock (Phase B) [success, PRP] ← PartialMatch[RqVP]; IF ~success THEN CallMProc[ReadMap]; --Clock (Phase B) CallMProc[ReadQuad]}; --Clock (B) [success, DataIndex] ← FullMatch[RqVP, RqBL]; IF ~Data[DataIndex].Shared THEN { IF~Data[DataIndex].RpDirty THEN CallMProc[SetRpDirty]; Reject ← FALSE; StoreTransportGo ← TRUE} ELSE { IF~Data[DataIndex].RpDirty THEN CallMProc[SetRpDirty]; Data[DataIndex].D[PWord] ← RqData; CallMProc[WriteSingle]}; PRq ← FALSE; }; -- CallStore CallMapOp: PROC = { -- Started at Phase B Reject ← TRUE; PRq ← TRUE; WaitForGrant[]; -- Clock (A) WITH b: Pbus SELECT FROM Data => RqData ← b.data; ENDCASE => ERROR; CallMProc[DoMapOp]; PRq ← FALSE}; -- CallMapOp CallMProc: PROC [procedure: MProcType] = { -- Starts in Phase B and finishes in Phase B MProcDone ← FALSE; DoMProc ← TRUE; MOp ← procedure; DO --Clock (Phase A) IF MProcDone THEN EXIT; ENDLOOP}; -- CallMProc WriteBackVictimIfDirty: PROC = { -- Starts at Phase A MRP ← Data[VictimIndex].rp; MBL ← Data[VictimIndex].bl; IF Data[VictimIndex].CEDirty THEN { CallMProc[WriteQuad]; Data[VictimIndex].CEDirty ← FALSE}; }; -- WriteBackVictimIfNotClean WaitForGrant: PROC = { DO --Clock (Phase A) IF Grant THEN EXIT ENDLOOP}; -- WaitForGrant -- FetchTransport process procedures FetchTransport: PROC = { -- Starts at Phase A DO --R (Phase A) IF FetchTransportGo THEN { PResult ← Data[DataIndex].D[PWord]; FetchTransportGo ← FALSE; --T (Phase B) Pbus ← [Data[PResult]]}; ENDLOOP}; StoreTransport: PROC = { -- Starts at Phase A DO --clock (A) IF StoreTransportGo THEN { Data[DataIndex].D[PWord] ← RqData; StoreTransportGo ← FALSE} ENDLOOP}; -- StoreTransport DoMapOpTransport: PROC = { DO -- clock (B) IF DoMapOpTransportGo THEN { NewRq ← TRUE; MOResult ← MRdData; Reject ← FALSE; --clock (A) PResult ← MOResult; NewRq ← FALSE; -- clock (B) IF Inline.BITAND[Inline.HighHalf[PResult],40000B]#0 THEN Exception ← TRUE; Pbus ← [Data[PResult]]} ENDLOOP}; -- DoMapOpTransport -- MProc process procedures MProc: PROC = { DO --Clock (Phase A) MProcDone ← FALSE; IF DoMProc THEN { DoMProc ← FALSE; MOp[]}; ENDLOOP}; WriteQuad: PROC = { i: CARDINAL; WriteOneWord: PROC [pword: [0..3]] = { --Clock (Phase B) MWData ← Data[DataIndex].D[pword]; --Clock (Phase A) Mbus ← [Data[MWData]]}; -- WriteOneWord --Clock (Phase A) Mbus ← [Instruction[WriteQuad, MRP, MBL, 0]]; FOR i IN [0..3] DO WriteOneWord[i] ENDLOOP; MProcDone ← TRUE}; -- WriteQuad ReadMap: PROC = { fault: BOOLEAN; --Clock (Phase A) Mbus ← [MapCommand[ReadMap, , , MVP]]; fault ← WaitMapOpDone[]; IF fault THEN SIGNAL PageFault; MProcDone ← TRUE}; ReadQuad: PROC = { ReadOneWord: PROC = {IF ~Orph THEN ReadDataFromBus[@Data[DataIndex].D[PWord]]}; success: BOOLEAN; --Clock (Phase A) Mbus ← [Instruction[ReadQuad, PRP, PBL, PWord]]; WITH b: Mbus SELECT FROM Instruction => {MRP ← b.rp; MBL ← b.bl; MWord ← b.word}; ENDCASE => ERROR; --Clock (Phase B, t2) MRq ← TRUE; --Clock (Phase A, t3) [success, DataIndex] ← FullMatch[MRP, MBL]; --Clock (Phase B, t4) Orph ← success; IF ~success THEN DataIndex ← VictimIndex; --Clock (Phase A, t5) IF ~success THEN { Data[DataIndex].rp ← MRP; Data[DataIndex].bl ← MBL}; --Clock (Phase B, t6) Data[DataIndex].vp ← RqVP; Data[DataIndex].Shared ← SharedIn; VictimIndex ← (VictimIndex+1) MOD DataArraySize; --Clock (Phase A, t7) MCMD ← CMDIn; ReadOneWord[]; IF MCMD AND MInst=NotReady THEN WaitOneCycle[]; MProcDone ← TRUE; --Clock (Phase B, t8) ReadOneWord[]; --Clock (Phase A, t9) PWord ← (PWord+1) MOD 4; --Clock (Phase B, t10) Data[DataIndex].TIP ← TRUE; ReadOneWord[]; MRq ← FALSE; IF ~Holding THEN NewRq ← TRUE; --Clock (Phase A, t11) PWord ← (PWord+1) MOD 4; --Clock (Phase B, t12) ReadOneWord[]; IF ~Holding THEN NewRq ← FALSE; --Clock (Phase A, t13) PWord ← (PWord+1) MOD 4; --Clock (Phase B, t14) ReadOneWord[]; Data[DataIndex].TIP ← FALSE}; SetRpDirty: PROC = { fault: BOOLEAN; --Clock (Phase A) Mbus ← [Instruction[SetRpDirty, PRP, PBL, PWord]]; WITH b: Mbus SELECT FROM Instruction => { MRP ← b.rp; MBL ← b.bl; MWord ← b.word}; ENDCASE => ERROR; --Clock (Phase B) fault ← WaitMapOpDone[]; IF fault THEN SIGNAL WriteViolation; MProcDone ← TRUE; }; WriteSingle: PROC = { --Clock (Phase A) Mbus ← [Instruction[WriteSingle, PRP, PBL, PWord]]; NewRq ← TRUE; --Clock (Phase B) MWData ← Data[DataIndex].D[PWord]; --Clock (Phase A) Mbus ← [Data[MWData]]; MProcDone ← TRUE; NewRq ← FALSE; }; DoMapOp: PROC = { fault: BOOLEAN; --Clock (Phase A) Mbus ← [MapCommand[DoMapOp, MapOp, , MVP]]; MCMD ← TRUE; --Clock (Phase B) MWData ← RqData; --Clock (Phase A) Mbus ← [Data[MWData]]; fault ← WaitMapOpDone[]; IF fault THEN SIGNAL PageFault; MProcDone ← TRUE; ReadDataFromBus[@MRdData]; DoMapOpTransportGo ← TRUE}; -- DoMapOp WaitMapOpDone: PROC RETURNS [fault: BOOLEAN] = { DO --Clock (Phase A) MCMD ← CMDIn; [MInst, fault] ← DecodeMbusCommand[]; IF MCMD AND MInst=SetRpDirtyDone THEN EXIT; ENDLOOP; }; DecodeMbusCommand: PROC RETURNS [MInst: MbusCommand, fault: BOOLEAN] = { WITH b: Mbus SELECT FROM MapCommand => {MInst ← b.command; fault ← b.fault}; ENDCASE => ERROR}; WaitOneCycle: PROC = { --Clock (Phase B) --Clock (Phase A) }; -- Backdoor process procedures BackDoor: PROC = { DO -- clock (B) MCMD ← CMDIn; [MInst, ] ← DecodeMbusCommand[]; IF MCMD THEN SELECT MInst FROM ReadQuad => BDReadQuad[]; WriteQuad => BDWriteQuad[]; WriteSingle => BDWriteSingle[]; ReadMap => NULL; SetRpDirty => BDSetRpDirty[]; DoMapOp => NULL; ENDCASE; ENDLOOP}; BDReadQuad: PROC = { success: BOOLEAN; ReadOneWord: PROC = { -- clock (B) IF success THEN MWData ← Data[DataIndex].D[MWord]; -- clock (A) IF success THEN Mbus ← [Data[MWData]]; MWord ← (MWord+1) MOD 4; }; [success, DataIndex] ← FullMatch[MRP, MBL]; -- clock (A) IF success THEN MShared ← TRUE; THROUGH [1..4] DO ReadOneWord[] ENDLOOP; -- clock (B) MShared ← FALSE}; -- BDReadQuad BDWriteQuad: PROC = { success: BOOLEAN; WriteOneWord: PROC = { -- clock (B) IF success THEN Data[DataIndex].D[MWord] ← MRdData; -- clock (A) MWord ← MWord+1; ReadDataFromBus[@MRdData]}; [success, DataIndex] ← FullMatch[MRP, MBL]; -- clock (A) IF success THEN { MShared ← TRUE; MWord ← 0; ReadDataFromBus[@MRdData]}; THROUGH [1..3] DO WriteOneWord[] ENDLOOP; -- clock (B) IF success THEN Data[DataIndex].D[MWord] ← MRdData; IF success THEN MShared ← FALSE}; -- BDWriteQuad BDWriteSingle: PROC = { success: BOOLEAN; [success, DataIndex] ← FullMatch[MRP, MBL]; -- clock (A) ReadDataFromBus[@MRdData]; -- clock (B) IF success THEN Data[DataIndex].D[MWord] ← MRdData};-- BDWriteSingle BDSetRpDirty: PROC = { success: BOOLEAN; [success, DataIndex] ← FullMatch[MRP, MBL]; -- clock (A) -- clock (B) IF success THEN Data[DataIndex].RpDirty ← TRUE}; -- BDSetRpDirty ReadDataFromBus: PROC [data: POINTER TO LONG CARDINAL] = { WITH b: Mbus SELECT FROM Data => data↑ ← b.data; ENDCASE => ERROR}; -- Data array access procedures FullMatch: ENTRY PROC [vp: LONG CARDINAL, bl: CARDINAL] RETURNS [BOOLEAN, CARDINAL] = { FOR i: CARDINAL IN [0..DataArraySize) DO IF Data[i].VpValid AND Data[i].vp=vp AND Data[i].bl=bl THEN RETURN [TRUE, i] ENDLOOP; RETURN[FALSE, 0]}; PartialMatch: ENTRY PROC [vp: LONG CARDINAL] RETURNS [BOOLEAN, CARDINAL] = { FOR i: CARDINAL IN [0..DataArraySize) DO IF Data[i].VpValid AND Data[i].vp=vp THEN RETURN [TRUE, i] ENDLOOP; RETURN[FALSE, 0]}; PAR { PbusFetch[] // FetchTransport[] // StoreTransport[] // DoMapOpTransport[] // MProc[] // BackDoor[]} } }; }.