<> <> <> <> <> <<>> <<>> <> DIRECTORY Basics USING [BITAND], TamarinOps USING [Byte, bytesPerWord, FieldDescriptor, FourBytes, Inst, OnesWord, ProcessorRegister, TrapIndex, Word, ZerosWord], TamarinOpsUtils USING [BytePCToWordAddress, ByteToCard, BytesToHalf, BytesToWord, CardToWord, CardToByte, DoubleWordShiftLeft, TamAnd, TamNot, TamOr, TamXor, HalfToCard, IntToWord, SingleWordShiftLeft, SingleWordShiftRight, TrapIndexToBytePC, VanillaAdd, VanillaSub, WordAddressToBytePC, WordToBytes, WordToCard, WordToInt], MonkeyHeart USING [ALUHelper, ALUOps, ChangeLogger, Control, InstBuffer, InstBufferRep, MicroInstruction, NoFault, NoTLBmiss, Processor, ProcessorRep, TrapPC], <> PrincOpsUtils USING [LongCopy], Rope USING [ROPE]; MonkeyHeartImpl: CEDAR PROGRAM IMPORTS Basics, TamarinOpsUtils, MonkeyHeart, PrincOpsUtils EXPORTS MonkeyHeart = BEGIN OPEN TamarinOps, TamarinOpsUtils, MonkeyHeart; CurrentProcVersion: [0..255] _ 0; <> InstBufferIndex: TYPE = [0..64); <> WordsInBuffer: NAT _ 4; <<# of Tamarin words in the instruction buffer (power of two)>> MaxMask: CARDINAL _ WordsInBuffer*bytesPerWord - 1; <> MaskInstBufferIndex: PROC [index: CARDINAL] RETURNS [InstBufferIndex] = INLINE { RETURN [LOOPHOLE[Basics.BITAND[index, MaxMask]]]; }; NewProcessor: PUBLIC PROC [logger: ChangeLogger] RETURNS [p: Processor] = { p _ NEW[ProcessorRep]; p.logger _ logger; InitProcessor[p]; }; InitProcessor: PROC [p: Processor] = { <> p.trapsEnabled _ FALSE; p.resetRequested _ FALSE; p.ccResult _ FALSE; p.instBuffer _ NEW[InstBufferRep[WordsInBuffer]]; p.version _ CurrentProcVersion; p.stats _ []; }; FlushInstBuffer: PUBLIC PROC [processor: Processor] = { <> instBuffer: InstBuffer = processor.instBuffer; delta: INT = WordToInt[instBuffer.nextPC] - WordToInt[instBuffer.basePC]; IF delta > 0 THEN { validBytes: INT = instBuffer.validWords*bytesPerWord; IF validBytes > delta THEN instBuffer.bytesDiscarded _ instBuffer.bytesDiscarded + validBytes-delta; }; instBuffer.validWords _ 0; instBuffer.forcedEmpty _ instBuffer.forcedEmpty + 1; }; InstructionFetch: PUBLIC PROC [control: Control, processor: Processor] RETURNS [inst: Inst, rest: Word] = { thisPC: Word _ processor.regs[nextPC].data; newPC: Word _ thisPC; rtnPC: Word; p: Processor = processor; -- for a short name cycles: CARDINAL _ 0; rCycles: CARDINAL _ 0; initCycles: INT _ processor.stats.cycles; nBytes: CARDINAL _ 0; instBuffer: InstBuffer _ p.instBuffer; instBufferPtr: LONG POINTER; max: CARDINAL = instBuffer.max * bytesPerWord; -- max bytes in buffer word: Word; wordAddr: Word; valid: InstBufferIndex _ 0; -- valid bytes in inst buffer AFTER newPC rbi: [0..bytesPerWord); tx: TrapIndex _ NoFault; CauseTrap: PROC [code: TrapIndex] = { <> <> <<-- **** Should add section for Stack UnderFlow (i.e., not present in machine)>> rtnPC _ thisPC; <> <> <> newPC _ TrapPC[code]; control _ doAbort; cycles _ cycles + 4; -- a rough guess tx _ code; IF code = StackOverflowTrap THEN p.stats.stackOver _ p.stats.stackOver + 1; }; ForceBufferEmpty: PROC = INLINE { <> instBuffer.validWords _ 0; instBuffer.forcedEmpty _ instBuffer.forcedEmpty + 1; IF valid # 0 THEN { instBuffer.bytesDiscarded _ instBuffer.bytesDiscarded + valid; valid _ 0; }; }; FlushInstWord: PROC = INLINE { <> vw: CARDINAL _ instBuffer.validWords - 1; instBuffer.basePC _ IntToWord[WordToInt[instBuffer.basePC] + bytesPerWord]; instBuffer.validWords _ instBuffer.validWords - 1; IF vw # 0 THEN TRUSTED { PrincOpsUtils.LongCopy[from: @instBuffer[1], nwords: instBuffer.validWords*SIZE[Word], to: @instBuffer[0]]; }; instBuffer.validWords _ vw; }; <<-- ** Start of Instruction Fetch (only trap which is a uInst trap is reset). All other traps>> <> IF p.resetRequested THEN { <> thisPC _ newPC _ TrapPC[ResetTrap]; InitProcessor[p]; ForceBufferEmpty[]; p.instBuffer.forcedEmpty _ instBuffer.forcedEmpty; instBuffer _ p.instBuffer; initCycles _ cycles _ 0; control _ nextOpcode; }; IF control = nextuInst THEN RETURN [LOOPHOLE[0, Inst], ZerosWord]; -- am inside of a uInst sequence and already have uPCa & uPCb so bug out. TRUSTED { instBufferPtr _ @instBuffer[0]; }; IF newPC = instBuffer.nextPC THEN { <> used: INT _ WordToInt[newPC] - WordToInt[instBuffer.basePC]; valid _ instBuffer.validWords*bytesPerWord; IF used > 0 AND used < valid THEN valid _ valid - used ELSE valid _ 0; }; { <> start: InstBufferIndex _ 0; -- byte index in buffer of newPC <> < RescheduleTrap > IFUPageFaultTrap>> <<-- **** Trap Handler should check OverFlow and UnderFlow>> <> <> <<= IFUOverflow-1 => {};>> <<< IFUStackSize =>>> <> <> <>> <> <> <<};>> <<};>> <<>> OutsideEnvelope: PUBLIC SIGNAL [explanation: Rope.ROPE] = CODE; END.