int main(int argc, char *argv[]) { PIN_InitSymbols(); if( PIN_Init(argc,argv) ) { return Usage(); } outFile.open(KnobOutputFile.Value().c_str()); dl1 = new DL1::CACHE("L1 Data Cache", KnobCacheSize.Value() * KILO, KnobLineSize.Value(), KnobAssociativity.Value()); profile.SetKeyName("iaddr "); profile.SetCounterName("dcache:miss dcache:hit"); COUNTER_HIT_MISS threshold; threshold[COUNTER_HIT] = KnobThresholdHit.Value(); threshold[COUNTER_MISS] = KnobThresholdMiss.Value(); profile.SetThreshold( threshold ); INS_AddInstrumentFunction(Instruction, 0); PIN_AddFiniFunction(Fini, 0); // Never returns PIN_StartProgram(); return 0; }
VOID Fini(int code, VOID * v) { std::ofstream out(KnobOutputFile.Value().c_str()); // print D-cache profile // @todo what does this print out << "PIN:MEMLATENCIES 1.0. 0x0\n"; out << "#\n" "# DCACHE stats\n" "#\n"; out << dl1->StatsLong("# ", CACHE_BASE::CACHE_TYPE_DCACHE); if( KnobTrackLoads || KnobTrackStores ) { out << "#\n" "# LOAD stats\n" "#\n"; out << profile.StringLong(); } out.close(); }
VOID Instruction(INS ins, void * v) { UINT32 memOperands = INS_MemoryOperandCount(ins); // Instrument each memory operand. If the operand is both read and written // it will be processed twice. // Iterating over memory operands ensures that instructions on IA-32 with // two read operands (such as SCAS and CMPS) are correctly handled. for (UINT32 memOp = 0; memOp < memOperands; memOp++) { const UINT32 size = INS_MemoryOperandSize(ins, memOp); const BOOL single = (size <= 4); if (INS_MemoryOperandIsRead(ins, memOp)) { if( KnobTrackLoads ) { // map sparse INS addresses to dense IDs const ADDRINT iaddr = INS_Address(ins); const UINT32 instId = profile.Map(iaddr); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingle, IARG_MEMORYOP_EA, memOp, IARG_UINT32, instId, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMulti, IARG_MEMORYOP_EA, memOp, IARG_UINT32, size, IARG_UINT32, instId, IARG_END); } } else { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingleFast, IARG_MEMORYOP_EA, memOp, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMultiFast, IARG_MEMORYOP_EA, memOp, IARG_UINT32, size, IARG_END); } } } if (INS_MemoryOperandIsWritten(ins, memOp)) { if( KnobTrackStores ) { const ADDRINT iaddr = INS_Address(ins); const UINT32 instId = profile.Map(iaddr); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingle, IARG_MEMORYOP_EA, memOp, IARG_UINT32, instId, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMulti, IARG_MEMORYOP_EA,memOp, IARG_UINT32, size, IARG_UINT32, instId, IARG_END); } } else { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingleFast, IARG_MEMORYOP_EA, memOp, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMultiFast, IARG_MEMORYOP_EA, memOp, IARG_UINT32, size, IARG_END); } } } } }
VOID Instruction(INS ins, void * v) { if (INS_IsMemoryRead(ins) && INS_IsStandardMemop(ins)) { // map sparse INS addresses to dense IDs const ADDRINT iaddr = INS_Address(ins); const UINT32 instId = profile.Map(iaddr); const UINT32 size = INS_MemoryReadSize(ins); const BOOL single = (size <= 4); if( KnobTrackLoads ) { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingle, IARG_MEMORYREAD_EA, IARG_UINT32, instId, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMulti, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, instId, IARG_END); } } else { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadSingleFast, IARG_MEMORYREAD_EA, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) LoadMultiFast, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } } } if ( INS_IsMemoryWrite(ins) && INS_IsStandardMemop(ins)) { // map sparse INS addresses to dense IDs const ADDRINT iaddr = INS_Address(ins); const UINT32 instId = profile.Map(iaddr); const UINT32 size = INS_MemoryWriteSize(ins); const BOOL single = (size <= 4); if( KnobTrackStores ) { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingle, IARG_MEMORYWRITE_EA, IARG_UINT32, instId, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMulti, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_UINT32, instId, IARG_END); } } else { if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingleFast, IARG_MEMORYWRITE_EA, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMultiFast, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } } } }