MonkeyHeart.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Pilfered by Ross January 28, 1987 11:57:47 am PST
Originally by Russ Atkinson (RRA) September 16, 1986 6:25:55 am PDT
Last Edited by: Ross February 3, 1987 3:56:39 pm PST
Interface for Basic Tamarin machine. Borrowed heavily from LizardHeart.mesa
(notice even the name similarities).
DIRECTORY
TamarinOps,
TamarinOpsUtils,
Rope USING [ROPE];
MonkeyHeart: CEDAR DEFINITIONS
IMPORTS TamarinOpsUtils
= BEGIN OPEN TamarinOps, TamarinOpsUtils;
Processor: TYPE = REF ProcessorRep; -- eventually something else
ProcessorRep: TYPE = RECORD [
logger: ChangeLogger ← NIL,
ccResult: BOOLFALSE,
resetRequested: BOOLTRUE,
trapsEnabled: BOOLFALSE,
version: [0..255] ← 0,
stats: ProcessorStats ← [],
lastCallRtn: INT ← 0, -- inst count of last call/return
instBuffer: InstBuffer ← NIL,
euCarry: BOOLFALSE,
vmMap: VMMap ← NIL,
regs: ARRAY ProcessorRegister OF TaggedWord ← ALL[TagZerosWord],
regsGood: ARRAY ProcessorRegister OF BOOLALL[FALSE],
mi: MicroCode ← NIL,
nextuPCa: NAT ← 0,
nextuPCb: NAT ← 0,
memory: Memory ← NIL,
memState: {deadCycle, ifStarted, dfStarted, blockdfStarted}
];
Memory: TYPE = REF MemoryRep;
MemoryRep: TYPE = RECORD [
fetch: MemFetchProc ← NIL,
write: MemWriteProc ← NIL];
MemFetchProc: TYPE =
PROC [processor: Processor, addr: Word, old,new: Word]
RETURNS [word: Word, tx: TrapIndex, rCycles: NAT];
MemWriteProc: TYPE =
PROC [data: REF, processor: Processor, addr: Word, old,new: Word]
RETURNS [word: Word, tx: TrapIndex, rCycles: NAT];
microCodeWidth: NAT = 109;
microCodeHeight: NAT = 512;
MicroCode: TYPE = REF MicroCodeRep;
MicroCodeRep: TYPE = ARRAY [0..512) OF MicroInstruction;
MicroInstruction: TYPE = MACHINE DEPENDENT RECORD [
readCxt (0: 15..15): BOOL,  -- 1 bit
writeCxt (0: 14..14): BOOL, -- 1 bit
newTopCxt (0: 13..13): BOOL, -- 1 bit
newBotCxt (0: 12..12): BOOL, -- 1 bit
altCxt (0: 9..11): [0..8),  -- 3 bits
memOp( 0: 3..8): [0..64),  -- 6 bits
tag (0: 0..2): [0..4),  -- 2 bits
euOp (1: 9..15): [0..128),  -- 7 bits
rd1Addr (1: 6..8): [0..8),  -- 3 bits
rd2Addr (1: 3..5): [0..8),  -- 3 bits
w2Addr (1: 0..2): [0..8),  -- 3 bits
dswap (2: 15..15): BOOL,  -- 1 bit
rAddr (2: 12..14): [0..8),  -- 3 bits
waddr (2: 9..11): [0..8),  -- 3 bits
newarg (2: 7..8): [0..4),  -- 2 bits
newarg2 (2: 5..6): [0..4),  -- 2 bits
newtos (2: 3..4): [0..4),  -- 2 bits
muxread (2: 0..2): [0..8),  -- 3 bits
muxwrite (3: 12..15): [0..16), -- 4 bits
tosPrime (3: 11..11): BOOL, -- 1 bit
argPrime (3: 10..10): BOOL, -- 1 bit
arg2Prime (3: 9..9): BOOL,  -- 1 bit
k (3: 0..8): [0..512),  -- 9 bits
invertCCode (4: 15..15): BOOL, -- 1 bit
dpCCode (4: 8..14): [0..128), -- 7 bits
muxCCode (4: 1..7): [0..32), -- 5 bits only
updatePC (4: 0..0): BOOL,  -- 1 bit
resultCCode (5: 11..15): [0..32), -- 5 bits
memCCode (5: 9..10): [0..4), -- 2 bits
writeOnTrue (5: 8..8): BOOL, -- 1 bit
nextInstA (5: 0..7): [0..256), -- 8 bits
nextInstB (6: 8..15): [0..256), -- 8 bits
misc (6: 3..7): [0..32),  -- 5 bits
opLength (6: 0..2): [0..8)  -- 3 bits
];
Position and Length of all MicroCodeWords:
readCxtPos: INT = 108; readCxtLen: INT = 1;
writeCxtPos: INT = 107; writeCxtLen: INT = 1;
newTopCxtPos: INT = 106; newTopCxtLen: INT = 1;
newBotCxtPos: INT = 105; newBotCxtLen: INT = 1;
altCxtPos: INT = 102; altCxtLen: INT = 3;
memOpPos: INT = 96; memOpLen: INT = 6;
tagPos: INT = 94;  tagLen: INT = 2;
euOpPos: INT = 87;  euOpLen: INT = 7;
rd1AddrPos: INT = 84; rd1AddrLen: INT = 3;
rd2AddrPos: INT = 81; rd2AddrLen: INT = 3;
w2AddrPos: INT = 78; w2AddrLen: INT = 3;
dswapPos: INT = 77;  dswapLen: INT = 1;
rAddrPos: INT = 74;  rAddrLen: INT = 3;
waddrPos: INT = 71;  waddrLen: INT = 3;
newargPos: INT = 69; newargLen: INT = 2;
newarg2Pos: INT = 67; newarg2Len: INT = 2;
newtosPos: INT = 65; newtosLen: INT = 2;
muxreadPos: INT = 62; muxreadLen: INT = 3;
muxwritePos: INT = 58; muxwriteLen: INT = 4;
tosPrimePos: INT = 57; tosPrimeLen: INT = 1;
argPrimePos: INT = 56; argPrimeLen: INT = 1;
arg2PrimePos: INT = 55; arg2PrimeLen: INT = 1;
kPos: INT = 49;  kLen: INT = 9;
invertCCodePos: INT = 45; invertCCodeLen: INT = 1;
dpCCodePos: INT = 38; dpCCodeLen: INT = 7;
muxCCodePos: INT = 33; muxCCodeLen: INT = 5;
updatePCPos: INT = 32; updatePCLen: INT = 1;
resultCCodePos: INT = 27; resultCCodeLen: INT = 5;
memCCodePos: INT = 25; memCCodeLen: INT = 2;
writeOnTruePos: INT = 24; writeOnTrueLen: INT = 1;
nextInstAPos: INT = 16; nextInstALen: INT = 8;
nextInstBPos: INT = 8; nextInstBLen: INT = 8;
miscPos: INT = 3;  miscLen: INT = 5;
opLengthPos: INT = 0; opLengthLen: INT = 3;
VMMap: TYPE = REF VMMapRep;
VMMapRep: TYPE = RECORD [
entryValid: BOOL,
virtualPage: Word,
physPage: Word,
pageFault: BOOL,
pageDirty: BOOL];
CondCode: TYPE = PACKED ARRAY [0..3) OF BOOL;
InstBuffer: TYPE = REF InstBufferRep;
InstBufferRep: TYPE = RECORD [
Circular buffer used to hold instructions for decoding.
basePC: Word ← ZerosWord, -- index of PC corresponding to startValid
nextPC: Word ← ZerosWord, -- next PC in straightline code
validWords: IBufWordIndex ← 0, -- # of valid words in buffer
bytesDiscarded: INT ← 0,
forcedEmpty: INT ← 0, -- # of times forced empty
refillAtPriority: BOOLTRUE, -- flag for setting refill priority
words: SEQUENCE max: NAT OF Word
];
IBufWordIndex: TYPE = [0..NumIBufWords);
NumIBufWords: NAT = 4;
IBufIndex: TYPE = [0..NumIBufWords*bytesPerWord);
ProcessorStats: TYPE = RECORD [
instructions: INT ← 0,
cycles: INT ← 0,
euFetches: INT ← 0,
euStores: INT ← 0,
instBytes: INT ← 0,
jumps: INT ← 0,
Number of unconditional jump instructions
calls: INT ← 0,
Number of call instructions
stackOver: INT ← 0,
Stack overflows
instBufferCycles: INT ← 0,
Cycles spent waiting for instructions
lookaheadProbes: INT ← 0,
Cache fetches due to instruction buffer lookahead
lookaheadRejects: INT ← 0
Reject cycles due to instruction buffer lookahead
];
ChangeLogger: TYPE = REF ChangeLoggerRep;
ChangeLoggerRep: TYPE = RECORD [
data: REFNIL,
regChange: RegChangeProc ← NIL,
memChange: MemChangeProc ← NIL,
ioChange: IOChangeProc ← NIL,
instStart: InstStartProc ← NIL,
instDone: InstDoneProc ← NIL
];
RegChangeProc: TYPE =
PROC [data: REF, processor: Processor, reg: ProcessorRegister, old,new: Word];
MemChangeProc: TYPE =
PROC [data: REF, processor: Processor, addr: Word, old,new: Word];
IOChangeProc: TYPE =
PROC [data: REF, processor: Processor, addr: Word, old,new: Word];
InstStartProc: TYPE =
PROC [data: REF, processor: Processor, thisPC: Word, inst: Inst, rest: Word];
InstDoneProc: TYPE =
PROC [data: REF, processor: Processor, newPC, rtnPC: Word, control: Control, cycles: INT];
Control: TYPE = {nextOpcode, nextuInst, doCall, doReturn, doAbort};
ALUOps: TYPE = MACHINE DEPENDENT {
Copied from /Indigo/Dragon/Rosemary/Dragon.mesa
SAdd(0), SSub(1), UAdd(2), USub(3), VAdd(4), VSub(5), LAdd(6), LSub(7), FOP(8), FOPK(9), And(10), Or(11), Xor(12), BndChk(13), Reserve14(14), Reserve15(15), Reserve16(16), Reserve17(17), Reserve18(18), Reserve19(19), Reserve20(20), Reserve21(21), Reserve22(22), Reserve23(23), Reserve24(24), Reserve25(25), Reserve26(26), Reserve27(27), Reserve28(28), Reserve29(29), Reserve30(30), Reserve31(31)};
EUPageFault: TrapIndex = EUPageFault;
Used to indicate page fault from cache, even for IFU fetches.
EUWriteFault: TrapIndex = EUWriteFault;
Used to indicate write protect fault from EU cache.
NoFault: TrapIndex = ALUCondFalse;
Any unused code will do. But we need a state to indicate that everything is OK.
NoTLBmiss: TrapIndex = ALUCondFalse;
Any unused code will do. But we need a state to indicate that everything is OK.
NewProcessor: PROC [logger: ChangeLogger] RETURNS [Processor];
InstructionExecute: PROC [processor: Processor];
FlushInstBuffer: PROC [processor: Processor];
This routine flushes the instruction buffer. This occurs on a bad jump prediction, a trap, or an xop.
INLINE routines for picking apart various pieces of the input
Signs: TYPE = MACHINE DEPENDENT {
a0b0c0 (0), a0b0c1 (1), a0b1c0 (2), a0b1c1 (3),
a1b0c0 (4), a1b0c1 (5), a1b1c0 (6), a1b1c1 (7)};
ALUHelper: PROC [a,b,c: BOOL] RETURNS [Signs] = INLINE {
RETURN [LOOPHOLE[
4*LOOPHOLE[a, CARDINAL] + 2*LOOPHOLE[b, CARDINAL] + LOOPHOLE[c, CARDINAL]]];
};
InstBytes: PROC [inst: Inst] RETURNS [bytes: [1..5]] = INLINE {
SELECT LOOPHOLE[inst, CARDINAL] FROM
< 40B => bytes ← 1;
< 100B => bytes ← 5;
ENDCASE => bytes ← LOOPHOLE[inst, CARDINAL] / 64;
};
RegPlus: PROC [reg: ProcessorRegister, delta: INTEGER] RETURNS [ProcessorRegister] = INLINE {
RETURN [LOOPHOLE[(LOOPHOLE[reg, CARDINAL] + LOOPHOLE[delta, CARDINAL]) MOD 256]];
};
StackPlus: PROC
[reg: ProcessorRegister, delta: INTEGER] RETURNS [ProcessorRegister] = INLINE {
RETURN [LOOPHOLE[(LOOPHOLE[reg, CARDINAL] + LOOPHOLE[delta, CARDINAL]) MOD 128]];
};
AlphaZ: PROC [rest: Word] RETURNS [CARDINAL] = INLINE {
RETURN [LOOPHOLE[WordToBytes[rest][3]]];
};
AlphaBetaZ: PROC [rest: Word] RETURNS [CARDINAL] = INLINE {
RETURN [LOOPHOLE[WordToHalves[rest][1]]];
};
AlphaS: PROC [rest: Word] RETURNS [INTEGER] = INLINE {
i: INTEGERLOOPHOLE[WordToBytes[rest][3], CARDINAL];
RETURN [IF i > 127 THEN i ← i - 256 ELSE i];
};
AlphaBetaS: PROC [rest: Word] RETURNS [INTEGER] = INLINE {
RETURN [LOOPHOLE[WordToHalves[rest][1]]];
};
BetaZ: PROC [rest: Word] RETURNS [CARDINAL] = INLINE {
RETURN [LOOPHOLE[WordToBytes[rest][2]]];
};
BetaS: PROC [rest: Word] RETURNS [INTEGER] = INLINE {
i: INTEGERLOOPHOLE[WordToBytes[rest][2], CARDINAL];
RETURN [IF i > 127 THEN i ← i - 256 ELSE i];
};
WordToReg: PROC [word: Word] RETURNS [ProcessorRegister] = INLINE {
RETURN [LOOPHOLE[WordToBytes[word][3]]];
};
RegToWord: PROC [reg: ProcessorRegister] RETURNS [Word] = INLINE {
RETURN [HalvesToWord[[LOOPHOLE[0], LOOPHOLE[reg]]]];
};
Utility Routines for manipulating data (incomplete)
TrapPC: PUBLIC PROC [tx: TamarinOps.TrapIndex] RETURNS [Word] = INLINE {
Turns a trap index into a byte PC. This is a full routine to keep from making the compiler unhappy with excessive INLINEs.
RETURN [CardToWord[TamarinOpsUtils.TrapIndexToBytePC[tx]]];
};
DoALUOp: PUBLIC PROC
[processor: Processor, wordA,wordB: Word, op: ALUOps, trap: TrapIndex]
RETURNS
[res: Word, resCode: TrapIndex ← NoFault];
FieldUnit: PUBLIC PROC [Left,Right: Word, fd: FieldDescriptor] RETURNS [out: Word];
WillPushOverflow: PUBLIC PROC [processor: Processor] RETURNS [BOOL];
... returns TRUE if the next push will overflow the IFU stack. Signals OutsideEnvelope in illegal cases.
OutsideEnvelope: PUBLIC SIGNAL [explanation: Rope.ROPE];
The program has been caught red-handed doing something that no reasonable Tamarin program should do; something for which the hardware response needn't be defined.
END.