SoftcardOps:
CEDAR
DEFINITIONS
= BEGIN OPEN Rapunzel: RapunzelP2200V2;
ROPE: TYPE = Rope.ROPE;
Addr: TYPE = CARD32;
SeqShort: TYPE = Rapunzel.SeqShort;
SeqLong:
TYPE =
REF SeqLongObject;
SeqLongObject:
TYPE ~
MACHINE
DEPENDENT
RECORD [
body: PACKED SEQUENCE length: CARD16 OF CARD32
];
EUInternal:
TYPE =
MACHINE
DEPENDENT {
left(0), right (1), -- operands for ALU and field unit
st2A (2), st2B (3), st3A (4), -- pipeline for the data to be sent to Cache (store)
kReg (5), -- a collection of control bits sent by the IFU
field (6), -- the field descriptor
r2B (7), r3A (8), r3B (9), -- pipeline for the output of the ALU
dataIn (10) -- data back from the Cache
};
All registers are 32-bits; all except kReg & field are interpreted as 32-bit values
FieldDesc:
TYPE =
MACHINE
DEPENDENT
RECORD[
insert (0: 0..0): [0..1],
mask (0: 1..6): [0..37B],
shift (0: 7..12): [0..77B],
reserved (0: 13..15): [0..7B] ← 0,
reserved1 (1: 0..15): [0..177777B] ← 0
];
KReg:
TYPE =
MACHINE
DEPENDENT
RECORD[
aAddr (0: 0..7): [0..377B], -- A address for the register file (left read port)
bAddr (0: 8..15): [0..377B], -- B address for the register file (right read port)
cAddr (1: 0..7): [0..377B], -- C address for the register file (write port)
leftSrc (1: 8..9): [0..3B], -- source for the `left' register (2 bits)
rightSrc (1: 10..12): [0..7B], -- source for the `right' register (3 bits)
st2ASrc (1: 13..14): [0..3B], -- source for the `st2A' register (2 bits)
st3ASrc (1: 15..15): [0..1] -- source for the `st3A' register (1 bit)
];
EURegister:
TYPE =
RECORD[
val:
SELECT tag: *
FROM
regular => [rVal: CARD32],
kReg => [kVal: KReg],
field => [fVal: FieldDesc],
ENDCASE
];
EUPBusCmd:
TYPE =
MACHINE
DEPENDENT
RECORD[
-- tbd
unused (0: 0..6): [0..177B] ← 0,
userMode (0: 7..7): BOOL ← FALSE,
unspecifiedAsYet (0: 8..15): [0..377B] ← 0
];
IFUPBusCmd: TYPE = MACHINE DEPENDENT {noAccess (0), access (1)};
numIFUBits: CARD16 = 30 * 16; -- for debugging at the moment
IFUInternalState: TYPE = PACKED ARRAY [0..numIFUBits) OF [0..1];
EstablishConnection: PROC[host: ROPE] RETURNS[ok: BOOL];
CloseConnection: PROC;
SCError: SIGNAL[code: ATOM, explanation: ROPE ← NIL];
SetEUBrkPtAddr: PROC[addr: Addr]; -- EU will brkpt when this address is accessed
SetIFUBrkPtAddr: PROC[addr: Addr]; -- IFU will brkpt when this address is accessed
ReadEUCmd: PROC RETURNS[euPBusCmd: EUPBusCmd];
ReadIFUCmd: PROC RETURNS[ifuPBusCmd: IFUPBusCmd];
ReadEUPBusData: PROC RETURNS[value: CARD32];
ReadIFUPBusData: PROC RETURNS[value: CARD32];
ReadClock: PROC RETURNS[value: CARD32];
*************************
ReadShort: PROC[addr: Addr] RETURNS[val: CARD16];
ReadLong:
PROC[addr: Addr]
RETURNS[value:
CARD32];
raises an error if addr is odd
WriteShort: PROC[addr: Addr, value: CARD16];
WriteLong:
PROC[addr: Addr, value:
CARD32];
raises an error if addr is odd
DumpShort: PROC[addr: Addr, num: CARD16] RETURNS[SeqShort];
DumpLong:
PROC[addr: Addr, num:
CARD16]
RETURNS[SeqLong];
raises an error if addr is odd
*************************
Control and status bits.
NOTE: virtualMemAccessXX:
if TRUE, the XX accesses to Dragon memory are using virtual addresses; if FALSE, physical addresses are being used
ControlBit:
TYPE = {
resetDragon,
interruptDragonToIOP,
interruptDragonToMesa,
dragonRun,
dragonStep,
writeParity,
allows selection of even or odd parity for subsequent writes; reads are always done with TDB parity; thus one can create a parity error
virtualMemAccessIOP,
virtualMemAccessMesa,
virtualMemAccessIFU,
virtualMemAccessEU,
resetIFUCacheStateMachine,
notResetIFUCache,
ifuBreakpointEnabled,
resetEUCacheStateMachine,
notResetEUCache,
euBreakpointEnabled,
iopIntToDragon,
mesaIntToDragon,
notResetClock
};
DragonPhase:
TYPE =
MACHINE
DEPENDENT
{ phaseB(0), betweenBandA(1), phaseA(2), betweenAandB(3)};
Notation: Fx/Fy => between Fx and Fy
DragonStepSize:
TYPE =
MACHINE
DEPENDENT {quarter(1), half(2), full(4)};
ReadControlBit: PROC[which: ControlBit] RETURNS[current: BOOL];
SetControlBit: PROC[which: ControlBit] RETURNS[previous: BOOL];
ResetControlBit: PROC[which: ControlBit] RETURNS[previous: BOOL];
ResetIFUCacheStateMachine: PROC;
ResetEUCacheStateMachine: PROC;
DisableIFUCache:
PROC;
enable by doing a FlushIFUCache
DisableEUCache:
PROC;
enable by doing a FlushEUCache
FlushIFUCache: PROC;
FlushEUCache: PROC;
DragonHaltInPhase:
PROC[phase: DragonPhase ← phaseA];
halt the dragon in the specified phase; if already halted, moves the Dragon to the specified phase
DragonStep:
PROC[size: DragonStepSize ← half]
RETURNS[ok:
BOOL];
returns FALSE if the dragon is running, mkaing a specified step difficult
DragonRun:
PROC;
no-op if Dragon is already running
DragonStop:
PROC;
no-op if Dragon is already stopped
ResetBoard:
PROC;
resets the entire dragon state on the softcard board
CurrentDragonPhase:
PROC
RETURNS[phase: DragonPhase, ok:
BOOL];
returns ok = FALSE if dragon is running
StatusBit:
TYPE = {
dOutIFU,
dOutEU,
phaseA,
The following status bits can be read & reset
periodicIntToDragon, -- 16HZ periodic interrupt
notMemoryError, -- IOP access to Dragon memory caused a parity error
euBkptReached,
ifuBkptReached,
mapError
};
ReadStatusBit: PROC[which: StatusBit] RETURNS[current: BOOL];
ResetStatusBit: PROC[which: StatusBit] RETURNS[previous: BOOL];
*************************
Mapping between 2 megabytes of Daybreak physical address space and Dragon memory
MesaMapEntry:
TYPE =
MACHINE
DEPENDENT
RECORD[
unused (0: 0..11): [0..3777B] ← 0,
dp (0: 12..14): [0..7B] ← 0,
ignored (0: 15..15): [0..1] ← 0
];
MesaMapIndex: TYPE = [0..3];
ReadMesaMap: PROC[index: MesaMapIndex] RETURNS[value: MesaMapEntry];
WriteMesaMap: PROC[index: MesaMapIndex, value: MesaMapEntry];
*************************
Access to the Dragon Map
DragonMapEntry:
TYPE =
MACHINE
DEPENDENT
RECORD[
fault (0: 0..0): BOOL ← TRUE,
unused (0: 1..5): [0..37B] ← 0,
rp (0: 6..15): [0..1777B] ← 0
];
DragonMapIndex: TYPE = [0..37777B];
ReadDragonMap: PROC[index: DragonMapIndex] RETURNS[value: DragonMapEntry];
WriteDragonMap: PROC[index: DragonMapIndex, value: DragonMapEntry];
END.