<> <> <> <> <> <<>> <<>> <> 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: BOOL _ FALSE, resetRequested: BOOL _ TRUE, trapsEnabled: BOOL _ FALSE, version: [0..255] _ 0, stats: ProcessorStats _ [], lastCallRtn: INT _ 0, -- inst count of last call/return instBuffer: InstBuffer _ NIL, euCarry: BOOL _ FALSE, vmMap: VMMap _ NIL, regs: ARRAY ProcessorRegister OF TaggedWord _ ALL[TagZerosWord], regsGood: ARRAY ProcessorRegister OF BOOL _ ALL[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 ]; <> 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 [ <> 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: BOOL _ TRUE, -- 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, <> calls: INT _ 0, <> stackOver: INT _ 0, <> instBufferCycles: INT _ 0, <> lookaheadProbes: INT _ 0, <> lookaheadRejects: INT _ 0 <> ]; ChangeLogger: TYPE = REF ChangeLoggerRep; ChangeLoggerRep: TYPE = RECORD [ data: REF _ NIL, 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 { <> 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; <> EUWriteFault: TrapIndex = EUWriteFault; <> NoFault: TrapIndex = ALUCondFalse; <> NoTLBmiss: TrapIndex = ALUCondFalse; <> NewProcessor: PROC [logger: ChangeLogger] RETURNS [Processor]; InstructionExecute: PROC [processor: Processor]; FlushInstBuffer: PROC [processor: Processor]; <> <> 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: INTEGER _ LOOPHOLE[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: INTEGER _ LOOPHOLE[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]]]]; }; <<>> <> TrapPC: PUBLIC PROC [tx: TamarinOps.TrapIndex] RETURNS [Word] = INLINE { <> 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]; <> END.