void TransactionConflictManager::notifyReceiveNack(int thread, Address physicalAddr, uint64 local_timestamp, uint64 remote_timestamp, MachineID remote_id){ bool possible_cycle = m_possible_cycle[thread]; // get the remote thread that NACKed us int remote_procnum = L1CacheMachIDToProcessorNum(remote_id); TransactionConflictManager * remote_conflict_mgr = g_system_ptr->getChip(m_chip_ptr->getID())->getTransactionInterfaceManager(remote_procnum)->getXactConflictManager(); int remote_thread = remote_conflict_mgr->getOldestThread(); int remote_logicalprocnum = remote_procnum*RubyConfig::numberofSMTThreads()+remote_thread; int my_logicalprocnum = getLogicalProcID(thread); Address myPC = SIMICS_get_program_counter(my_logicalprocnum); Address remotePC = SIMICS_get_program_counter(remote_logicalprocnum); //const char * my_instruction = SIMICS_disassemble_physical( my_logicalprocnum, SIMICS_translate_address( my_logicalprocnum, myPC )); //const char * remote_instruction = SIMICS_disassemble_physical( remote_logicalprocnum, SIMICS_translate_address( remote_logicalprocnum, remotePC )); m_nackedBy[thread][remote_logicalprocnum] = true; m_nackedByTimestamp[thread][remote_logicalprocnum] = remote_timestamp; m_magicWaitingTime[thread] = remote_timestamp; m_magicWaitingOn[thread] = remote_logicalprocnum; if (possible_cycle && isRemoteOlder(thread, remote_thread, local_timestamp, remote_timestamp, remote_id)){ m_shouldTrap[thread] = true; } if (XACT_DEBUG && (XACT_DEBUG_LEVEL > 2)){ cout << " " << g_eventQueue_ptr->getTime() << " " << getLogicalProcID(thread) << " [" << getProcID() << "," << thread << "] RECEIVED NACK " << physicalAddr << " remote_id: " << remote_logicalprocnum << " [" << remote_procnum << "," << remote_thread << "] myPC: " << myPC << " remotePC: " << remotePC << " local_timestamp: " << local_timestamp << " remote_timestamp: " << remote_timestamp << " shouldTrap " << m_shouldTrap[thread] << endl; } }
void TransactionSimicsProcessor::xactIsolationCheck(memory_transaction_t *mem_trans, CacheRequestType type){ assert(XACT_EAGER_CD); int proc_num = m_proc; Address addr = Address(mem_trans->s.physical_address); addr.makeLineAddress(); if (! g_system_ptr->getXactIsolationChecker()->checkXACTConsistency(proc_num, addr, type)){ bool isEscapedAccess = ((m_xact_mgr->getEscapeDepth(0) > 0)|| mem_trans->s.type==Sim_Trans_Instr_Fetch || PRIV_MODE); if (!isEscapedAccess){ cerr << m_proc << " XACT CONSISTENCY CHECK FAILURE DUE TO OVERLAP BETWEEN NONTRANSACTION AND TRANSACTIONS "; cerr << " Address: " << addr << " PC: " << SIMICS_get_program_counter(m_proc) << " RANDOM SEED " << g_RANDOM_SEED << " cycle " << g_eventQueue_ptr->getTime() << endl; assert(false); } else { cerr << m_proc << " XACT CONSISTENCY CHECK FAILURE DUE TO OVERLAP BETWEEN ESCAPE ACTIONS AND TRANSACTIONS "; cerr << " Address: " << addr << " PC: " << SIMICS_get_program_counter(m_proc) << " RANDOM SEED " << g_RANDOM_SEED << " cycle " << g_eventQueue_ptr->getTime() << endl; } } int xact_level = m_xact_mgr->getTransactionLevel(0); switch(type){ case CacheRequestType_ST_XACT: case CacheRequestType_LDX_XACT: g_system_ptr->getXactIsolationChecker()->addToWriteSet(proc_num, addr, xact_level); break; case CacheRequestType_LD_XACT: g_system_ptr->getXactIsolationChecker()->addToReadSet(proc_num, addr, xact_level); break; default: ; } }
void dump_registers(conf_object_t *cpu) { const char* reg_names[] = { "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7", "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "o0", "o1", "o2", "o3", "o4", "o5", "o6", "o7", "ccr", "pc", "npc" }; printf("Registers for %s\n", cpu->name); printf("------------------\n"); for (int i = 0; i < (sizeof(reg_names) / sizeof(char*)); i++) { const char* reg_name = reg_names[i]; printf(" %3s: 0x%016llx\n", reg_name, read_reg(cpu, reg_name)); if (i % 8 == 7) { printf("\n"); } } int myID = SIMICS_get_proc_no(cpu); Address myPC = SIMICS_get_program_counter(myID); physical_address_t myPhysPC = SIMICS_translate_address(myID, myPC); integer_t myInst = SIMICS_read_physical_memory(myID, myPhysPC, 4); const char *myInstStr = SIMICS_disassemble_physical(myID, myPhysPC); printf("\n *pc: 0x%llx: %s\n", myInst, myInstStr); printf("\n\n"); }
void TransactionSimicsProcessor::updateStoreSetPredictor(CacheRequestType type, Address address) { assert(XACT_EAGER_CD); if(type == CacheRequestType_LD_XACT){ m_xact_mgr->addToLoadAddressMap(0, SIMICS_get_program_counter(m_proc).getAddress(), address.getAddress()); } else if (type == CacheRequestType_ST_XACT){ m_xact_mgr->updateStorePredictor(0, address.getAddress()); } }
/** * SimicsProcessor about to issue a memory request to the cache coherence protocol. * Update Store Set Predictor * Issue coherence request for log block if necessary. * * Return Values * 0: Not Ready * 1: Not Ready - Summary conflict * 2: Ready */ unsigned int TransactionSimicsProcessor::startingMemRef(memory_transaction_t *mem_trans, CacheRequestType type) { Address logicalAddress = Address(mem_trans->s.logical_address); logicalAddress.makeLineAddress(); if (XACT_ENABLE_VIRTUALIZATION_LOGTM_SE) { SimicsDriver* simics_interface_ptr = static_cast<SimicsDriver*>(g_system_ptr->getDriver()); Address conflictAddress; bool isEscapeAction, request_is_read; unsigned int conflictType; if (type == CacheRequestType_LDX_XACT || type == CacheRequestType_ST_XACT || type == CacheRequestType_ST || type == CacheRequestType_ATOMIC) { request_is_read = false; } else { request_is_read = true; } conflictAddress = Address(mem_trans->s.physical_address); isEscapeAction = (m_xact_mgr->getEscapeDepth(0) > 0)|| mem_trans->s.type==Sim_Trans_Instr_Fetch || PRIV_MODE; if (!isEscapeAction && (conflictType = simics_interface_ptr->getHypervisor()->existSummarySignatureConflict(conflictAddress, request_is_read, m_xact_mgr))) { if (XACT_DEBUG && XACT_DEBUG_LEVEL > 1) { cout << g_eventQueue_ptr->getTime() << " " << m_proc << " [" << m_proc / RubyConfig::numberofSMTThreads() << "," << m_proc % RubyConfig::numberofSMTThreads() << "]" << " SUMMARY CONFLICT TYPE " << conflictType << " VA " << Address(mem_trans->s.logical_address) << " PA " << Address(mem_trans->s.physical_address) << " PC " << SIMICS_get_program_counter(m_proc) << endl; } m_xact_mgr->setSummaryConflictFlag(0, conflictAddress); m_xact_mgr->getXactIsolationManager()->setSummaryConflictAddress(conflictAddress); m_xact_mgr->getXactIsolationManager()->setSummaryConflictType(conflictType); return 1; } } if (m_xact_mgr->magicWait(0)) return 0; if (XACT_EAGER_CD) { updateStoreSetPredictor(type, logicalAddress); } if (!XACT_LAZY_VM){ if((type == CacheRequestType_ST_XACT) || (type == CacheRequestType_LDX_XACT)){ bool addEntry = m_xact_mgr->getXactVersionManager()->shouldLog(0, logicalAddress, m_xact_mgr->getTransactionLevel(0) ); if(addEntry) if (generateLogRequest(mem_trans) == false) return 0; } } return 2; }
bool TransactionSimicsProcessor::generateLogRequest(memory_transaction_t *mem_trans) { assert(mem_trans->s.may_stall); assert((m_outstandingXactStoreRefCount == 0)); assert(!XACT_LAZY_VM); if (XACT_ENABLE_TOURMALINE) return true; Address logBlockAddressPhy = m_xact_mgr->getXactVersionManager()->getLogPointerAddressPhysical(0); Address logBlockAddressVirt = m_xact_mgr->getXactVersionManager()->getLogPointerAddress(0); logBlockAddressPhy.makeLineAddress(); logBlockAddressVirt.makeLineAddress(); CacheMsg logMsg(logBlockAddressPhy, logBlockAddressPhy, CacheRequestType_ST, SIMICS_get_program_counter(mem_trans->s.ini_ptr), AccessModeType_UserMode, RubyConfig::dataBlockBytes(), PrefetchBit_No, 0, logBlockAddressVirt, 0, m_xact_mgr->getXactConflictManager()->getTimestamp(0), 1 // Log Blocks are escaped accesses by default, ); // check if Ruby is ready to accept requests if (m_sequencer->isReady(logMsg) == false) { DEBUG_MSG(SEQUENCER_COMP,MedPrio, "Sequencer was NOT READY"); cerr << "Sequencer for " << m_proc << " is not ready to handle logging request! " << endl; return false; } // Wait for both the program store and LOG store to complete // before unstalling SIMICS m_outstandingXactStoreRefCount = 2; m_sequencer->makeRequest(logMsg); return true; }
/** * SimicsProcessor is ready to retire the memory reference */ void TransactionSimicsProcessor::readyToRetireMemRef(bool success, memory_transaction_t *mem_trans, CacheRequestType type) { if (0 && XACT_DEBUG && XACT_DEBUG_LEVEL > 2) { if (m_xact_mgr->inTransaction(0)) cout << g_eventQueue_ptr->getTime() << " " << m_proc << " [" << m_proc / RubyConfig::numberofSMTThreads() << "," << m_proc % RubyConfig::numberofSMTThreads() << "] READY TO RETIRE MEM REF" << Address(mem_trans->s.physical_address) << " type " << type << " PC = " << SIMICS_get_program_counter(m_proc) << endl; } if (!success && !XACT_LAZY_VM) { conf_object_t* cpu_obj = (conf_object_t*) SIM_proc_no_2_ptr(m_proc); uinteger_t intr_receive = SIM_read_register(cpu_obj, SIM_get_register_number(cpu_obj, "intr_receive")); uinteger_t intr_receive_busy_flag = (intr_receive & 0x20) >> 5; if (intr_receive_busy_flag) { // There is a pending interrupt and we are stalling SIMICS. How unfortunate! // SIMICS would not take the interrupt until we unstall this conflicting memory request! m_xact_mgr->setInterruptTrap(0); return; } }
void TransactionSimicsProcessor::processLogStore(memory_transaction_t *mem_trans, CacheRequestType type) { assert(!XACT_LAZY_VM); if (type == CacheRequestType_LDX_XACT || type == CacheRequestType_ST_XACT){ Address phys_addr = Address(mem_trans->s.physical_address); Address logical_addr = Address(mem_trans->s.logical_address); phys_addr.makeLineAddress(); logical_addr.makeLineAddress(); bool shouldLog = m_xact_mgr->getXactVersionManager()->shouldLog(0, logical_addr, m_xact_mgr->getTransactionLevel(0)); if (XACT_DEBUG && XACT_DEBUG_LEVEL > 2) { cout << g_eventQueue_ptr->getTime() << " " << m_proc << " [" << m_proc / RubyConfig::numberofSMTThreads() << "," << m_proc % RubyConfig::numberofSMTThreads() << "] LOGGING STORE: " << logical_addr << " " << shouldLog << " PC = " << SIMICS_get_program_counter(m_proc) << endl; } if (shouldLog){ // LOG XACT STORES m_xact_mgr->getXactVersionManager()->addUndoLogEntry(0, logical_addr, phys_addr); } } else if (((type == CacheRequestType_ST) || (type == CacheRequestType_ATOMIC)) && m_xact_mgr->inLoggedException(0) && (m_xact_mgr->getTransactionLevel(0) > 0)){ Address phys_addr = Address(mem_trans->s.physical_address); Address logical_addr = Address(mem_trans->s.logical_address); phys_addr.makeLineAddress(); logical_addr.makeLineAddress(); bool shouldLog = m_xact_mgr->getXactVersionManager()->shouldLog(0, logical_addr, m_xact_mgr->getTransactionLevel(0)); if (XACT_DEBUG && XACT_DEBUG_LEVEL > 2) { cout << g_eventQueue_ptr->getTime() << " " << m_proc << " [" << m_proc / RubyConfig::numberofSMTThreads() << "," << m_proc % RubyConfig::numberofSMTThreads() << "] LOGGING STORE: " << logical_addr << " " << shouldLog << " PC = " << SIMICS_get_program_counter(m_proc) << endl; } if (shouldLog){ // LOG SPILL STORES m_xact_mgr->getXactVersionManager()->addUndoLogEntry(0, logical_addr, phys_addr); } } }
/** Ruby has either * 1) obtained the necessary cache permissions for the block or * 2) failed to acquire necessary cache permissions due to transactional conflicts * Isolate transactional blocks, if successful. * Unstall SIMICS * * If TOURMALINE, need to do all conflict checks here. * - If retry, do not unstall simics */ void TransactionSimicsProcessor::completedMemRef(bool success, CacheRequestType type, Address physicalAddress, Address logicalAddress) { if (success) { int transactionLevel = m_xact_mgr->getTransactionLevel(0); switch (type) { case CacheRequestType_ST: m_xact_mgr->profileStore(0, logicalAddress, physicalAddress, transactionLevel); break; case CacheRequestType_LD: m_xact_mgr->profileLoad(0, logicalAddress, physicalAddress, transactionLevel); break; default: break; } // REDIRECT WRITE BUFFER REQUESTS if (XACT_LAZY_VM && type == CacheRequestType_ST_XACT){ if ((XACT_EAGER_CD && g_system_ptr->getXactCommitArbiter()->existCommitTokenRequest(m_proc)) || (!XACT_EAGER_CD && g_system_ptr->getXactCommitArbiter()->getTokenOwner() == m_proc)) { m_xact_mgr->getXactLazyVersionManager()->hitCallback(0, physicalAddress); return; } } if (m_xact_mgr->inTransaction(0)) { addToReadWriteSets(type, physicalAddress, logicalAddress); } } // UNSTALL SIMICS if (m_outstandingXactStoreRefCount > 0) m_outstandingXactStoreRefCount -= 1; if (m_outstandingXactStoreRefCount == 0) { int firstAccessCost = computeFirstXactAccessCost(type, physicalAddress); if (!success) firstAccessCost = 0; SIMICS_unstall_proc(m_proc, firstAccessCost); } if (0 && XACT_DEBUG && XACT_DEBUG_LEVEL > 2) { if (m_xact_mgr->inTransaction(0)) cout << g_eventQueue_ptr->getTime() << " " << m_proc << " [" << m_proc / RubyConfig::numberofSMTThreads() << "," << m_proc % RubyConfig::numberofSMTThreads() << "] COMPLETED MEM REF" << physicalAddress << " type " << type << " PC = " << SIMICS_get_program_counter(m_proc) << endl; } }
bool TransactionSimicsProcessor::tourmalineExistGlobalConflict(CacheRequestType type, Address physicalAddress) { bool existConflict = false; switch (type) { case CacheRequestType_IFETCH: case CacheRequestType_LD: case CacheRequestType_LD_XACT: if (m_xact_mgr->existGlobalLoadConflict(0, physicalAddress)) existConflict = true; break; case CacheRequestType_ST: case CacheRequestType_ST_XACT: case CacheRequestType_LDX_XACT: case CacheRequestType_ATOMIC: if (m_xact_mgr->existGlobalStoreConflict(0, physicalAddress)) existConflict = true; break; default: break; } if (existConflict) { if (XACT_DEBUG && XACT_DEBUG_LEVEL > 2) { cout << g_eventQueue_ptr->getTime() << " " << m_proc << " [" << m_proc / RubyConfig::numberofSMTThreads() << "," << m_proc % RubyConfig::numberofSMTThreads() << "] TOURMALINE CONFLICT " << physicalAddress << " PC = " << SIMICS_get_program_counter(m_proc) << endl; } } return existConflict; }