📄 false_sharing.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. * *//*********************************************************************** * false_sharing.c * Cache interface that determines true and false sharing. * * $Author: bosch $ * $Date: 1998/02/10 00:28:55 $ * * XXX bug: scales with TOTAL_CPUS, which is bad * XXX for multiple machines (although theoretically correct) * XXX bug: sparse address space not really supported ***********************************************************************/#include <stdlib.h>#include "string.h"#include "sim_error.h"#include "cpu_interface.h"#include "simutil.h"#include "machine_params.h"#include "false_sharing.h"#include "memstat.h"#include "statrecord.h"#include "tcl_init.h"#include "arch_specifics.h"FalseSharingBV *falseSharingMaskEntries[MAX_MACHINES];uint falseSharingMask;bool falseSharing;static FalseSharingEntry *falseSharingAccessed[MAX_MACHINES][SIM_MAXCPUS];static FalseSharingBV *falseSharingModifyWords;static MA startMA;static MA endMA;static struct { StatRecordFieldDesc falseSharing[NUM_CATEGS]; StatRecordFieldDesc trueSharing[NUM_CATEGS]; StatRecordFieldDesc falseSharingStall[NUM_CATEGS]; StatRecordFieldDesc trueSharingStall[NUM_CATEGS];} falseSharingBucket;#define PADDR_TO_INDEX(_pa,_way) \ (((_pa>>log2SCACHE_LINE_SIZE) & (SCACHE_INDEX-1))*SCACHE_ASSOC + _way)#ifdef TRACK_FALSE_SHARINGint FalseSharing = 1;#elseint FalseSharing = 0;#endifextern int memstatOption;/***************************************************************** * FalseSharingInit *****************************************************************/void FalseSharingEarlyInit(void){ if (FalseSharing) { if (memstatOption == 0) { CPUWarning("\n\nFALSE SHARING: requires MemStat enabled (Level != None)\n\n"); return; } MemStatInitCategoryFields(falseSharingBucket.trueSharing, "trueSharing", STATRECORD_DATA|STATRECORD_INSTRUCTION); MemStatInitCategoryFields(falseSharingBucket.falseSharing, "falseSharing", STATRECORD_DATA|STATRECORD_INSTRUCTION); MemStatInitCategoryFields(falseSharingBucket.trueSharingStall, "trueShStall", STATRECORD_DATA|STATRECORD_INSTRUCTION); MemStatInitCategoryFields(falseSharingBucket.falseSharingStall, "falseShStall", STATRECORD_DATA|STATRECORD_INSTRUCTION); falseSharing = 1; }} void FalseSharingLateInit(void){ int machine; int i; int scacheLine = SCACHE_LINE_SIZE; int scacheSize = SCACHE_SIZE; int shift; long totalMemSize = 0; if (!falseSharing) { return; } CPUWarning("FALSE SHARING: initialized\n"); falseSharingMask = scacheLine -1; if (scacheLine > 4* 8 * sizeof(FalseSharingBV)) { shift = GetLog2(scacheLine / (8 * sizeof(FalseSharingBV))); } else { shift = 2; /* word granularity */ } ASSERT(TOTAL_CPUS && NUM_MACHINES); for (machine = 0; machine < NUM_MACHINES; machine++) { ASSERT(MEM_SIZE(machine)); totalMemSize += MEM_SIZE(machine); falseSharingMaskEntries[machine] = (FalseSharingBV *) ZALLOC_PERM(scacheLine* sizeof(FalseSharingBV), "FalseSharing"); for (i=0; i<scacheLine; i++) { uint j = (i>>shift); ASSERT( j < 8 * sizeof(FalseSharingBV) ); falseSharingMaskEntries[machine][i] = 1<<j; } for (i=0; i<NUM_CPUS(machine); i++) { int j; falseSharingAccessed[machine][i] = (FalseSharingEntry *) ZALLOC_PERM(sizeof(FalseSharingEntry) * scacheSize / scacheLine ,"FalseSharing"); for(j=0;j< scacheSize / scacheLine; j++) { falseSharingAccessed[machine][i][j].categ = -1; } } } falseSharingModifyWords = (FalseSharingBV *) ZALLOC_PERM(sizeof(FalseSharingBV)* (totalMemSize/scacheLine) * TOTAL_CPUS, "FalseSharing"); ASSERT(falseSharingModifyWords); startMA = PHYS_TO_MEMADDR(0,0); endMA = startMA + totalMemSize; ASSERT(startMA);}/***************************************************************** * SCacheLineToFalseSharing *****************************************************************/FalseSharingEntry *SCacheLineToFalseSharing(int cpuNum, PA pAddr, int way) { uint index = PADDR_TO_INDEX(pAddr,way); if (!falseSharing) { return 0; } else { return (falseSharingAccessed[M_FROM_CPU(cpuNum)] [MCPU_FROM_CPU(cpuNum)]) + index ; }}/***************************************************************** * FalseSharingDefine *****************************************************************/void FalseSharingDefine(int cpuNum, PA pAddr, int way, VA PC, VA vAddr, int stall){ uint index; FalseSharingEntry *e; if( !falseSharing ) { return; } index = PADDR_TO_INDEX(pAddr,way); if( interest(pAddr)) { LogEntry("def", cpuNum,"pA=0x%08x index=0x%06x way=%i \n",pAddr,index,way); } e = (falseSharingAccessed[M_FROM_CPU(cpuNum)] [MCPU_FROM_CPU(cpuNum)])+index; ASSERT (!e->valid);#ifndef SIM_ALPHA ASSERT (vAddr);#endif e->valid = 1; e->PC = PC; e->vAddr = vAddr; e->pAddr = pAddr; e->stall = stall; e->snap = StatRecordAllocSnapshot(cpuNum); e->accessedWords = 0; /* clear bit vector */ e->categ = -1;}/***************************************************************** * FalseSharingDefineOffset *****************************************************************/void FalseSharingDefineOffset(int cpuNum, PA pAddr,int way, int categ){ uint index; FalseSharingEntry *e; if( !falseSharing ) { return; } index = PADDR_TO_INDEX(pAddr,way); e = (falseSharingAccessed[M_FROM_CPU(cpuNum)] [MCPU_FROM_CPU(cpuNum)])+index; ASSERT (e->valid); ASSERT( e->categ < 0 ); ASSERT( categ >= 0 && categ < NUM_CATEGS); ASSERT (pAddr>>log2SCACHE_LINE_SIZE == e->pAddr>>log2SCACHE_LINE_SIZE); e->categ = categ;}/***************************************************************** * FalseSharingEvict *****************************************************************/void FalseSharingEvict(int cpuNum, PA pAddr, int way, int type){ int machine = M_FROM_CPU(cpuNum); MA mAddr = PHYS_TO_MEMADDR(machine,pAddr); PA mAddrOff = (PA)(mAddr-startMA); uint index; FalseSharingEntry *e; FalseSharingBV *modifiedBV; if (!falseSharing) { return; } ASSERT( startMA <= mAddr && mAddr < endMA); ASSERT(mAddrOff >= 0); index = PADDR_TO_INDEX(pAddr,way); e = (falseSharingAccessed[machine][MCPU_FROM_CPU(cpuNum)])+index; if( interest(pAddr)) { LogEntry("evict", cpuNum,"pA=0x%08x index=0x%06x way=%i \n",pAddr,index,way); } /* now we know if it is true or false sharing */ if( !e->valid ) { ASSERT (e->categ < 0); /* *miss was not recorded. *Most likely an instruction miss on that line. */ return; } if (pAddr>>log2SCACHE_LINE_SIZE != e->pAddr>>log2SCACHE_LINE_SIZE) { LogEntry("FALSESH",cpuNum,"pAddr missmatched %x != %x type=%x \n", pAddr,e->pAddr,type); return; } ASSERT(e->categ >= 0); modifiedBV = &falseSharingModifyWords[((mAddrOff>>log2SCACHE_LINE_SIZE)*TOTAL_CPUS) + cpuNum]; if (e->accessedWords & *modifiedBV) { /* true sharing */ StatRecordIncrement(e->snap, e->PC, e->vAddr, falseSharingBucket.trueSharing[e->categ],1); StatRecordIncrement(e->snap, e->PC, e->vAddr, falseSharingBucket.trueSharingStall[e->categ], e->stall); *modifiedBV = 0; } else { StatRecordIncrement(e->snap, e->PC, e->vAddr, falseSharingBucket.falseSharing[e->categ],1); StatRecordIncrement(e->snap, e->PC, e->vAddr, falseSharingBucket.falseSharingStall[e->categ], e->stall); } StatRecordFreeSnapshot(e->snap); e->vAddr = 0; e->valid = 0; e->categ = -1;}/***************************************************************** * FalseSharingModify *****************************************************************/void FalseSharingModify(int cpuNum, PA pAddr){ int machine = M_FROM_CPU(cpuNum); MA mAddr = PHYS_TO_MEMADDR(cpuNum,pAddr); PA mAddrOff = (PA)(mAddr-startMA); FalseSharingBV *modifiedBV; FalseSharingBV mask; int i; if (!falseSharing) { return; } ASSERT(startMA <= mAddr && mAddr < endMA); modifiedBV = &falseSharingModifyWords[(mAddrOff>>log2SCACHE_LINE_SIZE) * TOTAL_CPUS]; mask = falseSharingMaskEntries[machine][pAddr&falseSharingMask]; for(i=0;i<TOTAL_CPUS;i++){ if (i != cpuNum) { *modifiedBV |= mask; } modifiedBV++; }} /***************************************************************** * FalseSharingModify * Called when the simulation ends. All true sharing misses * are classified as such. *****************************************************************/void FalseSharingCleanup(void){ int lines; int cpuNum; int index; int count=0; if (!falseSharing) return; ASSERT (SCACHE_SIZE && SCACHE_LINE_SIZE); lines = SCACHE_SIZE / SCACHE_LINE_SIZE; for(cpuNum=0; cpuNum < TOTAL_CPUS;cpuNum++) { int machine = M_FROM_CPU(cpuNum); for(index=0;index < lines; index++){ FalseSharingEntry *e = (falseSharingAccessed[machine][MCPU_FROM_CPU(cpuNum)])+index; FalseSharingBV *modifiedBV = &falseSharingModifyWords[index*TOTAL_CPUS + cpuNum]; if( !e->valid ) continue; ASSERT(e->categ >= 0); if (e->accessedWords & *modifiedBV) { /* true sharing */ count++; StatRecordIncrement(e->snap, e->PC, e->vAddr, falseSharingBucket.trueSharing[e->categ],1); StatRecordIncrement(e->snap, e->PC, e->vAddr, falseSharingBucket.trueSharingStall[e->categ], e->stall); *modifiedBV = 0; StatRecordFreeSnapshot(e->snap); e->vAddr = 0; e->valid = 0; e->categ = -1; } } } CPUWarning("FALSE SHARING CLEANUP : %d true sharings detected \n",count);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -