📄 perfectmem.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * *//***************************************************************** * perfectmem.c * * Author: $Author: bosch $ * Date: $Date: 1998/02/10 00:37:23 $ *****************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include "memsys.h"#include "sim.h"#include "sim_error.h"#include "simutil.h"#if 0#include "mipsy.h"#include "cpu_state.h"#endif#include "scache.h"#include "eventcallback.h"#include "cpu_interface.h"#include "machine_params.h"#include "arch_specifics.h"#ifdef SOLO#include "solo_page.h"#define DATA_ADDR(_m, _pa) SoloGetMemoryAddr(SoloDecompressAddr(0,_pa))#else#define DATA_ADDR(_m, _pa) PHYS_TO_MEMADDR(_m, _pa)#endifstatic Result PerfectMemCmd(int cpunum, int cmd, PA paddr, int transId, PA replacedPaddr, int writeback, byte *data);static void PerfectMemDumpStats(void);static void PerfectMemDone(void);static void PerfectMemStatus(void);struct PerfMemStats { SimCounter gets; SimCounter igets; SimCounter getxs; SimCounter uncwrites; SimCounter uncaccwrites; SimCounter uncreads; SimCounter upgrades; SimCounter invalidates; SimCounter sharingwritebacks; SimCounter invalwritebacks; SimCounter memreads; SimCounter memwrites; SimCounter naks; SimCounter invalHist[SIM_MAXCPUS];} perfStats[SIM_MAXCPUS];#define MAX_OUTSTANDING (SIM_MAXCPUS*MEMSYS_MAX_OUTSTANDING)static int DoInvalidates(int cpunum, int transId, PA paddr, int mode);static Result DoMemRequest(int cpunum, int transId, PA paddr, int mode, byte *data, int len);static Result DoUncachedRequest(int cpunum, int transId, PA paddr, uint mcmd, byte *data, int len);static void InitStats(void);/***************************************************************** * remap region support *****************************************************************/static PA backmapMask;static PA nodeaddrMask;static voidPerfUpdateBackmapMask(void){ /* the backmapMask is an optimization that summarizes all the enabled * remap masks; it has ones in any bit position which, if set, means * this physical address could not be the target of a remap on any * CPU. * * nodeaddrMask masks out the node id bits. */ int i; backmapMask = nodeaddrMask; for (i=0; i<TOTAL_CPUS; i++) { if (remapVec->RemapEnable[i]) { backmapMask &= remapVec->RemapMask[i]; } }}static voidPerfInitRemap(void){ int i, machine; /* We initialize backmapMask to all ones except for the * bits that might be set in the node id field */ nodeaddrMask = ~0; for (machine=0; machine<NUM_MACHINES; machine++) { for (i=0; i<NUM_CPUS(machine); i++) { if (!remapVec->NodeAddrInitialized) {#ifdef TORNADO int m = machine; remapVec->NodeAddr[FIRST_CPU(machine)+i] = (i*NUM_MEMORIES(m)/NUM_CPUS(m)) * (MEM_SIZE(m) / NUM_CPUS(m)); CPUWarning("perfectmem: nodeaddr for %d/%d is %lx\n", i, FIRST_CPU(machine)+i, (unsigned long)(remapVec->NodeAddr[FIRST_CPU(machine)+i]));#elif defined(SIM_ORIGIN) remapVec->NodeAddr[FIRST_CPU(machine)+i] = MEMADDR_TO_PHYS(machine, SIM_MEM_ADDR(machine) + (i/2) * 2 * (MEM_SIZE(machine) / NUM_CPUS(machine)));#else remapVec->NodeAddr[FIRST_CPU(machine)+i] = MEMADDR_TO_PHYS(machine, SIM_MEM_ADDR(machine) + i * (MEM_SIZE(machine) / NUM_CPUS(machine)));#endif } nodeaddrMask &= ~remapVec->NodeAddr[FIRST_CPU(machine)+i]; } } remapVec->NodeAddrInitialized = 1; /* now zero out the low bits of the backmapmask */ PerfUpdateBackmapMask();}static voidPerfSetRemap(int cpunum, PA mask){ remapVec->RemapMask[cpunum] = mask; PerfUpdateBackmapMask();}static voidPerfControlRemap(int cpunum, int isEnabled){ remapVec->RemapEnable[cpunum] = isEnabled; PerfUpdateBackmapMask();}static voidPerfDrain(void){}static PAPerfGetNodeAddress(int cpunum){ return remapVec->NodeAddr[cpunum];}#define BACKMAP_PADDR(paddr,cpunum) \ (((paddr & backmapMask) \ || !remapVec->RemapEnable[cpunum] \ || ((paddr & remapVec->RemapMask[cpunum]) != remapVec->NodeAddr[cpunum])) \ ? paddr : (paddr - remapVec->NodeAddr[cpunum]))/***************************************************************** * MemsysInit *****************************************************************//***************************************************************** * PerfectMemInit *****************************************************************/voidPerfectMemInit(void){ memsysVec.type = PERFECTMEM; memsysVec.MemsysCmd = PerfectMemCmd; memsysVec.MemsysDumpStats = PerfectMemDumpStats; memsysVec.MemsysDone = PerfectMemDone; memsysVec.MemsysStatus = PerfectMemStatus; memsysVec.MemsysSetRemap = PerfSetRemap; memsysVec.MemsysControlRemap = PerfControlRemap; memsysVec.MemsysGetNodeAddress = PerfGetNodeAddress; memsysVec.MemsysDrain = PerfDrain; /* For now, only allow zero-latency memory */ memsysVec.NoMemoryDelay = 1; if (PERFECTMEM_LATENCY != 0) { CPUError("Nonzero fixed memory latency not yet supported\n"); } CPUPrint("MEMSYS - Perfect: %d pclock access time\n", PERFECTMEM_LATENCY); bzero((char *) perfStats, sizeof(perfStats)); InitStats(); PerfInitRemap();}/***************************************************************** * PerfectMemCmd *****************************************************************/static ResultPerfectMemCmd(int cpunum, int cmd, PA addr, int transId, PA replacedPaddr, int writeback, byte *data){ int dmalen;#ifndef SOLO addr = REMAP_PADDR(addr, cpunum); replacedPaddr = REMAP_PADDR(replacedPaddr, cpunum);#endif#ifdef DEBUG CPUPrint("MEM: cpu %d, cmd %d, transId %d, addr %08x, replace %08x, " "wb %d, data %08x\n", cpunum, cmd, transId, addr, replacedPaddr, writeback, data);#endif if (cmd == MEMSYS_SYNC) { return SUCCESS; } if (writeback && (replacedPaddr != MEMSYS_NOADDR)) { ASSERT(!(cmd & MEMSYS_DMAFLAVOR));#ifdef DATA_HANDLING bcopy(data, DATA_ADDR(M_FROM_CPU(cpunum), replacedPaddr), SCACHE_LINE_SIZE);#ifdef DEBUG CPUPrint("MEM: Writeback of %08x from %08x to %08x\n", replacedPaddr, data, DATA_ADDR(M_FROM_CPU(cpunum), replacedPaddr));#endif#endif } /* Handle special case: a GET with transId -1 indicates * a writeback or repl hint without the associated GET (due * to a CACHE instruction executed in the processor) */ if (((cmd & MEMSYS_CMDMASK) == MEMSYS_GET) && (transId == -1) && !(cmd & MEMSYS_DMAFLAVOR)) { return SUCCESS; } if (addr == MEMSYS_NOADDR) { /* * Ignore writebacks and replacement hints. */ if (writeback) perfStats[cpunum].memwrites++; return SUCCESS; } if( cmd & MEMSYS_DMAFLAVOR ) { /* DMA command. This is not issued by any particular CPU * and does not unstall the CPU. CacheCmdDone must therefore not * be called */ /* writeback is the length */ ASSERT( transId < 0 ); dmalen = writeback; } else { ASSERT( transId >= 0); dmalen = 0; } switch (cmd & MEMSYS_CMDMASK) { case MEMSYS_GET: if( cpunum >= 0) { perfStats[cpunum].gets++; if (cmd & MEMSYS_IFFLAVOR) perfStats[cpunum].igets++; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -