-- File: [Indigo]<Sakura>Dragon>DragonCacheImpl.sak
-- Dragon Cache
-- 23-Mar-82 13:02:29
DIRECTORY
ConvertUnsafe: TYPE,
DragonCache: TYPE,
Inline: TYPE,
SakuraRT: TYPE,
SimIO: TYPE;
DragonCacheImpl1: 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 = "Proc2: ";
-- 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.