-- BusSlave.sak
-- last edited by: Suzuki August 5, 1981 9:58 AM


BusSlave: DEVICE = {
IN
-- Memory bus
BusException: BOOLEAN, MemoryBus: MemoryBusType,
-- Master process
Next: BOOLEAN
-- TriMOS control
BusDone, Ready: BOOLEAN,
OUT
-- Memory bus
Advnace, Shared: BOOLEAN,
-- Master process
Done, Exception, Start, MapEnd, ValidData: BOOLEAN,
-- TriMOS control
Advnace: BOOLEAN
GUARDIAN
STATE
DATAFLOW
CONTROL
REPEAT {
Exception ← FALSE;
SELECT MemoryBus.Op FROM
Fetch => BusFetchSlave[];
Store => BusStoreSlave[];
SFetch => BusSFetchSlave[];
SetMapDirty => BusSetMapDirtySlave[];
InvalidateVp => BusInvalidateVpSlave[];
WriteMap => BusWriteMapSlave[];
ReadMap => BusReadMapSlave[];
WriteMapFlags => BusWriteMapFlagsSlave[];
ENDCASE};
};

--1) Bus Slave procedures

success: BOOLEAN;
loc: [0..CacheSize);

BusFetchSlave: PROC = {
Start ← TRUE;
SELECT {
WHEN Next UP -> -- Data is not on the cache. This cache is in control
SlaveFetch[] ||
WHEN Ready UP -> -- Some other cache is in control
{[success, loc] ← RpBMatch[MemoryBus.Arg];
IF success THEN {
Cache[loc].flags.shared ← TRUE;
Shared ← TRUE};
OneStep[];
IF success THEN BackDoorAccess[]
ELSE IdleSteps[]};
}
};

SlaveFetch: PROC = {
Advance ← TRUE;
WHEN BusDone UP: IF BusException THEN {Exception ← TRUE; RETURN};
THROUGH [0..1] DO
WHEN Ready UP: ValidData ← TRUE;
WHEN Next UP: Advnace ← TRUE;
ValidData ← FALSE;
WHEN BusDone UP: IF BusException THEN {Exception ← TRUE; RETURN};
ENDLOOP};

BackDoorAccess: PROC = {
i: CARDINAL;
FOR i IN [0..1] DO
MemoryBus.Data ← Cache[loc].data.long[i];
OneStep[];
ENDLOOP;
};

IdleStep: PROC = {
THROUGH [0..1] DO
OneStep[];
ENDLOOP};

BusStoreSlave: PROC = {
Start ← TRUE;
SELECT {
WHEN Next UP -> -- This cache is in control
{StoreInstruction[];
SlaveStore[]} ||
WHEN Ready UP -> -- some other cache is in control
{StoreInstruction[];
OneStep[];
IF success THEN BackDoorStore[]
ELSE SlaveIdleSteps[]}
}
};

StoreInstruction: PROC = {
SetRpDirty[];
[success, loc] ← RpBMatch[MemoryBus.Arg];
IF success THEN Cache[loc].flags.ceDirty ← FALSE};

SlaveIdleSteps: PROC = {
StepPhases[2];
WHEN BusDone UP: NULL};

BackDoorStore: PROC = {
i: CARDINAL;
FOR i IN [0..1] DO
Cache[loc].data.long[i] ← MemoryBus.Data;
OneStep[];
ENDLOOP};

SlaveStore: PROC = {
Advance ← TRUE;
WHEN BusDone UP: IF BusException THEN {Exception ← TRUE; RETURN};
Done ← TRUE;
THROUGH [0..1] DO
WHEN Next UP: Advnace ← TRUE;
WHEN BusDone UP: IF BusException THEN {Exception ← TRUE; RETURN};
Done ← TRUE;
ENDLOOP};

BusSFetchSlave: PROC = {
START ← TRUE;
SELECT {
WHEN Next UP -> -- This cache is in control
{SetRpDirty[];
SlaveFetch[];
IF Shared THEN SlaveStore[]} ||
WHEN Ready UP -> {
StoreInstruction[]; -- success is set by Match
OneStep[];
IF success THEN {BackDoorAccess[]; BackDoorStore[]}
ELSE IdleSteps[]}
}
};

BusInvalidateVpSlave: PROC = {
FOR loc IN [0..CacheSize) DO
AcquireArbiter[loc];
IF Cache[loc].rp = MemoryBus.Arg THEN
Cache[loc].flags.vaValid ← FALSE
ReleaseArbiter[loc];
ENDLOOP;
DataTaken ← TRUE};

BusReadMapSlave, BusWriteMapSlave, BusWriteMapFlagsSlave: PROC = {
MapPrologue[];
StepPhases[1]};

MapPrologue, BusSetMapDirtySlave: PROC = {
DataTaken ← TRUE;
DO
WHEN DataReady UP:
IF MemoryBus.flags.mapend THEN {
MapEnd ← TRUE;
DataTaken ← TRUE;
EXIT};
DataTaken ← TRUE;
StepPhases[2];
ENDLOOP};

StepPhases: PROC[num:CARDINAL] = {
THROUGH [1..num] DO
WHEN Ready UP: Advance ← TRUE;
ENDLOOP};

OneStep: PROC = {
Advance ← TRUE;
WHEN BusDone UP: NULL};