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: 
           ;    
  }
}
Exemple #3
0
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;      
}