introduced victim cache for a trace cache structure.

Allows to significantly  cut trace cache miss latenct and find data in victim cahe instead of redoding it 
8 entries VC in parallel with direct map 64K entries
This commit is contained in:
Stanislav Shwartsman 2011-03-25 23:06:34 +00:00
parent 9950c2a943
commit 4de76b0571
8 changed files with 74 additions and 26 deletions

View File

@ -192,7 +192,7 @@ bxICacheEntry_c* BX_CPU_C::getICacheEntry(void)
// iCache miss. No validated instruction with matching fetch parameters
// is in the iCache.
InstrICache_Increment(iCacheMisses);
serveICacheMiss(entry, (Bit32u) eipBiased, pAddr);
entry = serveICacheMiss(entry, (Bit32u) eipBiased, pAddr);
}
return entry;

View File

@ -2965,7 +2965,7 @@ public: // for now...
BX_SMF int fetchDecode64(const Bit8u *fetchPtr, bxInstruction_c *i, unsigned remainingInPage) BX_CPP_AttrRegparmN(3);
#endif
BX_SMF void boundaryFetch(const Bit8u *fetchPtr, unsigned remainingInPage, bxInstruction_c *);
BX_SMF void serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr);
BX_SMF bxICacheEntry_c *serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr);
BX_SMF bxICacheEntry_c* getICacheEntry(void);
#if BX_SUPPORT_TRACE_CACHE
BX_SMF bx_bool mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy_address pAddr);

View File

@ -1271,9 +1271,8 @@ BX_CPU_C::fetchDecode32(const Bit8u *iptr, bxInstruction_c *i, unsigned remainin
unsigned sse_prefix = SSE_PREFIX_NONE;
int had_vex = 0;
#if BX_SUPPORT_AVX
int vvv = -1;
unsigned vex;
#if BX_SUPPORT_AVX
bx_bool vex_w = 0;
#endif
@ -1357,7 +1356,7 @@ fetch_b1:
if ((attr & BxGroupX) == BxPrefixVEX && (*iptr & 0xc0) == 0xc0) {
had_vex = 1;
if (sse_prefix) had_vex = -1;
unsigned vex_opcext = 1;
unsigned vex, vex_opcext = 1;
if (remain != 0) {
remain--;
@ -1391,7 +1390,6 @@ fetch_b1:
return(-1);
b1 += 256 * vex_opcext;
if (b1 < 256 || b1 >= 1024) had_vex = -1;
else {
if (b1 >= 512)
@ -1434,9 +1432,10 @@ fetch_b1:
i->setNnn(nnn);
#if BX_SUPPORT_AVX
if (had_vex == 0) vvv = nnn;
i->setVvv(vvv);
if (had_vex == 0)
#endif
vvv = nnn;
i->setVvv(vvv);
// MOVs with CRx and DRx always use register ops and ignore the mod field.
if ((b1 & ~3) == 0x120)
@ -1613,8 +1612,9 @@ modrm_done:
case BxGroupN:
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn]);
#if BX_SUPPORT_AVX
if (had_vex == 0) i->setVvv(rm);
if (had_vex == 0)
#endif
i->setVvv(rm);
break;
case BxSplitGroupN:
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn + (mod_mem << 3)]);

View File

@ -1704,9 +1704,8 @@ BX_CPU_C::fetchDecode64(const Bit8u *iptr, bxInstruction_c *i, unsigned remainin
unsigned rex_prefix = 0;
int had_vex = 0;
#if BX_SUPPORT_AVX
int vvv = -1;
unsigned vex;
#if BX_SUPPORT_AVX
bx_bool vex_w = 0;
#endif
@ -1828,7 +1827,7 @@ fetch_b1:
if ((attr & BxGroupX) == BxPrefixVEX) {
had_vex = 1;
if (sse_prefix || rex_prefix) had_vex = -1;
unsigned vex_opcext = 1;
unsigned vex, vex_opcext = 1;
if (remain != 0) {
remain--;
@ -1838,7 +1837,6 @@ fetch_b1:
return(-1);
rex_r = ((vex >> 4) & 0x8) ^ 0x8;
if (b1 == 0xc4) {
rex_x = ((vex >> 3) & 0x8) ^ 0x8;
rex_b = ((vex >> 2) & 0x8) ^ 0x8;
@ -1871,7 +1869,6 @@ fetch_b1:
return(-1);
b1 += 256 * vex_opcext;
if (b1 < 256 || b1 >= 1024) had_vex = -1;
else {
if (b1 >= 512)
@ -1914,9 +1911,10 @@ fetch_b1:
i->setNnn(nnn);
#if BX_SUPPORT_AVX
if (had_vex == 0) vvv = nnn;
i->setVvv(vvv);
if (had_vex == 0)
#endif
vvv = nnn;
i->setVvv(vvv);
// MOVs with CRx and DRx always use register ops and ignore the mod field.
if ((b1 & ~3) == 0x120)
@ -2092,8 +2090,9 @@ modrm_done:
case BxGroupN:
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn & 0x7]);
#if BX_SUPPORT_AVX
if (had_vex == 0) i->setVvv(rm);
if (had_vex == 0)
#endif
i->setVvv(rm);
break;
case BxSplitGroupN:
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[(nnn & 0x7) + (mod_mem << 3)]);

View File

@ -57,8 +57,15 @@ void handleSMC(bx_phy_address pAddr, Bit32u mask)
#if BX_SUPPORT_TRACE_CACHE
void BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr)
bxICacheEntry_c* BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr)
{
bxICacheEntry_c *vc_hit = BX_CPU_THIS_PTR iCache.lookup_victim_cache(pAddr, BX_CPU_THIS_PTR fetchModeMask);
if (vc_hit) {
return vc_hit;
}
BX_CPU_THIS_PTR iCache.victim_entry(entry, BX_CPU_THIS_PTR fetchModeMask);
BX_CPU_THIS_PTR iCache.alloc_trace(entry);
// Cache miss. We weren't so lucky, but let's be optimistic - try to build
@ -104,7 +111,7 @@ void BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_
pageWriteStampTable.markICacheMask(entry->pAddr, entry->traceMask);
pageWriteStampTable.markICacheMask(BX_CPU_THIS_PTR pAddrPage, 0x1);
BX_CPU_THIS_PTR iCache.commit_page_split_trace(BX_CPU_THIS_PTR pAddrPage, entry);
return;
return entry;
}
// add instruction to the trace
@ -137,6 +144,8 @@ void BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_
pageWriteStampTable.markICacheMask(pAddr, entry->traceMask);
BX_CPU_THIS_PTR iCache.commit_trace(entry->tlen);
return entry;
}
bx_bool BX_CPU_C::mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy_address pAddr)

View File

