CacheOps.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Frailong, October 13, 1986 1:48:20 pm PDT
Description of cache operations from a Dragon processor.
DIRECTORY
DragonOpsIO;
CacheOps: CEDAR DEFINITIONS
IMPORTS DragonOpsIO
~ BEGIN
Principles
Each cache has a number of I/O registers that control either its internal functions or some extension of processor functions. Cache I/O registers are usually accessible from a processor in three different ways:
- Directed access: any cache may be accessed by specifying its DevNum (equal to it's DynaBus ID)
- Self access: a processor may access the registers of it's own EU cache directly
- Broadcast access: a processor may write a given register in all caches simultaneously
I/O operations reading a register are thus available in two flavors (directed and self), whereas writes are available in three flavors (directed, self and broadcast).
All functions in this package are actually inline IO instructions.
DevID: TYPE ~ DragonOpsIO.DevID;
IOAddress: TYPE ~ DragonOpsIO.IOAddress;
WORD: TYPE ~ DragonOpsIO.WORD;
DevNum: TYPE ~ [0 .. 1024); -- Identifies uniquely a cache - equal to its DevID
Interrupt management
The cache handles part of the interrupt management for the processor, coalescing multiple interrupt reasons into the single Reschedule line. The interrupt handling hardware exists both in the EU cache and in the IFU cache, but the Reschedule line of the Dragon processor is connected only to the Reschedule output of it's EU cache. Thus, the following functions are of really use only when directed to a EU cache.
The interrupt management hardware in the cache consists of two registers, InterruptStatus and InterruptMask, and some related hardware. The logical function is very simple:
- an interrupt reason is posted by setting a bit in InterruptStatus
- interrupts are visible when they are set and that the corresponding InterruptMask bit is set
- Reschedule to the processor is pulsed whenever an interrupt that was not visible before the operation becomes visible.
Interrupt status management
SetInterruptStatus: PROC [n: DevNum, itStatus: WORD] ~ INLINE {
DragonOpsIO.IOWrite[Addr[n, itStatusReg], itStatus];
};
OR itStatus into InterruptStatus for the specified Cache. Reschedule will be pulsed if new interrupts are posted.
pulseReschedule ← (itMask AND InterruptMask)#0
InterruptStatus ← InterruptStatus OR itStatus
SetInterruptStatusBroadcast: PROC [itStatus: WORD] ~ INLINE {
DragonOpsIO.BIOWrite[BroadcastAddr[itStatusReg], itStatus];
};
OR itStatus into InterruptStatus for all Caches. In each cache, pulse Reschedule if new interrupts are posted.
pulseReschedule ← (itMask AND InterruptMask)#0
InterruptStatus ← InterruptStatus OR itStatus
SetInterruptStatusSelf: PROC [itStatus: WORD] ~ INLINE {
DragonOpsIO.IOWrite[SelfAddr[itStatusReg], itStatus];
};
OR itStatus into InterruptStatus for the calling processor's EU Cache. Reschedule will be pulsed if new interrupts are posted.
pulseReschedule ← (itMask AND InterruptMask)#0
InterruptStatus ← InterruptStatus OR itStatus
ClearInterruptStatus: PROC [n: DevNum, clrMask: WORD] ~ INLINE {
DragonOpsIO.IOWrite[Addr[n, itClearReg], clrMask];
};
Remove clrMask from InterruptStatus for the specified Cache.
InterruptStatus ← InterruptStatus&~clrMask
ClearInterruptStatusBroadcast: PROC [clrMask: WORD] ~ INLINE {
DragonOpsIO.BIOWrite[BroadcastAddr[itClearReg], clrMask];
};
Remove clrMask from InterruptStatus for the all Caches.
InterruptStatus ← InterruptStatus&~clrMask
ClearInterruptStatusSelf: PROC [clrMask: WORD] ~ INLINE {
DragonOpsIO.IOWrite[SelfAddr[itClearReg], clrMask];
};
Remove clrMask from InterruptStatus for the calling processor's EU Cache.
InterruptStatus ← InterruptStatus&~clrMask
ReadInterruptStatus: PROC [n: DevNum] RETURNS [itStatus: WORD] ~ INLINE {
itStatus ← DragonOpsIO.IORead[Addr[n, itStatusReg]];
};
Return the current value of InterruptStatus for the specified Cache.
itStatus ← InterruptStatus
ReadInterruptStatusSelf: PROC RETURNS [itStatus: WORD] ~ INLINE {
itStatus ← DragonOpsIO.IORead[SelfAddr[itStatusReg]];
};
Return the current value of InterruptStatus for the calling processor's EU Cache.
itStatus ← InterruptStatus
Interrupt mask management
WriteInterruptMask: PROC [n: DevNum, itMask: WORD] ~ INLINE {
DragonOpsIO.IOWrite[Addr[n, itMaskReg], itMask];
};
Set InterruptMask for the specified Cache. If new interrupts become visible, Reschedule will be pulsed.
pulseReschedule ← (itMask AND ~InterruptMask AND InterruptStatus)#0
InterruptMask ← itMask
WriteInterruptMaskBroadcast: PROC [itMask: WORD] ~ INLINE {
DragonOpsIO.BIOWrite[BroadcastAddr[itMaskReg], itMask];
};
Set InterruptMask for all Caches. Each cache pulses Reschedule if new interrupts become visible.
pulseReschedule ← (itMask AND ~InterruptMask AND InterruptStatus)#0
InterruptStatus ← itMask
WriteInterruptMaskSelf: PROC [itMask: WORD] ~ INLINE {
DragonOpsIO.IOWrite[SelfAddr[itMaskReg], itMask];
};
Set InterruptMask for the calling processor's EU Cache. If new interrupts become visible, Reschedule will be pulsed.
pulseReschedule ← (itMask AND ~InterruptMask AND InterruptStatus)#0
InterruptStatus ← itMask
ReadInterruptMask: PROC [n: DevNum] RETURNS [itMask: WORD] ~ INLINE {
itMask ← DragonOpsIO.IORead[Addr[n, itMaskReg]];
};
Return the current value of InterruptMask for the specified Cache.
itMask ← InterruptMask
ReadInterruptMaskSelf: PROC RETURNS [itMask: WORD] ~ INLINE {
itMask ← DragonOpsIO.IORead[SelfAddr[itMaskReg]];
};
Return the current value of InterruptMask for the calling processor's EU Cache.
itMask ← InterruptMask
DynaBus ID management
The cache, as all DynaBus devices, has a DynaBus identifier used in all DynaBus transactions. This identifier is also used in IO operations to identify a specific cache, as a DevNum. The bootstrap mechanis initializes the device ID for the EU and IFU caches, and guarantees that the IFU cache ID will always be exactly one more than the EU cache ID. By convention, a Dragon processor (IFU+EU+caches) is identified in software by the ID of its EU cache. This ID may be read using ReadIDSelf, thus providing processor identification for the software.
ReadID: PROC [n: DevNum] RETURNS [devID: DevID] ~ INLINE {
devID ← DragonOpsIO.IORead[Addr[n, devIDReg]];
};
Return the DynaBus device ID for the specified Cache. This function is provided only for debugging purposes, since it should return devID=n if the cache has been correctly initialized during bootstrap phase.
devID ← DeviceID
ReadIDSelf: PROC RETURNS [devID: DevID] ~ INLINE {
devID ← DragonOpsIO.IORead[SelfAddr[devIDReg]];
};
Return the DynaBus device ID for the calling processor's EU Cache.
devID ← DeviceID
Address space management
Fault management
Reset management
Private information
This information is strictly private, and figures in this interface only because INLINEs should be inthe interface if you want them to have any effect...
Offset: TYPE ~ [0 .. 256); -- Offset of a register inside the cache
itStatusReg: Offset = 0; -- offset to InterruptStatus - May still change
itClearReg: Offset = 1; -- offset to InterruptStatus - May still change
itMaskReg: Offset = 2; -- offset to InterruptMask - May still change
devIDReg: Offset = 3; -- offset to InterruptMask - May still change
CacheBase: WORD = 0; -- Some value to be defined later
Addr: PROC [n: DevNum, offset: Offset] RETURNS [addr: IOAddress] ~ INLINE {
dev: WORD ← n;
addr.v ← CacheBase+1024*dev+offset;
};
BroadcastAddr: PROC [offset: Offset] RETURNS [addr: IOAddress] ~ INLINE {
broadcastDevNum: WORD = LAST [DevNum]; -- required by cache decoding mechanism
addr.v ← CacheBase+1024*broadcastDevNum+offset;
};
SelfAddr: PROC [offset: Offset] RETURNS [addr: IOAddress] ~ INLINE {
addr.v ← offset;
};
END.