-- File: [Indigo]Dragon>DragonCacheImpl.sak -- Dragon Cache -- 23-Mar-82 13:02:29 DIRECTORY ConvertUnsafe: TYPE, DragonCache: TYPE, Inline: TYPE, SakuraRT: TYPE, SimIO: TYPE; DragonCacheImpl: MONITOR IMPORTS ConvertUnsafe, Inline, SakuraRT, SimIO EXPORTS DragonCache -- 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. = BEGIN Cell: TYPE = RECORD [vp: LONG CARDINAL, rp: LONG CARDINAL, bl: INTEGER [0..37B], D: ARRAY INTEGER [0..3] OF LONG CARDINAL, VpValid, RpValid, RpDirty, CEDirty, Shared, TIP: BOOLEAN]; MProcType: TYPE = PROC; -- Constants DataArraySize: CARDINAL = 64; ProcessorNum: STRING = "Proc1: "; -- Global variables FetchTransportGo, StoreTransportGo, DoMapOpTransportGo, Holding, DoMProc, MProcDone, PRq, NewRq, MRq, Orph, MCMD: BOOLEAN; Instruction: DragonCache.PbusOp; DataIndex, VictimIndex: CARDINAL; RqBL, PBL, MBL: INTEGER [0..37B]; PWord, MWord: INTEGER [0..3]; RqVP, MVP, RqData, PResult, PRP, MRP, MOResult, MRdData, MWData: LONG CARDINAL; Data: ARRAY INTEGER [0..DataArraySize) OF Cell; MOp: MProcType; MInst: DragonCache.MbusCommand; MapOp: DragonCache.MapOpKind; RpDirtyReg: BOOLEAN; -- This register is set by ReadMap or PartialMatch PageFault: SIGNAL = CODE; WriteViolation: SIGNAL = CODE; CheckVal: PUBLIC ENTRY PROC [vp: LONG CARDINAL, bl: INTEGER [0..37B], word: INTEGER [0..3], val: LONG CARDINAL] = { loc: CARDINAL; matched: BOOLEAN; [matched, loc] _ FullVpMatch[vp, bl]; IF NOT matched THEN ERROR; IF Data[loc].D[word] # val THEN ERROR}; Cache: PUBLIC PROC [Op: SakuraRT.Handle, PDataIn: SakuraRT.Handle, MDataIn: SakuraRT.Handle, ClockA, ClockB, CMDIn, RQ, SharedIn, Grant: SakuraRT.Handle, Exception, Reject, SharedOut, CMDOut, Rq: SakuraRT.Handle, PDataOut: SakuraRT.Handle, MDataOut: SakuraRT.Handle] = { -- PbusFetch process procedures PbusFetch: PROC = { success: BOOLEAN; {ENABLE {ABORTED => GO TO Aborted}; DO SakuraRT.GetNew[ClockA, TRUE]; NULL; --A (Phase A) IF NARROW[SakuraRT.Get[RQ], REF BOOLEAN]^ AND NOT NARROW[SakuraRT.Get[Reject], REF BOOLEAN]^ THEN {SakuraRT.Put[Exception, NEW[BOOLEAN _ FALSE]]; WITH b: NARROW[SakuraRT.Get[PDataIn], REF DragonCache.PbusType]^ SELECT FROM Instruction => {RqVP _ b.vp; RqBL _ b.bl; PWord _ b.word} ENDCASE => ERROR; Instruction _ NARROW[SakuraRT.Get[Op], REF DragonCache.PbusOp]^; SakuraRT.GetNew[ClockB, TRUE]; [success, DataIndex] _ FullVpMatch[RqVP, RqBL]; --M (Phase B) {ENABLE { PageFault => {SakuraRT.Put[PDataOut, NEW[DragonCache.PbusType _ [Data[-1]]]]; SakuraRT.Put[Exception, NEW[BOOLEAN _ TRUE]]}; WriteViolation => {SakuraRT.Put[PDataOut, NEW[DragonCache.PbusType _ [Data[0]]]]; SakuraRT.Put[Exception, NEW[BOOLEAN _ TRUE]]}}; SELECT Instruction FROM Fetch => CallFetch[success]; FetchHold => CallFetchHold [success ! PageFault => {SakuraRT.Put[PDataOut, NEW[DragonCache.PbusType _ [Data[- 1]]]]; Holding _ FALSE; SakuraRT.Put[Exception, NEW[BOOLEAN _ TRUE]]}; WriteViolation => {SakuraRT.Put[PDataOut, NEW[DragonCache.PbusType _ [Data[0]]]]; SakuraRT.Put[Exception, NEW[BOOLEAN _ TRUE]]}]; Store => CallStore[success]; MapOp => CallMapOp[success] ENDCASE}} ENDLOOP; SakuraRT.ProcessEnd[]} EXITS Aborted => SakuraRT.Abort[]}; WaitForTIP: PROC = { SakuraRT.Put[Reject, NEW[BOOLEAN _ TRUE]]; DO SakuraRT.Delay[30]; IF Data[DataIndex].TIP THEN {SakuraRT.GetNew[ClockB, TRUE]; NULL; LOOP} ELSE EXIT ENDLOOP}; CallFetch: PROC [success: BOOLEAN] = { -- Started at Phase B index: CARDINAL; IF success --hit THEN {WaitForTIP[]; SakuraRT.Put[Reject, NEW[BOOLEAN _ FALSE]]; FetchTransportGo _ TRUE; Holding _ FALSE} ELSE {SakuraRT.Put[Reject, NEW[BOOLEAN _ TRUE]]; Holding _ FALSE; SakuraRT.GetNew[ClockA, TRUE]; Holding _ TRUE; --R (Phase A) SakuraRT.Delay[10]; PRq _ TRUE; --T (Phase B) WaitForGrant[]; WriteBackVictimIfDirty[]; [success, index] _ PartialMatch[RqVP]; PRP _ Data[index].rp; SakuraRT.GetNew[ClockB, TRUE]; IF NOT success THEN CallMProc[ReadMap, "ReadMap"]; IF success THEN CallMProc[ReadQuadMatch, "ReadQuad"] ELSE CallMProc[ReadQuad, "ReadQuad"]; PRq _ FALSE; SakuraRT.Put[Reject, NEW[BOOLEAN _ FALSE]]; [success, DataIndex] _ FullVpMatch[RqVP, RqBL]; IF NOT success THEN ERROR; -- This is a description error FetchTransportGo _ TRUE}}; CallFetchHold: PROC [success: BOOLEAN] = { -- Started at Phase B IF NOT Holding THEN {SakuraRT.Put[Reject, NEW[BOOLEAN _ TRUE]]; SakuraRT.GetNew[ClockA, TRUE]; NULL; SakuraRT.Delay[10]; PRq _ TRUE; WaitForGrant[]; SakuraRT.GetNew[ClockB, TRUE]; Holding _ TRUE}; CallFetch[success]}; CallStore: PROC [success: BOOLEAN] = { SakuraRT.Put[Reject, NEW[BOOLEAN _ TRUE]]; SakuraRT.GetNew[ClockA, TRUE]; WITH b: NARROW[SakuraRT.Get[PDataIn], REF DragonCache.PbusType]^ SELECT FROM Data => RqData _ b.data ENDCASE => ERROR; WaitForTIP[]; IF NOT success THEN {SakuraRT.Delay[10]; PRq _ TRUE; WaitForGrant[]; WriteBackVictimIfDirty[]; SakuraRT.GetNew[ClockB, TRUE]; {[success, DataIndex] _ PartialMatch[RqVP]; PRP _ Data[DataIndex].rp; IF NOT success THEN CallMProc[ReadMapAndSetRpDirty, "ReadMapAndSetRpDirty"]}; SakuraRT.GetNew[ClockB, TRUE]; IF success THEN CallMProc[ReadQuadMatch, "ReadQuad"] ELSE CallMProc[ReadQuad, "ReadQuad"]}; SakuraRT.GetNew[ClockB, TRUE]; [success, DataIndex] _ FullVpMatch[RqVP, RqBL]; Data[DataIndex].CEDirty _ TRUE; IF NOT Data[DataIndex].RpDirty THEN {IF NOT PRq THEN {PRq _ TRUE; WaitForGrant[]}; CallMProc[ReadMapAndSetRpDirty, "ReadMapAndSetRpDirty"]}; IF NOT Data[DataIndex].Shared THEN StoreTransportGo _ TRUE ELSE {Data[DataIndex].D[PWord] _ RqData; IF NOT PRq THEN {PRq _ TRUE; WaitForGrant[]}; CallMProc[WriteSingle, "WriteSingle"]}; SakuraRT.Put[Reject, NEW[BOOLEAN _ FALSE]]; PRq _ FALSE}; -- CallStore CallMapOp: PROC [success: BOOLEAN] = { -- Started at Phase B SakuraRT.Put[Reject, NEW[BOOLEAN _ TRUE]]; SakuraRT.GetNew[ClockA, TRUE]; NULL; SakuraRT.Delay[10]; PRq _ TRUE; WaitForGrant[]; SakuraRT.GetNew[ClockA, TRUE]; WITH b: NARROW[SakuraRT.Get[PDataIn], REF DragonCache.PbusType]^ SELECT FROM Data => RqData _ b.data ENDCASE => ERROR; CallMProc[DoMapOp, "DoMapOp"]; PRq _ FALSE}; -- CallMapOp CallMProc: PROC [procedure: MProcType, name: REF TEXT] = { -- Starts in Phase B and finishes in Phase B st: LONG STRING _ [25]; ConvertUnsafe.AppendRefText[st, name]; WaitMProcReallyDone[]; SetMProcDone[FALSE]; SetDoMProc[TRUE]; MOp _ procedure; SimIO.WF2[" %sMbus op: %s started*n", ProcessorNum, st]; DO SakuraRT.GetNew[ClockB, TRUE]; IF IsMProcDone[] THEN EXIT ENDLOOP; SimIO.WF2[" %sMbus op: %s finished*n", ProcessorNum, st]}; -- CallMProc WaitMProcReallyDone: PROC = { -- Starts in Phase B DO SakuraRT.Delay[30]; IF IsMProcReallyDone[] THEN EXIT; SakuraRT.GetNew[ClockB, TRUE]; NULL ENDLOOP}; SetMProcReallyDone: ENTRY PROC [val: BOOLEAN] = { MProcReallyDone _ val}; IsMProcReallyDone: ENTRY PROC RETURNS [BOOLEAN] = { RETURN [MProcReallyDone]}; MProcReallyDone: BOOLEAN _ TRUE; WriteBackVictimIfDirty: PROC = { -- Starts at Phase A MRP _ Data[VictimIndex].rp; MBL _ Data[VictimIndex].bl; IF Data[VictimIndex].RpValid AND Data[VictimIndex].CEDirty THEN {CallMProc[WriteQuad, "WriteQuad"]; Data[VictimIndex].CEDirty _ FALSE}}; -- WriteBackVictimIfNotClean WaitForGrant: PROC = { DO SakuraRT.GetNew[ClockA, TRUE]; IF NARROW[SakuraRT.Get[Grant], REF BOOLEAN]^ THEN EXIT ENDLOOP}; -- WaitForGrant -- FetchTransport process procedures FetchTransport: PROC = { -- Starts at Phase B {ENABLE {ABORTED => GO TO Aborted}; DO SakuraRT.GetNew[ClockA, TRUE]; NULL; --R (Phase A) IF FetchTransportGo THEN {PResult _ Data[DataIndex].D[PWord]; FetchTransportGo _ FALSE; SakuraRT.GetNew[ClockB, TRUE]; SakuraRT.Put[PDataOut, NEW[DragonCache.PbusType _ [Data[PResult]]]]} ENDLOOP; SakuraRT.ProcessEnd[]} EXITS Aborted => SakuraRT.Abort[]}; StoreTransport: PROC = { -- Starts at Phase B index, pword: CARDINAL; success: BOOLEAN; {ENABLE {ABORTED => GO TO Aborted}; DO SakuraRT.GetNew[ClockB, TRUE]; {pword _ PWord; [success, index] _ FullVpMatch[RqVP, RqBL]}; SakuraRT.GetNew[ClockA, TRUE]; IF StoreTransportGo THEN {IF NOT success THEN ERROR; Data[index].D[pword] _ RqData; StoreTransportGo _ FALSE} ENDLOOP; SakuraRT.ProcessEnd[]} EXITS Aborted => SakuraRT.Abort[]}; -- StoreTransport DoMapOpTransport: PROC = { {ENABLE {ABORTED => GO TO Aborted}; DO SakuraRT.GetNew[ClockB, TRUE]; NULL; -- (B) IF DoMapOpTransportGo THEN {NewRq _ TRUE; MOResult _ MRdData; SakuraRT.Put[Reject, NEW[BOOLEAN _ FALSE]]; SakuraRT.GetNew[ClockA, TRUE]; {PResult _ MOResult; NewRq _ FALSE}; SakuraRT.GetNew[ClockB, TRUE]; {IF Inline.BITAND[Inline.HighHalf[PResult], 40000B] # 0 THEN SakuraRT.Put[Exception, NEW[BOOLEAN _ TRUE]]; SakuraRT.Put[PDataOut, NEW[DragonCache.PbusType _ [Data[PResult]]]]}} ENDLOOP; SakuraRT.ProcessEnd[]} EXITS Aborted => SakuraRT.Abort[]}; -- DoMapOpTransport -- MProc process procedures MProc: PROC = { {ENABLE {ABORTED => GO TO Aborted}; SetMProcDone[FALSE]; DO SakuraRT.GetNew[ClockA, TRUE]; NULL; IF IsDoMProc[] THEN {SetDoMProc[FALSE]; SakuraRT.Put[CMDOut, NEW[BOOLEAN _ TRUE]]; MOp[]} ENDLOOP; SakuraRT.ProcessEnd[]} EXITS Aborted => SakuraRT.Abort[]}; SetDoMProc: ENTRY PROC [val: BOOLEAN] = { DoMProc _ val}; IsDoMProc: ENTRY PROC RETURNS [BOOLEAN] = { RETURN [DoMProc]}; SetMProcDone: ENTRY PROC [val: BOOLEAN] = { MProcDone _ val}; IsMProcDone: ENTRY PROC RETURNS [BOOLEAN] = { RETURN [MProcDone]}; WriteQuad: PROC = { i: CARDINAL; WriteOneWord: PROC [pword: INTEGER [0..3]] = { SakuraRT.GetNew[ClockB, TRUE]; MWData _ Data[VictimIndex].D[pword]; SakuraRT.GetNew[ClockA, TRUE]; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Data[MWData]]]]}; -- WriteOneWord SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Instruction[WriteQuad, MRP, MBL, 0]]]]; SakuraRT.GetNew[ClockB, TRUE]; MWData _ Data[VictimIndex].D[0]; SakuraRT.Delay[20]; SakuraRT.Put[CMDOut, NEW[BOOLEAN _ FALSE]]; SakuraRT.GetNew[ClockA, TRUE]; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Data[MWData]]]]; FOR i IN [1..3] DO WriteOneWord[i] ENDLOOP; SakuraRT.GetNew[ClockB, TRUE]; SetMProcDone[TRUE]; SetMProcReallyDone[TRUE]}; -- WriteQuad ReadMap: PROC = { fault: BOOLEAN; MVP _ RqVP; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [MapCommand[ReadMap, , , , MVP]]]]; SakuraRT.GetNew[ClockB, TRUE]; SakuraRT.Delay[20]; SakuraRT.Put[CMDOut, NEW[BOOLEAN _ FALSE]]; fault _ WaitMapOpDone[]; IF fault THEN SIGNAL PageFault; WITH b: NARROW[SakuraRT.Get[MDataIn], REF DragonCache.MbusType]^ SELECT FROM MapCommand => {MRP _ b.vp; RpDirtyReg _ b.rpdirty} ENDCASE => ERROR; SetMProcDone[TRUE]; SetMProcReallyDone[TRUE]}; ReadMapAndSetRpDirty: PROC = { fault: BOOLEAN; MVP _ RqVP; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [MapCommand[ReadMapAndSetRpDirty, , , , MVP]]]]; SakuraRT.GetNew[ClockB, TRUE]; SakuraRT.Delay[20]; SakuraRT.Put[CMDOut, NEW[BOOLEAN _ FALSE]]; fault _ WaitMapOpDone[]; IF fault THEN SIGNAL PageFault; WITH b: NARROW[SakuraRT.Get[MDataIn], REF DragonCache.MbusType]^ SELECT FROM MapCommand => {MRP _ b.vp; RpDirtyReg _ b.rpdirty} ENDCASE => ERROR; SetMProcDone[TRUE]; SetMProcReallyDone[TRUE]}; ReadQuadMatch: PROC = { MRP _ PRP; ReadQuad[]}; ReadQuad: PROC = { ReadOneWord: PROC = { IF NOT Orph THEN ReadDataFromBus[@Data[index].D[pword]]}; success: BOOLEAN; pword: CARDINAL _ PWord; index: CARDINAL; PBL _ RqBL; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Instruction[ReadQuad, MRP, PBL, pword]]]]; WITH b: NARROW[SakuraRT.Get[MDataIn], REF DragonCache.MbusType]^ SELECT FROM Instruction => {MRP _ b.rp; MBL _ b.bl; MWord _ b.word} ENDCASE => ERROR; SakuraRT.GetNew[ClockB, TRUE]; MRq _ TRUE; -- (Phase B, t2) SakuraRT.Delay[20]; SakuraRT.Put[CMDOut, NEW[BOOLEAN _ FALSE]]; SakuraRT.GetNew[ClockA, TRUE]; [success, index] _ FullRpMatch[MRP, MBL]; -- (Phase A, t3) SakuraRT.GetNew[ClockB, TRUE]; -- (Phase B, t4) {Orph _ success; IF NOT success THEN index _ VictimIndex}; SakuraRT.GetNew[ClockA, TRUE]; IF NOT success THEN -- (Phase A, t5) {Data[index].rp _ MRP; Data[index].bl _ MBL; Data[index].RpValid _ TRUE; Data[index].Shared _ FALSE; Data[index].CEDirty _ FALSE; Data[index].RpDirty _ RpDirtyReg}; SakuraRT.GetNew[ClockB, TRUE]; -- (Phase B, t6) -- Data[index].vp _ RqVP; Data[index].VpValid _ TRUE; Data[index].Shared _ NARROW[SakuraRT.Get[SharedIn], REF BOOLEAN]^; VictimIndex _ (VictimIndex + 1) MOD DataArraySize; SakuraRT.GetNew[ClockA, TRUE]; MCMD _ NARROW[SakuraRT.Get[CMDIn], REF BOOLEAN]^; -- (Phase A, t7) IF MCMD AND MInst = NotReady THEN WaitOneCycle[]; SetMProcDone[TRUE]; SakuraRT.GetNew[ClockB, TRUE]; ReadOneWord[]; -- (Phase B, t8) SakuraRT.GetNew[ClockA, TRUE]; pword _ (pword + 1) MOD 4; -- (Phase A, t9) SakuraRT.GetNew[ClockB, TRUE]; -- (Phase B, t10) -- {Data[index].TIP _ TRUE; ReadOneWord[]; MRq _ FALSE; IF NOT Holding THEN NewRq _ TRUE}; SakuraRT.GetNew[ClockA, TRUE]; pword _ (pword + 1) MOD 4; -- (Phase A, t11) SakuraRT.GetNew[ClockB, TRUE]; -- (Phase B, t12) {ReadOneWord[]; IF NOT Holding THEN NewRq _ FALSE}; SakuraRT.GetNew[ClockA, TRUE]; pword _ (pword + 1) MOD 4; -- (Phase A, t13) SakuraRT.GetNew[ClockB, TRUE]; -- (Phase B, t14) -- {ReadOneWord[]; Data[index].TIP _ FALSE; SetMProcReallyDone[TRUE]}}; SetRpDirty: PROC = { -- Starts in A fault: BOOLEAN; PBL _ RqBL; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Instruction[SetRpDirty, MRP, PBL, PWord]]]]; WITH b: NARROW[SakuraRT.Get[MDataIn], REF DragonCache.MbusType]^ SELECT FROM Instruction => {MRP _ b.rp; MBL _ b.bl; MWord _ b.word} ENDCASE => ERROR; SakuraRT.GetNew[ClockB, TRUE]; fault _ WaitMapOpDone[]; IF fault THEN SIGNAL WriteViolation; SetMProcDone[TRUE]; SetMProcReallyDone[TRUE]}; WriteSingle: PROC = { PBL _ RqBL; PRP _ RqVP; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Instruction[WriteSingle, PRP, PBL, PWord]]]]; NewRq _ TRUE; SakuraRT.GetNew[ClockB, TRUE]; MWData _ RqData; SakuraRT.Delay[20]; SakuraRT.Put[CMDOut, NEW[BOOLEAN _ FALSE]]; SakuraRT.GetNew[ClockA, TRUE]; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Data[MWData]]]]; SakuraRT.GetNew[ClockB, TRUE]; SetMProcDone[TRUE]; NewRq _ FALSE; SetMProcReallyDone[TRUE]}; DoMapOp: PROC = { fault: BOOLEAN; MVP _ RqVP; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [MapCommand[DoMapOp, MapOp, , , MVP]]]]; MCMD _ TRUE; SakuraRT.GetNew[ClockB, TRUE]; MWData _ RqData; SakuraRT.Delay[20]; SakuraRT.Put[CMDOut, NEW[BOOLEAN _ FALSE]]; SakuraRT.GetNew[ClockA, TRUE]; SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Data[MWData]]]]; fault _ WaitMapOpDone[]; IF fault THEN SIGNAL PageFault; SetMProcDone[TRUE]; ReadDataFromBus[@MRdData]; DoMapOpTransportGo _ TRUE; SetMProcReallyDone[TRUE]}; -- DoMapOp WaitMapOpDone: PROC RETURNS [fault: BOOLEAN] = { DO SakuraRT.GetNew[ClockB, TRUE]; SakuraRT.Delay[30]; MCMD _ NARROW[SakuraRT.Get[CMDIn], REF BOOLEAN]^; [MInst, fault] _ DecodeMbusCommand[]; IF MCMD AND MInst = MapOpDone THEN EXIT ENDLOOP}; DecodeMbusCommand: PROC RETURNS [MInst: DragonCache.MbusCommand, fault: BOOLEAN] = { WITH b: NARROW[SakuraRT.Get[MDataIn], REF DragonCache.MbusType]^ SELECT FROM Instruction => {MInst _ b.command; MRP _ b.rp; MBL _ b.bl; MWord _ b.word; fault _ FALSE}; MapCommand => {MInst _ b.command; fault _ b.fault} ENDCASE => ERROR}; WaitOneCycle: PROC = { SakuraRT.GetNew[ClockB, TRUE]; NULL; SakuraRT.GetNew[ClockA, TRUE]; NULL}; ReadDataFromBus: PROC [data: POINTER TO LONG CARDINAL] = { WITH b: NARROW[SakuraRT.Get[MDataIn], REF DragonCache.MbusType]^ SELECT FROM Data => data^ _ b.data ENDCASE => ERROR}; ArbiterInterface: PROC = { arbiterHolding: BOOLEAN _ FALSE; {ENABLE {ABORTED => GO TO Aborted}; DO SakuraRT.GetNew[ClockA, TRUE]; NULL; SakuraRT.Delay[15]; IF NOT arbiterHolding AND (PRq OR MRq) THEN {arbiterHolding _ TRUE; SakuraRT.Put[Rq, NEW[BOOLEAN _ TRUE]]} ELSE IF arbiterHolding AND NOT PRq AND NOT MRq THEN {arbiterHolding _ FALSE; SakuraRT.Put[Rq, NEW[BOOLEAN _ FALSE]]} ENDLOOP; SakuraRT.ProcessEnd[]} EXITS Aborted => SakuraRT.Abort[]}; -- Back door operations BackDoor: PROC = { MInst: DragonCache.MbusCommand; {ENABLE {ABORTED => GO TO Aborted}; DO SakuraRT.GetNew[ClockB, TRUE]; NULL; MCMD _ NARROW[SakuraRT.Get[CMDIn], REF BOOLEAN]^; IF MCMD THEN {[MInst, ] _ DecodeMbusCommand[]; SELECT MInst FROM ReadQuad => BDReadQuad[]; WriteQuad => NULL; WriteSingle => BDWriteSingle[]; ReadMap => NULL; ReadMapAndSetRpDirty => BDReadMapAndSetRpDirty[]; SetRpDirty => BDSetRpDirty[]; DoMapOp => NULL ENDCASE} ENDLOOP; SakuraRT.ProcessEnd[]} EXITS Aborted => SakuraRT.Abort[]}; BDReadQuad: PROC = { -- Starts in B index: CARDINAL; success: BOOLEAN; ReadOneWord: PROC = { SakuraRT.GetNew[ClockB, TRUE]; IF success THEN MWData _ Data[index].D[MWord]; SakuraRT.GetNew[ClockA, TRUE]; {IF success THEN SakuraRT.Put[MDataOut, NEW[DragonCache.MbusType _ [Data[MWData]]]]; MWord _ (MWord + 1) MOD 4}}; SakuraRT.GetNew[ClockA, TRUE]; [success, index] _ FullRpMatch[MRP, MBL]; IF success THEN {Data[index].Shared _ TRUE; SakuraRT.Put[SharedOut, NEW[BOOLEAN _ TRUE]]}; SakuraRT.GetNew[ClockB, TRUE]; NULL; THROUGH [1..4] DO ReadOneWord[] ENDLOOP; SakuraRT.GetNew[ClockB, TRUE]; SakuraRT.Put[SharedOut, NEW[BOOLEAN _ FALSE]]}; -- BDReadQuad BDWriteSingle: PROC = { index: CARDINAL; success: BOOLEAN; SakuraRT.GetNew[ClockA, TRUE]; [success, index] _ FullRpMatch[MRP, MBL]; SakuraRT.Delay[30]; ReadDataFromBus[@MRdData]; -- (A) SakuraRT.GetNew[ClockB, TRUE]; IF success THEN Data[index].D[MWord] _ MRdData}; -- BDWriteSingle BDReadMapAndSetRpDirty: PROC = { index: CARDINAL; success: BOOLEAN; SakuraRT.GetNew[ClockA, TRUE]; [success, index] _ FullRpMatch[MRP, MBL]; SakuraRT.GetNew[ClockB, TRUE]; IF success THEN Data[index].RpDirty _ TRUE}; -- BDReadMapAndSetRpDirty BDSetRpDirty: PROC = { index: CARDINAL; success: BOOLEAN; SakuraRT.GetNew[ClockA, TRUE]; [success, index] _ FullRpMatch[MRP, MBL]; SakuraRT.GetNew[ClockB, TRUE]; IF success THEN Data[index].RpDirty _ TRUE}; -- BDSetRpDirty {ENABLE {ABORTED => GO TO Aborted}; SakuraRT.Put[Reject, NEW[BOOLEAN _ FALSE]]; SakuraRT.Put[SharedOut, NEW[BOOLEAN _ FALSE]]; SakuraRT.Put[CMDOut, NEW[BOOLEAN _ FALSE]]; FOR i: CARDINAL IN [0..DataArraySize) DO Data[i].VpValid _ Data[i].RpValid _ FALSE ENDLOOP; SakuraRT.GetNew[ClockA, TRUE]; NULL; {pbus, fetch, store, domapop, mproc, backdoor, arbinterface: PROCESS; SakuraRT.IncCurrent[];pbus _ FORK PbusFetch;SakuraRT.CatalogProcId[pbus]; SakuraRT.IncCurrent[];fetch _ FORK FetchTransport;SakuraRT.CatalogProcId[fetch]; SakuraRT.IncCurrent[];store _ FORK StoreTransport;SakuraRT.CatalogProcId[store]; SakuraRT.IncCurrent[]; domapop _ FORK DoMapOpTransport;SakuraRT.CatalogProcId[domapop]; SakuraRT.IncCurrent[];mproc _ FORK MProc;SakuraRT.CatalogProcId[mproc]; SakuraRT.IncCurrent[];backdoor _ FORK BackDoor;SakuraRT.CatalogProcId[backdoor]; SakuraRT.IncCurrent[]; arbinterface _ FORK ArbiterInterface;SakuraRT.CatalogProcId[arbinterface]; SakuraRT.DecCurrent[]; SakuraRT.Join[pbus]; SakuraRT.Join[fetch]; SakuraRT.Join[store]; SakuraRT.Join[domapop]; SakuraRT.Join[mproc]; SakuraRT.Join[backdoor]; SakuraRT.Join[arbinterface]; SakuraRT.IncCurrent[]}; SakuraRT.ProcessEnd[]} EXITS Aborted => SakuraRT.Abort[]}; -- Data array access procedures FullVpMatch: 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]}; FullRpMatch: PROC [rp: LONG CARDINAL, bl: CARDINAL] RETURNS [BOOLEAN, CARDINAL] = { FOR i: CARDINAL IN [0..DataArraySize) DO IF Data[i].RpValid AND Data[i].rp = rp 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 {RpDirtyReg _ Data[i].RpDirty; RETURN [TRUE, i]} ENDLOOP; RETURN [FALSE, 0]}; END.