DIRECTORY Basics, CacheModel, Convert, DragOpsCross, DragOpsCrossUtils, IO, PrincOps, RESInterpreter, Rope; RESIUtil: CEDAR PROGRAM IMPORTS Convert, CacheModel, DragOpsCrossUtils, IO, RI: RESInterpreter, Rope EXPORTS RESInterpreter = { OPEN PrincOps; Value: TYPE = RI.Value; DValue: TYPE = RI.DValue; Ptr1: TYPE = RI.Ptr1; Ptr2: TYPE = RI.Ptr2; LPtr1: TYPE = RI.LPtr1; LPtr2: TYPE = RI.LPtr2; ROPE: TYPE = Rope.ROPE; Machine: TYPE = RI.Machine; Byte: TYPE = RI.Byte; Bytes: TYPE = RI.Bytes; Pair: TYPE = RI.Pair; FieldDescriptor: TYPE = PrincOps.FieldDescriptor; LCB: TYPE = RI.LCB; wordsPerPage: CARDINAL = CacheModel.wordsPerPage; bytesPerWord: NAT = DragOpsCross.bytesPerWord; LocalsInRing: NAT = 16; Word: TYPE = DragOpsCross.Word; CacheIndex: TYPE = [0..8); CacheInfoRec: TYPE = RECORD [ active: BOOL _ TRUE, cacheLines: NAT, cacheQuads: NAT, iCaches, dCaches: NAT _ 0, iCache: ARRAY CacheIndex OF CacheModel.CacheBase _ ALL[NIL], dCache: ARRAY CacheIndex OF CacheModel.CacheBase _ ALL[NIL], iBufferSize: NAT _ 16, iBufferBytes: NAT _ 0, afterJump: BOOL _ FALSE, lru: BOOL _ FALSE]; CacheInfo: TYPE = REF CacheInfoRec; FlushAllCaches: PUBLIC PROC [m: Machine] = { cache: CacheInfo _ NARROW[m.cacheData]; IF cache = NIL THEN RETURN; FOR i: NAT IN [0..cache.iCaches) DO CacheModel.FlushCache[cache.iCache[i]]; ENDLOOP; FOR i: NAT IN [0..cache.dCaches) DO CacheModel.FlushCache[cache.dCache[i]]; ENDLOOP; }; ResetCacheModel: PUBLIC PROC [m: Machine, instr, data, lines, quads: NAT, lru: BOOL] = { cache: CacheInfo _ NARROW[m.cacheData]; IF cache # NIL AND lines = cache.cacheLines AND quads = cache.cacheQuads AND instr = cache.iCaches AND data = cache.dCaches AND lru = cache.lru THEN { FOR i: NAT IN [0..instr) DO CacheModel.ResetCache[cache.iCache[i]]; ENDLOOP; FOR i: NAT IN [0..data) DO CacheModel.ResetCache[cache.dCache[i]]; ENDLOOP; cache.iBufferBytes _ 0} ELSE { m.cacheData _ cache _ NEW [CacheInfoRec _ [ cacheLines: lines, cacheQuads: quads, iCaches: instr, dCaches: data, lru: lru]]; FOR i: NAT IN [0..instr) DO cache.iCache[i] _ CacheModel.NewCache[lines, quads, lru]; ENDLOOP; FOR i: NAT IN [0..data) DO cache.dCache[i] _ CacheModel.NewCache[lines, quads, lru]; ENDLOOP}; }; PrintOneCache: PROC [ os: IO.STREAM, cb: CacheModel.CacheBase, name: ROPE, lines, quads: NAT, lru: BOOL] = { Realn: PROC [r: REAL, n: NAT] RETURNS [IO.Value] = { RETURN [[rope[Convert.RopeFromReal[r, n]]]]}; quadMisses: INT _ cb.stats.chunkMisses; misses: INT _ quadMisses + cb.stats.lineMisses; probes: INT _ cb.stats.probes; rProbes: REAL _ probes; rMisses: REAL _ misses; os.PutF[ "\nStats for %g (lines: %g, quads/line: %g)\n probes: %g\n", [rope[IF lru THEN Rope.Cat[name, " (pseudo-lru)"] ELSE name]], [integer[lines]], [integer[quads]], [integer[probes]]]; IF probes = 0 THEN RETURN; os.PutF[ " misses: %g (%g (%g%%) existing line)\n", [integer[misses]], [integer[cb.stats.chunkMisses]], IF misses = 0 THEN [rope["-"]] ELSE Realn[(quadMisses/rMisses)*100, 3]]; IF cb.stats.jumpMisses # 0 THEN os.PutF[ " misses caused by jumps: %g (%g%% of probes)\n", [integer[cb.stats.jumpMisses]], Realn[(cb.stats.jumpMisses/rProbes)*100, 3]]; IF probes # 0 THEN os.PutF[ " hit rate: %g%%\n", Realn[((probes - misses)/rProbes)*100, 3]]; os.PutF[ " map misses: %g\n dirty writes: %g\n", [integer[cb.stats.mapMisses]], [integer[cb.stats.dirtyWrites]]]; }; EnableCacheModel: PUBLIC PROC [m: Machine, state: BOOL, instr, data, lines, quads: NAT, lru: BOOL] = { cache: CacheInfo _ NARROW[m.cacheData]; IF cache = NIL THEN { ResetCacheModel[m: m, instr: instr, data: data, lines: lines, quads: quads, lru: lru]; cache _ NARROW[m.cacheData]}; cache.active _ state}; PrintCacheStats: PUBLIC PROC [os: IO.STREAM, m: Machine] = { cache: CacheInfo _ NARROW[m.cacheData]; IF cache # NIL THEN { FOR i: NAT IN [0..cache.iCaches) DO PrintOneCache[ os, cache.iCache[i], Rope.Cat["instruction cache ", Convert.RopeFromInt[i]], cache.cacheLines, cache.cacheQuads, cache.lru]; ENDLOOP; FOR i: NAT IN [0..cache.dCaches) DO PrintOneCache[ os, cache.dCache[i], Rope.Cat["data cache ", Convert.RopeFromInt[i]], cache.cacheLines, cache.cacheQuads, cache.lru]; ENDLOOP; }; }; ReadAtAddress: PUBLIC PROC [m: Machine, addr: LONG POINTER] = TRUSTED { cache: CacheInfo = NARROW[m.cacheData]; IF cache # NIL AND cache.active AND cache.dCaches # 0 THEN { byteAddress: LONG CARDINAL _ LOOPHOLE[addr, LONG CARDINAL]*2; wordAddr: Word; cacheIndex: NAT; [wordAddr,] _ DragOpsCrossUtils.BytePCToWordAddress[ [DragOpsCrossUtils.CardToWord[byteAddress]]]; cacheIndex _ (DragOpsCrossUtils.WordToCard[wordAddr] / wordsPerPage) MOD cache.dCaches; cache.dCache[cacheIndex].Fetch[wordAddr]}; }; DoubleReadAtAddress: PUBLIC PROC [m: Machine, addr: LONG POINTER] = TRUSTED { tAddr: Basics.LongNumber = LOOPHOLE[addr]; ReadAtAddress[m, addr]; }; ReadLocal: PUBLIC PROC [m: Machine, offset: CARDINAL] = TRUSTED { IF offset >= PrincOps.localbase + LocalsInRing THEN ReadAtAddress[m, m.l + offset]}; DoubleReadLocal: PUBLIC PROC [m: Machine, offset: CARDINAL] = TRUSTED { IF offset >= PrincOps.localbase + LocalsInRing THEN ReadAtAddress[m, m.l + offset]; }; WriteAtAddress: PUBLIC PROC [m: Machine, addr: LONG POINTER] = TRUSTED { cache: CacheInfo = NARROW[m.cacheData]; IF cache # NIL AND cache.active AND cache.dCaches # 0 THEN { byteAddress: LONG CARDINAL _ LOOPHOLE[addr, LONG CARDINAL]*2; wordAddr: Word; cacheIndex: NAT; [wordAddr,] _ DragOpsCrossUtils.BytePCToWordAddress[ [DragOpsCrossUtils.CardToWord[byteAddress]]]; cacheIndex _ (DragOpsCrossUtils.WordToCard[wordAddr] / wordsPerPage) MOD cache.dCaches; cache.dCache[cacheIndex].Store[wordAddr]}; }; DoubleWriteAtAddress: PUBLIC PROC [m: Machine, addr: LONG POINTER] = TRUSTED { tAddr: Basics.LongNumber = LOOPHOLE[addr]; WriteAtAddress[m, addr+1]; }; StoreLocal: PUBLIC PROC [m: Machine, offset: CARDINAL] = TRUSTED { IF offset >= PrincOps.localbase + LocalsInRing THEN WriteAtAddress[m, m.l + offset]}; DoubleStoreLocal: PUBLIC PROC [m: Machine, offset: CARDINAL] = TRUSTED { IF offset >= PrincOps.localbase + LocalsInRing THEN WriteAtAddress[m, m.l + offset+1]; }; NextOpByte: PUBLIC PROC [m: Machine, opcode: BOOL] RETURNS [b: Byte] = { cache: CacheInfo = NARROW[m.cacheData]; IF cache # NIL AND cache.active AND cache.iCaches # 0 THEN { IF cache.iBufferBytes = 0 OR (opcode AND cache.iBufferBytes <= cache.iBufferSize - bytesPerWord) THEN TRUSTED { cacheIndex: NAT; wordAddrInCache: Word; byteInWord: [0..bytesPerWord); byteAddress: LONG CARDINAL _ LOOPHOLE[m.cb, LONG CARDINAL]*2 + m.pc; [wordAddrInCache, byteInWord] _ DragOpsCrossUtils.BytePCToWordAddress[ [DragOpsCrossUtils.CardToWord[byteAddress]]]; cacheIndex _ (DragOpsCrossUtils.WordToCard[wordAddrInCache] / wordsPerPage) MOD cache.iCaches; cache.iCache[cacheIndex].Fetch[wordAddrInCache, cache.afterJump]; cache.iBufferBytes _ IF cache.iBufferBytes = 0 THEN bytesPerWord - byteInWord ELSE cache.iBufferBytes + bytesPerWord; }; cache.iBufferBytes _ cache.iBufferBytes - 1; cache.afterJump _ FALSE}; b _ LOOPHOLE[m.cb, LONG POINTER TO PACKED ARRAY [0..0) OF Byte][m.pc]; m.pc _ m.pc + 1; }; SetPc: PUBLIC PROC [m: Machine, pc: CARDINAL] = { WITH m.cacheData SELECT FROM cache: CacheInfo => {cache.iBufferBytes _ 0; cache.afterJump _ TRUE}; ENDCASE; m.pc _ pc}; UnboundProcTrap: PUBLIC PROC [m: Machine, link: ControlLink] = {ERROR Problem[m, unboundProc]}; ControlTrap: PUBLIC PROC [m: Machine, link: ControlLink] = {ERROR Problem[m, controlFault]}; Problem: PUBLIC ERROR [m: Machine, reason: RI.InterpreterProblem] = CODE; Confusion: PUBLIC PROC [m: Machine] = {ERROR Problem[m, confused]}; NilFault: PUBLIC PROC [m: Machine] = {ERROR Problem[m, nilcheck]}; BoundsFault: PUBLIC PROC [m: Machine] = {ERROR Problem[m, boundscheck]}; Push: PUBLIC PROC [m: Machine, v: Value] = {m.stack[m.sd] _ v; m.sd _ m.sd + 1}; Pop: PUBLIC PROC [m: Machine] RETURNS [v: Value] = {m.sd _ m.sd - 1; RETURN [m.stack[m.sd]]}; Top: PUBLIC PROC [m: Machine] RETURNS [v: Value] = {RETURN [m.stack[m.sd-1]]}; Push2: PUBLIC PROC [m: Machine, v: DValue] = { m.stack[m.sd] _ RI.VCard[v.lo]; m.stack[m.sd+1] _ RI.VCard[v.hi]; m.sd _ m.sd + 2}; Pop2: PUBLIC PROC [m: Machine] RETURNS [v: DValue] = { m.sd _ m.sd - 2; RETURN [[lo: RI.CardV[m.stack[m.sd]], hi: RI.CardV[m.stack[m.sd+1]]]]}; Read: PUBLIC PROC [m: Machine, p: LPtr1] RETURNS [Value] = TRUSTED { ReadAtAddress[m, p]; RETURN [p^]}; ReadDouble: PUBLIC PROC [m: Machine, p: LPtr2] RETURNS [DValue] = TRUSTED { DoubleReadAtAddress[m, p]; RETURN [p^]}; ReadField: PUBLIC PROC [m: Machine, p: LPtr1, fd: FieldDescriptor] RETURNS [Value] = TRUSTED { ReadAtAddress[m, p]; RETURN [RI.RFSLOp[p, fd]]}; Write: PUBLIC PROC [m: Machine, p: LPtr1, v: Value] = TRUSTED { WriteAtAddress[m, p]; p^ _ v}; WriteDouble: PUBLIC PROC [m: Machine, p: LPtr2, v: DValue] = TRUSTED { DoubleWriteAtAddress[m, p]; p^ _ v}; WriteField: PUBLIC PROC [m: Machine, p: LPtr1, fd: FieldDescriptor, v: Value] = TRUSTED { ReadAtAddress[m, p]; WriteAtAddress[m, p]; RI.WFSLOp[v: v, p: p, fd: fd]}; }. ΚRESIUtil.mesa Last Edited by: Sweet, March 19, 1985 10:14:42 am PST Types and Global Data Cache Model stuff Statistics recording IF tAddr.lowbits MOD 2 # 0 THEN ReadAtAddress[m, addr+1]; IF offset MOD 2 # 0 THEN ReadAtAddress[m, m.l + offset + 1]; IF tAddr.lowbits MOD 2 # 0 THEN WriteAtAddress[m, addr]; IF offset MOD 2 # 0 THEN WriteAtAddress[m, m.l + offset]; Utilities note instruction fetch This is a PrincOps byte address! note new pc value Κ 2˜Icodešœ ™ K™5K˜šΟk ˜ K˜K˜ K˜K˜ K˜Kšœ˜Kšœ ˜ K˜K˜K˜—šœ  œ˜Kšœ)œœ˜MKšœ˜—Kšœ ˜K˜šœ™Kšœœœ˜Kšœœœ ˜Kšœœœ˜Kšœœœ˜Kšœœœ˜Kšœœœ˜Kšœœœ˜K˜šœ œœ ˜K˜—Kšœœœ˜Kšœœœ˜Kšœœœ˜Kšœœ˜1Kšœœœœ˜Jšœœ˜1Jšœœ˜.Jšœœ˜Jšœœ˜K˜—šœ™K˜K˜šœœœ˜Kšœœœ˜Kšœ œ˜Kšœ œ˜Kšœœ˜Kš œœ œœœ˜1: