-- ProcessorInterface.sak -- last edited by Suzuki: August 5, 1981 10:24 AM CacheProcessor: MONITOR = { CacheSize: CARDINAL = 400B; DataSize: CARDINAL = 4; BusProtocol: TYPE = {Fetch, InvalidateVp, Noop, Store, SFetch, ReadMap, SetMapDirty, WriteMap, WriteMapFlags}; MemoryBusType: TYPE = RECORD[ body: SELECT OVERLAID * FROM Instruction => [Op: BusProtocol, Arg: [0..1777777777B]], Data => [Data: Word], Map => [Flags: MapFlags, Rp: [0..77777777B]], Exception => [ExceptionCode: Word] ENDCASE]; CacheIndex: TYPE = [0..CacheSize); CacheArray: TYPE = ARRAY CacheIndex OF RECORD [ data: RECORD [ body: SELECT OVERLAIN * FROM Short => [short: ARRAY [0..DataSize) OF Word], Long => [long: ARRAY [0..DataSize/2) OF LONG CARDINAL] ], vp: VirtualPage, b: PageOffset, rp: RealPage, flags: RECORD[ vaValid, raValid, ceDirty, shared, rpDirty: BOOLEAN]]; MapFlags: TYPE = MACHINE DEPENDENT RECORD [ reserved: [0..37B], protectd, dirty, referenced: BOOLEAN]; Instruction: TYPE = { Fetch1, Fetch2, Fetch4, Store1, Store2, Store4, Associate, SetF, GetF}; AddressType: TYPE = RECORD[ body: SELECT OVERLAID * FROM Fetch => [vp: VirtualPage, b: PageOffset, w: WordIndex], Store => [data: Word], SM => [mf: MapFlags, fill: [0..377B], rp: RealPage], SMF => [mf: MapFlags, vp: VirtualPage] ]; Word: TYPE = CARDINAL; VirtualPage: TYPE = [0..77777777B]; PageOffset: TYPE = [0..77B]; WordIndex: TYPE = [0..3]; RealPage: TYPE = [0..177777B]; ProcessorInterface: DEVICE = { IN -- From Processor Operation: Instruction, Hold, ReqFromProc: BOOLEAN, Address: AddressType, ProcParity, Tag: BOOLEAN, -- From Memory Bus AckFromBus, Shared, MemException: BOOLEAN, MemoryBus: MemoryBusType, -- From Slave Done, Exception, Start, MapEnd, ValidData: BOOLEAN OUT -- To Processor AckToProc: BOOLEAN, Address: AddressType, Data: DataType, CacheException, ProcParity, Tag: BOOLEAN, -- To Memory Bus ReqToBus, MemHold, Shared: BOOLEAN, MemoryBus: MemoryBusType, -- To slave Next: BOOLEAN GUARDIAN -- STATE Cache: CacheArray, held: BOOLEAN, entryLoc, victimLoc: CacheIndex DATA FLOW CONTROL { victimLoc _ 0; REPEAT { ENABLE ExceptionAbort => CONTINUE; WHEN ReqFromProc CHANGE: CacheException _ FALSE; SELECT Operation FROM Fetch1 -> Fetch1Proc[]; Fetch2 -> Fetch2Proc[]; Fetch4 -> Fetch4Proc[]; Store1 -> Store1Proc[]; Store2 -> Store2Proc[]; Store4 -> Store4Proc[]; Associate -> AssociateProc[]; SetF -> SetFProc[]; GetF -> GetFProc[] ENDCASE; held _ Hold; AckToProc _ NOT AckToProc}; }; --3) Processor Interface procedures Fetch1Proc: PROC = { OneWordAssign: PROC = { Address.data _ Cache[entryLoc].data.short[w]; ReleaseArbiter[entryLoc]}; FetchProc[OneWordAssign]}; Fetch2Proc: PROC = { TwoWordsAssign: PROC = { Address.data _ Cache[entryLoc].data.long[w/2]; ReleaseArbiter[entryLoc]}; FetchProc[TwoWordsAssign]}; Fetch4Proc: PROC = { FourWordsAssign: PROC = { Address.data _ Cache[entryLoc].data.long[0]; AckToProc _ NOT AckToProc; WHEN ReqFromProc CHANGE; Address.data _ Cache[entryLoc].data.long[1]; ReleaseArbiter[entryLoc]}; FetchProc[FourWordsAssign]}; FetchProc: PROC[WordsAssign: PROC] = { rp: RealPage; rpDirty, success: BOOLEAN; [vp: vp, b: b, w: w] _ Address; DO [success, entryLoc] _ VpBMatch[vp, b]; --This will acquire an arbiter at entryLoc IF success THEN GOTO CFinal; [success, rp, rpDirty] _ SelectVictimAndVpMatch[vp]; --This will acquire an arbiter at victimLoc IF success THEN Cache[entryLoc] _ [vp: vp, b: b, rp: rp, flags: [vaValid: TRUE, raValid: FALSE, ceDirty: FALSE, shared: FALSE, rpDirty: rpDirty]] ELSE { ReleaseArbiter[entryLoc]; [flags, rp] _ ReadMap[vp]; IF Vacant[flags] THEN GOTO PageFault; AcquireArbiter[entryLoc]; Cache[entryLoc] _ [vp: vp, b: b, rp: rp, flags: [vaValid: TRUE, raValid: FALSE, ceDirty: FALSE, shared: FALSE, rpDirty: flags.dirty]]}; ReleaseArbiter[entryLoc]; GetMasterCycle[]; -- If vp is valid then no map operations occurred in between IF Cache[entryLoc].flags.vaValid THEN GOTO Fetch; Abort[]; REPEAT Fetch => { MemoryBus _ [Op: Fetch, Arg: rp]; IF Hold THEN MemHold _ TRUE; BeginNewPhase[]; FetchFromBus[entryLoc]; WordsAssign[]; MemHold _ FALSE}; CFinal => { WordsAssign[]; Noop[]}; PageFault => { Address.exception _ PageFault; CacheException _ TRUE; Noop[]}; ENDLOOP}; VictimDirty: PROC RETURNS[BOOLEAN] = { RETURN[Cache[victimLoc].flags.vaValid AND Cache[victimLoc].flags.raValid AND Cache[victimLoc].flags.ceDirty]}; Vacant: PROC[flags: MapFlags] RETURN[BOOLEAN] = { RETURN[flags.protectd AND flags.dirty AND ~flags.referenced]}; Noop: PROC = { IF NOT held OR Hold THEN RETURN; GetMasterCycle[]; MemoryBus _ [Op: Noop, Arg: 0]; BeginNewPhase[]}; Store1Proc: = { OneWordStore: PROC[oldLevel:BOOLEAN] = { IF oldLevel=ReqFromProc THEN WHEN ReqFromProc CHANGE: NULL; Cache[entryLoc].data.short[w] _ Address.data}; StoreProc[OneWordStore]}; Store2Proc: = { TwoWordsStore: PROC[oldLevel:BOOLEAN] = { IF oldLevel=ReqFromProc THEN WHEN ReqFromProc CHANGE: NULL; Cache[entryLoc].data.long[w/2] _ Address.data}; StoreProc[TwoWordsStore]}; Store4Proc: = { FourWordsStore: PROC[oldLevel:BOOLEAN] = { IF oldLevel=ReqFromProc THEN WHEN ReqFromProc CHANGE: NULL; Cache[entryLoc].data.long[0] _ Address.data; AckToProc _ NOT AckToProc; WHEN ReqFromProc CHANGE: Cache[entryLoc].data.long[1] _ Address.data} StoreProc[FourWordsStore]}; StoreProc: PROC[WordsStore: PROC] = { rp: RealPage; oldLevel, rpDirty, success: BOOLEAN; [vp: vp, b: b, w: w] _ Address; oldLevel _ ReqFromProc; AckToProc _ NOT AckToProc; DO [success, entryLoc] _ VpBMatch[vp, b]; IF ~success THEN { [success, rp, rpDirty] _ SelectVictimAndVpMatch[vp]; --This will acquire an arbiter at victimLoc IF success THEN Cache[entryLoc] _ [vp: vp, b: b, rp: rp, flags: [vaValid: TRUE, raValid: FALSE, ceDirty: FALSE, shared: FALSE, rpDirty: rpDirty]] ELSE { ReleaseArbiter[entryLoc]; [flags, rp] _ ReadMap[vp]; IF Vacant[flags] THEN GOTO PageFault; IF flags.protected THEN GOTO WriteProtectFault; AcquireArbiter[entryLoc]; Cache[entryLoc] _ [vp: vp, b: b, rp: rp, flags: [vaValid: TRUE, raValid: FALSE, ceDirty: FALSE, shared: FALSE, rpDirty: flags.dirty]]}; ReleaseArbiter[entryLoc]; GetMasterCycle[]; -- Obtains the memory bus -- Checks the validity of vp IF Cache[entryLoc].flags.vaValid THEN GOTO SFetch; Abort[]; LOOP}; IF ~Cache[entryLoc].flags.rpDirty THEN { ReleaseArbiter[entryLoc]; GetMasterCycle[]; IF ~Cache[entryLoc].flags.vaValid THEN {HeldNoop[]; LOOP}; MemoryBus _ [Op: SetMapDirty, vp: vp]; IF held THEN MemHold _ TRUE; AcquireArbiter[entryLoc]; --AcquireArbiter must come before Next so that --vaValid will not be invalidated from the back door BeginNewPhase[]; MemHold _ FALSE}; IF ~Cache[entryLoc].flags.shared THEN GOTO CacheStore; ReleaseArbiter[entryLoc]; GetMasterCycle[]; IF Cache[entryLoc].flags.vaValid THEN GOTO Store; HeldNoop[]; REPEAT CacheStore => { Cache[entryLoc].rpDirty _ Cache[entryLoc].ceDirty _ TRUE; WordsStore[oldLevel]} Store => { WordsStore[oldLevel]; MemoryBus _ [Op: Store, Arg: vp]; IF Hold THEN MemHold _ TRUE; BeginNewPhase[]; StoreToBus[]; MemHold _ FALSE}; SFetch => SFetch[rp, oldLevel, WordsStore]; PageFault => { Address.exception _ PageFault; CacheException _ TRUE; Noop[]}; WriteProtectFault => { Address.exception _ WriteProtectFault; CacheException _ TRUE; Noop[]}; ENDLOOP; }; HeldNoop: PROC = { StartHeldInstruction[Op: Noop, Arg: 0]; MemHold _ FALSE}; Abort: PROC = { Cache[victimLoc].flags.vaValid _ FALSE; victimLoc _ (victimLoc - 1) MOD CacheSize; -- Send noop HeldNoop[]}; AssociateProc: PROC = { [vp: vp] _ Address; [mf: mf, rp: rp] _ Data; -- Invalidate Vp GetMasterCycle[]; MemoryBus _ [Op: SM, Arg: vp]; IF held THEN MemHold _ TRUE; BeginNewPhase[]; MemoryBus _ [Flag: mf, Rp: rp]; BeginNewPhase[]; MemHold _ FALSE}; GetFProc: PROC = { [vp: vp] _ Address; [mf, rp] _ ReadMap[vp]; Data _ [mf: mf, rp: rp]}; SetFProc: PROC = { [mf: newMf, vp: vp] _ Data; GetMasterCycle[]; MemoryBus _ [Op: SMF, Arg: vp]; IF held THEN MemHold _ TRUE; BeginNewPhase[]; MemoryBus _ [Flags: newMf]; BeginNewPhase[]; Address _ MemoryBus; MemHold _ FALSE};e6(635)\f9G448g18G1789g27G20g7G81g1G27g1G27g1G27g1G27g1G27g1G33g1G23g1G124g1G121g32G203g1G50g26G1g30G77g32G39g1G14g1G27g1G32g1G4g2G81g2G16g1G12g2G97g2G16g2G8g8G50g2G68g2G7g3G16g8G2g2G28g2G39g31G8g8G49g2G74g3G15g8G2g172G12g104G12g39G17g109G2g3G404g107G111g18G5g62G116g18G5g62G49g25G1g30G112g1G14g1G37g1G32g54G44g2G19g3G97g2G18g2G9g8G50g2G69g2G8g2G18g8G2g2G29g2G40g29G5g20G3g14G1g8G2g2G9g8G50g2G75g2G17g8G2g2G45g2G30g75G42g2G27g2G19g14G8g42G40g34G2g14G11g35G4g66G39g2G55g2G26g2G18g2G50g16G25g1G59g4G11g8G2g1G13g1G13g8G2g4G34g2G50g3G58g10G224g1G96g104G8g2G27g1G20g1G25g1G17g1G98g1G50g1G19g1G18g1G20g1G24g1G27g1G18g1G28g1G --4) Processor Interface to Bus Interface communication VictimStore: PROC = { Cache[victimLoc].flags.vaValid _ FALSE; Cache[victimLoc].flags.raValid _ FALSE; ReleaseArbiter[victimLoc]; GetMasterCycle[]; StartHeldInstruction[Op: Store, Arg: vp]; StoreToBus[]; MemHold _ FALSE; AcquireArbiter[victimLoc]}; SFetch: PROC [rp: RealPage, oldLevel: BOOLEAN, WordsStore: PROC] = { MemoryBus _ [Op: SFetch, Arg: rp]; IF Hold THEN MemHold _ TRUE; BeginNewPhase[]; FetchFromBus[entryLoc]; WordsStore[oldLevel]; WHEN Done UP: IF Shared THEN StoreToBus[]; MemHold _ FALSE}; ReadMap: PROC[vp: VirtualPage] RETURNS [mf: Flags, rp: RealPage] = { GetMasterCycle[]; MemoryBus _ [Op: ReadMap, Arg: vp]; IF held THEN MemHold _ TRUE; BeginNewPhase[]; WHEN MapEnd UP: MemHold _ FALSE; WHEN ValidData UP: { MemoryBusSuccess _ TRUE; [mf: MapFlags, rp: MapRp] _ MemoryBus; BeginNewPhase[]; RETURN[MapFlags, MapRp]}};e6\f9G57g1G21g1G59g5G45g1G125g1G167g8G2g24G63g1G68g1G275g --2) Bus Master procedures GetMasterCycle: PROC = { AcquireBus[]; WHEN Start UP: NULL}; StartHeldInstruction: PROC[Op: BusProtocol, Arg: [0..1777777777B]] = { MemoryBus _ [Op: Op, Arg: Arg]; IF held THEN MemHold _ TRUE; BeginNewPhase[]}; BeginNewPhase: PROC = { Next _ TRUE; WHEN Done UP: Next _ FALSE; IF Exception THEN {Noop[]; CacheException_ TRUE; SIGNAL ExceptionAbort}}; FetchFromBus: PROC[loc: CacheIndex] RETURNS[word: Word] = { WHEN ValidData UP: Cache[loc].data.long[0] _ MemoryBus.Data; BeginNewPhase[]; WHEN ValidData UP: Cache[loc].data.long[1] _ MemoryBus.Data; BeginNewPhase[]}; StoreToBus: PROC = { MemoryBus.Data _ Cache[loc].data[0]; BeginNewPhase[]; MemoryBus.Data _ Cache[loc].data[1]; BeginNewPhase[]}; -- Cache operations SelectVictimAndVpMatch: PROC[vp: VirtualPage] RETURNS[success: BOOLEAN, rp: RealPage, rpDirty: BOOLEAN] = { victimLoc _ (victimLoc + 1) MOD CacheSize; AcquireArbiter[victimLoc]; entryLoc _ victimLoc; IF VictimDirty[] THEN VictimStore[]; [success, rp, rpDirty] _ VpMatch[vp]}; }.\f9G28g1G51g3G232g71G63g1G161g1G20g1G37g1G17g1G37g1G222g20G2g2G36g2G36g4G