You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
6.8 KiB

/*
* Copyright 2002-2019 Intel Corporation.
*
* This software is provided to you as Sample Source Code as defined in the accompanying
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
* section 1.L.
*
* This software and the related documents are provided as is, with no express or implied
* warranties, other than those that are expressly stated in the License.
*/
/*! @file
* This file contains an ISA-portable PIN tool for functional simulation of
* instruction+data TLB+cache hierarchies
*/
#include <iostream>
#include "pin.H"
typedef UINT32 CACHE_STATS; // type of cache hit/miss counters
#include "pin_cache.H"
namespace ITLB
{
// instruction TLB: 4 kB pages, 32 entries, fully associative
const UINT32 lineSize = 4*KILO;
const UINT32 cacheSize = 32 * lineSize;
const UINT32 associativity = 32;
const CACHE_ALLOC::STORE_ALLOCATION allocation = CACHE_ALLOC::STORE_ALLOCATE;
const UINT32 max_sets = cacheSize / (lineSize * associativity);
const UINT32 max_associativity = associativity;
typedef CACHE_ROUND_ROBIN(max_sets, max_associativity, allocation) CACHE;
}
LOCALFUN ITLB::CACHE itlb("ITLB", ITLB::cacheSize, ITLB::lineSize, ITLB::associativity);
namespace DTLB
{
// data TLB: 4 kB pages, 32 entries, fully associative
const UINT32 lineSize = 4*KILO;
const UINT32 cacheSize = 32 * lineSize;
const UINT32 associativity = 32;
const CACHE_ALLOC::STORE_ALLOCATION allocation = CACHE_ALLOC::STORE_ALLOCATE;
const UINT32 max_sets = cacheSize / (lineSize * associativity);
const UINT32 max_associativity = associativity;
typedef CACHE_ROUND_ROBIN(max_sets, max_associativity, allocation) CACHE;
}
LOCALVAR DTLB::CACHE dtlb("DTLB", DTLB::cacheSize, DTLB::lineSize, DTLB::associativity);
namespace IL1
{
// 1st level instruction cache: 32 kB, 32 B lines, 32-way associative
const UINT32 cacheSize = 32*KILO;
const UINT32 lineSize = 32;
const UINT32 associativity = 32;
const CACHE_ALLOC::STORE_ALLOCATION allocation = CACHE_ALLOC::STORE_NO_ALLOCATE;
const UINT32 max_sets = cacheSize / (lineSize * associativity);
const UINT32 max_associativity = associativity;
typedef CACHE_ROUND_ROBIN(max_sets, max_associativity, allocation) CACHE;
}
LOCALVAR IL1::CACHE il1("L1 Instruction Cache", IL1::cacheSize, IL1::lineSize, IL1::associativity);
namespace DL1
{
// 1st level data cache: 32 kB, 32 B lines, 32-way associative
const UINT32 cacheSize = 32*KILO;
const UINT32 lineSize = 32;
const UINT32 associativity = 32;
const CACHE_ALLOC::STORE_ALLOCATION allocation = CACHE_ALLOC::STORE_NO_ALLOCATE;
const UINT32 max_sets = cacheSize / (lineSize * associativity);
const UINT32 max_associativity = associativity;
typedef CACHE_ROUND_ROBIN(max_sets, max_associativity, allocation) CACHE;
}
LOCALVAR DL1::CACHE dl1("L1 Data Cache", DL1::cacheSize, DL1::lineSize, DL1::associativity);
namespace UL2
{
// 2nd level unified cache: 2 MB, 64 B lines, direct mapped
const UINT32 cacheSize = 2*MEGA;
const UINT32 lineSize = 64;
const UINT32 associativity = 1;
const CACHE_ALLOC::STORE_ALLOCATION allocation = CACHE_ALLOC::STORE_ALLOCATE;
const UINT32 max_sets = cacheSize / (lineSize * associativity);
typedef CACHE_DIRECT_MAPPED(max_sets, allocation) CACHE;
}
LOCALVAR UL2::CACHE ul2("L2 Unified Cache", UL2::cacheSize, UL2::lineSize, UL2::associativity);
namespace UL3
{
// 3rd level unified cache: 16 MB, 64 B lines, direct mapped
const UINT32 cacheSize = 16*MEGA;
const UINT32 lineSize = 64;
const UINT32 associativity = 1;
const CACHE_ALLOC::STORE_ALLOCATION allocation = CACHE_ALLOC::STORE_ALLOCATE;
const UINT32 max_sets = cacheSize / (lineSize * associativity);
typedef CACHE_DIRECT_MAPPED(max_sets, allocation) CACHE;
}
LOCALVAR UL3::CACHE ul3("L3 Unified Cache", UL3::cacheSize, UL3::lineSize, UL3::associativity);
LOCALFUN VOID Fini(int code, VOID * v)
{
std::cerr << itlb;
std::cerr << dtlb;
std::cerr << il1;
std::cerr << dl1;
std::cerr << ul2;
std::cerr << ul3;
}
LOCALFUN VOID Ul2Access(ADDRINT addr, UINT32 size, CACHE_BASE::ACCESS_TYPE accessType)
{
// second level unified cache
const BOOL ul2Hit = ul2.Access(addr, size, accessType);
// third level unified cache
if ( ! ul2Hit) ul3.Access(addr, size, accessType);
}
LOCALFUN VOID InsRef(ADDRINT addr)
{
const UINT32 size = 1; // assuming access does not cross cache lines
const CACHE_BASE::ACCESS_TYPE accessType = CACHE_BASE::ACCESS_TYPE_LOAD;
// ITLB
itlb.AccessSingleLine(addr, accessType);
// first level I-cache
const BOOL il1Hit = il1.AccessSingleLine(addr, accessType);
// second level unified Cache
if ( ! il1Hit) Ul2Access(addr, size, accessType);
}
LOCALFUN VOID MemRefMulti(ADDRINT addr, UINT32 size, CACHE_BASE::ACCESS_TYPE accessType)
{
// DTLB
dtlb.AccessSingleLine(addr, CACHE_BASE::ACCESS_TYPE_LOAD);
// first level D-cache
const BOOL dl1Hit = dl1.Access(addr, size, accessType);
// second level unified Cache
if ( ! dl1Hit) Ul2Access(addr, size, accessType);
}
LOCALFUN VOID MemRefSingle(ADDRINT addr, UINT32 size, CACHE_BASE::ACCESS_TYPE accessType)
{
// DTLB
dtlb.AccessSingleLine(addr, CACHE_BASE::ACCESS_TYPE_LOAD);
// first level D-cache
const BOOL dl1Hit = dl1.AccessSingleLine(addr, accessType);
// second level unified Cache
if ( ! dl1Hit) Ul2Access(addr, size, accessType);
}
LOCALFUN VOID Instruction(INS ins, VOID *v)
{
// all instruction fetches access I-cache
INS_InsertCall(
ins, IPOINT_BEFORE, (AFUNPTR)InsRef,
IARG_INST_PTR,
IARG_END);
if (INS_IsMemoryRead(ins) && INS_IsStandardMemop(ins))
{
const UINT32 size = INS_MemoryReadSize(ins);
const AFUNPTR countFun = (size <= 4 ? (AFUNPTR) MemRefSingle : (AFUNPTR) MemRefMulti);
// only predicated-on memory instructions access D-cache
INS_InsertPredicatedCall(
ins, IPOINT_BEFORE, countFun,
IARG_MEMORYREAD_EA,
IARG_MEMORYREAD_SIZE,
IARG_UINT32, CACHE_BASE::ACCESS_TYPE_LOAD,
IARG_END);
}
if (INS_IsMemoryWrite(ins) && INS_IsStandardMemop(ins))
{
const UINT32 size = INS_MemoryWriteSize(ins);
const AFUNPTR countFun = (size <= 4 ? (AFUNPTR) MemRefSingle : (AFUNPTR) MemRefMulti);
// only predicated-on memory instructions access D-cache
INS_InsertPredicatedCall(
ins, IPOINT_BEFORE, countFun,
IARG_MEMORYWRITE_EA,
IARG_MEMORYWRITE_SIZE,
IARG_UINT32, CACHE_BASE::ACCESS_TYPE_STORE,
IARG_END);
}
}
GLOBALFUN int main(int argc, char *argv[])
{
PIN_Init(argc, argv);
INS_AddInstrumentFunction(Instruction, 0);
PIN_AddFiniFunction(Fini, 0);
// Never returns
PIN_StartProgram();
return 0; // make compiler happy
}