@ -137,6 +137,13 @@ public:
bxICacheEntry_c *e; // Pointer to icache entry
} pageSplitIndex[BX_ICACHE_PAGE_SPLIT_ENTRIES];
int nextPageSplitIndex;
#define BX_ICACHE_VICTIM_ENTRIES 8 /* must be power of two */
struct bxVictimCacheEntry {
Bit32u fetchModeMask;
bxICacheEntry_c vc_entry;
} victimCache[BX_ICACHE_VICTIM_ENTRIES];
int nextVictimCacheIndex;
#endif
public:
@ -173,11 +180,31 @@ public:
nextPageSplitIndex = (nextPageSplitIndex+1) & (BX_ICACHE_PAGE_SPLIT_ENTRIES-1);
}
BX_CPP_INLINE bxICacheEntry_c *lookup_victim_cache(bx_phy_address pAddr, Bit32u fetchModeMask)
{
for (int i=0; i < BX_ICACHE_VICTIM_ENTRIES;i++) {
bxVictimCacheEntry *e = &victimCache[i];
if (e->vc_entry.pAddr == pAddr && e->fetchModeMask == fetchModeMask) {
return &e->vc_entry;
}
}
return NULL;
}
BX_CPP_INLINE void victim_entry(bxICacheEntry_c *entry, Bit32u fetchModeMask)
{
if (entry->pAddr != BX_ICACHE_INVALID_PHY_ADDRESS) {
victimCache[nextVictimCacheIndex].fetchModeMask = fetchModeMask;
victimCache[nextVictimCacheIndex].vc_entry = *entry;
nextVictimCacheIndex = (nextVictimCacheIndex+1) & (BX_ICACHE_VICTIM_ENTRIES-1);
}
}
#endif
BX_CPP_INLINE void handleSMC(bx_phy_address pAddr, Bit32u mask);
BX_CPP_INLINE void purgeICacheEntries(void);
BX_CPP_INLINE void flushICacheEntries(void);
BX_CPP_INLINE bxICacheEntry_c* get_entry(bx_phy_address pAddr, unsigned fetchModeMask)
@ -198,17 +225,22 @@ BX_CPP_INLINE void bxICache_c::flushICacheEntries(void)
}
#if BX_SUPPORT_TRACE_CACHE
nextPageSplitIndex = 0;
for (i=0;i<BX_ICACHE_PAGE_SPLIT_ENTRIES;i++)
pageSplitIndex[i].ppf = BX_ICACHE_INVALID_PHY_ADDRESS;
nextPageSplitIndex = 0;
nextVictimCacheIndex = 0;
for (i=0;i<BX_ICACHE_VICTIM_ENTRIES;i++)
victimCache[i].vc_entry.pAddr = BX_ICACHE_INVALID_PHY_ADDRESS;
mpindex = 0;
#endif
}
// TODO: invalidate only entries in same page as pAddr
BX_CPP_INLINE void bxICache_c::handleSMC(bx_phy_address pAddr, Bit32u mask)
{
// TODO: invalidate only entries in same page as pAddr
unsigned i;
pAddr = LPFOf(pAddr);
@ -216,12 +248,17 @@ BX_CPP_INLINE void bxICache_c::handleSMC(bx_phy_address pAddr, Bit32u mask)
if (mask & 0x1) {
// the store touched 1st cache line in the page, check for
// page split traces to invalidate.
for (unsigned i=0;i<BX_ICACHE_PAGE_SPLIT_ENTRIES;i++) {
for (i=0;i<BX_ICACHE_PAGE_SPLIT_ENTRIES;i++) {
if (pAddr == pageSplitIndex[i].ppf) {
pageSplitIndex[i].ppf = BX_ICACHE_INVALID_PHY_ADDRESS;
}
}
}
for (i=0;i < BX_ICACHE_VICTIM_ENTRIES; i++) {
bxVictimCacheEntry *e = &victimCache[i];
e->vc_entry.pAddr = BX_ICACHE_INVALID_PHY_ADDRESS;
}
#endif
bxICacheEntry_c *e = get_entry(pAddr, 0);

View File

@ -38,6 +38,8 @@ typedef bx_address (BX_CPU_C::*BxResolvePtr_tR)(bxInstruction_c *) BX_CPP_AttrRe
extern bx_address bx_asize_mask[];
const char *get_bx_opcode_name(Bit16u ia_opcode);
// <TAG-CLASS-INSTRUCTION-START>
class bxInstruction_c {
public:
@ -244,6 +246,9 @@ public:
BX_CPP_INLINE void setIaOpcode(Bit16u op) {
metaInfo.ia_opcode = (metaInfo.ia_opcode & 0xf000) | op;
}
BX_CPP_INLINE const char* getIaOpcodeName(void) const {
return get_bx_opcode_name(getIaOpcode());
}
BX_CPP_INLINE unsigned repUsedL(void) const {
return metaInfo.metaInfo1 >> 6;
@ -283,8 +288,6 @@ public:
};
// <TAG-CLASS-INSTRUCTION-END>
const char *get_bx_opcode_name(Bit16u ia_opcode);
enum {
#define bx_define_opcode(a, b, c, d, e) a,
#include "ia_opcodes.h"

View File

@ -475,7 +475,7 @@ void BX_CPP_AttrRegparmN(3) BX_CPU_C::VMexit_IO(bxInstruction_c *i, unsigned por
break;
default:
BX_PANIC(("VMexit_IO: I/O instruction %s unknown", get_bx_opcode_name(i->getIaOpcode())));
BX_PANIC(("VMexit_IO: I/O instruction %s unknown", i->getIaOpcodeName()));
}
if (qualification & VMX_VMEXIT_IO_INSTR_STRING) {