Ejemplo n.º 1
0
const char *asm_s(instruction_id_t ii)
{
    tuple_int_string_t *tuple;
    attr_value_t pc;

    pc = SIM_instruction_read_input_reg(ii, V9_Reg_Id_PC);
    if (pc.kind != Sim_Val_Integer) {
        SIM_clear_exception();
        return "<unknown pc>";
    }

    SIM_clear_exception();
    tuple = SIM_disassemble(SIM_instruction_cpu(ii), (logical_address_t)pc.u.integer, 1);
    if (SIM_get_pending_exception()) {
        SIM_clear_exception();
        return "<disass error>";
    }

    vtsprintf(tmp_buf, "<0x%016llx> %s", (logical_address_t)pc.u.integer, tuple->string);

    return (const char *)tmp_buf;
}
Ejemplo n.º 2
0
//**************************************************************************
void
control_inst_t::Retire( abstract_pc_t *a )
{
  #ifdef DEBUG_DYNAMIC_RET
  DEBUG_OUT("control_inst_t:Retire BEGIN, proc[%d]\n",m_proc);
  #endif

  #ifdef DEBUG_DYNAMIC
  char buf[128];
  s->printDisassemble(buf);
  DEBUG_OUT("\tcontrol_inst_t::Retire BEGIN %s seq_num[ %lld ] cycle[ %lld ] fetchPC[ 0x%llx ] fetchNPC[ 0x%llx ] PredictedPC[ 0x%llx ] PredictedNPC[ 0x%llx ]\n", buf, seq_num, m_pseq->getLocalCycle(), m_actual.pc, m_actual.npc, m_predicted.pc, m_predicted.npc);
     for(int i=0; i < SI_MAX_DEST; ++i){
       reg_id_t & dest = getDestReg(i);
       reg_id_t & tofree = getToFreeReg(i);
       if( !dest.isZero() ){
         DEBUG_OUT("\tDest[ %d ] Vanilla[ %d ] Physical[ %d ] Arf[ %s ] ToFree: Vanilla[ %d ] physical[ %d ] Arf[ %s ]\n", i, dest.getVanilla(), dest.getPhysical(), dest.rid_type_menomic( dest.getRtype() ), tofree.getVanilla(), tofree.getPhysical(), tofree.rid_type_menomic( tofree.getRtype() ) );
       }
     }
  #endif

  ASSERT( !getEvent( EVENT_FINALIZED ) );
  STAT_INC( m_pseq->m_stat_control_retired[m_proc] );
  
  // Need this bc we place fetch barrier on retry instead of stxa:
  if ( (s->getOpcode() == i_retry) || (s->getFlag( SI_FETCH_BARRIER)) ) {
    // if we have a branch misprediction, we already unstalled the fetch in partialSquash():
    if(getEvent(EVENT_BRANCH_MISPREDICT) == false){
      m_pseq->unstallFetch(m_proc);   
    }
  }

  STAT_INC( m_pseq->m_branch_seen_stat[s->getBranchType()][2] );
  STAT_INC( m_pseq->m_branch_seen_stat[s->getBranchType()][m_priv? 1:0] );

  // record when execution takes place
  m_event_times[EVENT_TIME_RETIRE] = m_pseq->getLocalCycle() - m_fetch_cycle;
  
  // update dynamic branch prediction (predicated) instruction statistics
  static_inst_t *s_instr = getStaticInst();
  if (s_instr->getType() == DYN_CONTROL) {
    uint32 inst;
    int    op2;
    int    pred;
    switch (s_instr->getBranchType()) {
    case BRANCH_COND:
      // conditional branch
      STAT_INC( m_pseq->m_nonpred_retire_count_stat[m_proc] );
      break;
      
    case BRANCH_PCOND:
      // predictated conditional
      inst = s_instr->getInst();
      op2  = maskBits32( inst, 22, 24 );
      pred = maskBits32( inst, 19, 19 );
      if ( op2 == 3 ) {
        // integer register w/ predication
        STAT_INC( m_pseq->m_pred_reg_retire_count_stat[m_proc] );
        if (pred) {
          STAT_INC( m_pseq->m_pred_reg_retire_taken_stat[m_proc] );
        } else {
          STAT_INC( m_pseq->m_pred_reg_retire_nottaken_stat[m_proc] );
        }
      } else {
        STAT_INC( m_pseq->m_pred_retire_count_stat[m_proc] );
        if (pred) {
          STAT_INC( m_pseq->m_pred_retire_count_taken_stat[m_proc] );
        } else {
          STAT_INC( m_pseq->m_pred_retire_count_nottaken_stat[m_proc] );
        }
      }
      if (pred == true && m_isTaken == false ||
          pred == false && m_isTaken == true) {
        STAT_INC( m_pseq->m_branch_wrong_static_stat );
      }
      break;
      
    default:
      ;      // ignore non-predictated branches
    }
  }

#ifdef DEBUG_RETIRE
  m_pseq->out_info("## Control Retire Stage\n");
  printDetail();
  m_pseq->printPC( &m_actual );
#endif


  bool mispredict = (m_events & EVENT_BRANCH_MISPREDICT);
  if (mispredict) {

    // incorrect branch prediction
    STAT_INC( m_pseq->m_branch_wrong_stat[s->getBranchType()][2] );
    STAT_INC( m_pseq->m_branch_wrong_stat[s->getBranchType()][m_priv? 1:0] );

    //train BRANCH_PRIV predictor
    if( (s->getBranchType() == BRANCH_PRIV) ){
      if (m_predicted.cwp != m_actual.cwp) {
        m_pseq->getRegstatePred()->update(getVPC(), CONTROL_CWP, m_actual.cwp, m_predicted.cwp);
      }
      if (m_predicted.tl != m_actual.tl) {
        m_pseq->getRegstatePred()->update(getVPC(), CONTROL_TL, m_actual.tl, m_predicted.tl);
      }
      if (m_predicted.pstate != m_actual.pstate) {
        m_pseq->getRegstatePred()->update(getVPC(), CONTROL_PSTATE, m_actual.pstate, m_predicted.pstate);
      }
    }

    //****************************** print out mispredicted inst *****************
    if(s->getBranchType() == BRANCH_PRIV){
      char buf[128];
      s->printDisassemble( buf );
      bool imm = s->getFlag(SI_ISIMMEDIATE); 
      #if 0
        if(m_predicted.pc != m_actual.pc){
          m_pseq->out_info("CONTROLOP: PC mispredict: predicted[ 0x%llx ] actual[ 0x%llx ] type=%s seqnum[ %lld ]  VPC[ 0x%llx ] PC[ 0x%llx ] fetched[ %lld ] executed[ %lld ] correctPC[ 0x%llx ] imm[ %d ] %s\n",
                           m_predicted.pc, m_actual.pc, pstate_t::branch_type_menomic[s->getBranchType()], seq_num, getVPC(), getPC(), m_fetch_cycle, m_event_times[EVENT_TIME_EXECUTE] + m_fetch_cycle, m_actual.pc, imm, buf);
        }
      #endif
      #if 0
        if(m_predicted.npc != m_actual.npc){
          m_pseq->out_info("CONTROLOP: NPC mispredict: predicted[ 0x%llx ] actual[ 0x%llx ] type=%s seqnum[ %lld ]  VPC[ 0x%llx ] PC[ 0x%llx ] fetched[ %lld ] executed[ %lld ] correctPC[ 0x%llx ] imm[ %d ] %s\n",
                           m_predicted.npc, m_actual.npc, pstate_t::branch_type_menomic[s->getBranchType()], seq_num, getVPC(), getPC(), m_fetch_cycle, m_event_times[EVENT_TIME_EXECUTE] + m_fetch_cycle, m_actual.pc, imm, buf);
        }
      #endif
      #if 0
        if (m_predicted.cwp != m_actual.cwp) {
          m_pseq->out_info("CONTROLOP: CWP mispredict: predicted[ %d ] actual[ %d ] type=%s seqnum[ %lld ]  VPC[ 0x%llx ] PC[ 0x%llx ] fetched[ %lld ] executed[ %lld ] correctPC[ 0x%llx ] imm[ %d ] %s\n",
                           m_predicted.cwp, m_actual.cwp, pstate_t::branch_type_menomic[s->getBranchType()], seq_num, getVPC(), getPC(), m_fetch_cycle, m_event_times[EVENT_TIME_EXECUTE] + m_fetch_cycle, m_actual.pc, imm, buf);
        }
      #endif
      #if 0
        if (m_predicted.tl != m_actual.tl) {
          m_pseq->out_info("CONTROLOP: TL mispredict: predicted[ %d ] actual[ %d ] type=%s seqnum[ %lld ] VPC[ 0x%llx ] PC[ 0x%llx ] fetched[ %lld ] executed[ %lld ] correctPC[ 0x%llx ] imm[ %d ] %s\n",
                           m_predicted.tl, m_actual.tl, pstate_t::branch_type_menomic[s->getBranchType()], seq_num, getVPC(), getPC(), m_fetch_cycle, m_event_times[EVENT_TIME_EXECUTE] + m_fetch_cycle, m_actual.pc, imm, buf);
        }
      #endif
      #if 0
        if (m_predicted.pstate != m_actual.pstate) {
          m_pseq->out_info("CONTROLOP: PSTATE mispredict: predicted[ 0x%0x ] actual[ 0x%0x ] type=%s seqnum[ %lld ] VPC[ 0x%llx ] PC[ 0x%llx ] fetched[ %lld ] executed[ %lld ] correctPC[ 0x%llx ] imm[ %d ] %s\n",
                           m_predicted.pstate, m_actual.pstate, pstate_t::branch_type_menomic[s->getBranchType()], seq_num, getVPC(), getPC(), m_fetch_cycle,  m_event_times[EVENT_TIME_EXECUTE] + m_fetch_cycle, m_actual.pc, imm, buf);
        }
      #endif
    }
    //**************************************************************************

    // train ras's exception table
    if (ras_t::EXCEPTION_TABLE && s->getBranchType() == BRANCH_RETURN) {
      my_addr_t tos;
      ras_t *ras = m_pseq->getRAS(m_proc);    
      ras->getTop(&(m_pred_state.ras_state), &tos);
      if(tos == m_actual.npc) {
        ras->markException(m_predicted.npc);
        // update RAS state
        ras->pop(&(m_pred_state.ras_state));
        m_pseq->setSpecBPS(m_pred_state);
        if (ras_t::DEBUG_RAS) m_pseq->out_info("*********** DEBUG_RAS ***********\n");
      } else {
        ras->unmarkException(m_actual.npc);
      }
    }

    // XU DEBUG
    if (0 && s->getBranchType() == BRANCH_RETURN) {
      m_pseq->out_info("**** %c:mispred 0x%llx, pred 0x%llx target 0x%llx, "
                       "next %d TOS %d\n", m_priv? 'K':'U', getVPC(),
                       m_predicted.npc, m_actual.npc,
                       m_pred_state.ras_state.next_free,
                       m_pred_state.ras_state.TOS);

      // print 5 instr after mis-pred
      generic_address_t addr = m_predicted.npc-8;
      for(uint32 i = 0; i < 5; i++, addr+=4) {
        //get the actual seq number for the pointer to m_state:
        int32 seq_num = m_pseq->getID() / CONFIG_LOGICAL_PER_PHY_PROC;
        assert(seq_num >= 0 && seq_num < system_t::inst->m_numSMTProcs);
             
        tuple_int_string_t *disassemble = SIM_disassemble((processor_t *) system_t::inst->m_state[seq_num]->getSimicsProcessor(m_proc), addr, /* logical */ 1);
        if (disassemble) m_pseq->out_info("     %s\n", disassemble->string);
      }
    }
  } else {
    // correct or no prediction
    STAT_INC( m_pseq->m_branch_right_stat[s->getBranchType()][2] );
    STAT_INC( m_pseq->m_branch_right_stat[s->getBranchType()][m_priv? 1:0] );
  }

  /* update branch predictor tables at retirement */
  if (s->getBranchType() == BRANCH_COND ||
      s->getBranchType() == BRANCH_PCOND) {
    m_pseq->getDirectBP()->Update(getVPC(),
                                  (m_pseq->getArchBPS()->cond_state),
                                  s->getFlag( SI_STATICPRED ),
                                  m_isTaken, m_proc);

  } else if (s->getBranchType() == BRANCH_INDIRECT ||
             (s->getBranchType() == BRANCH_CALL && s->getOpcode() != i_call) ) {
    // m_actual.npc is the indirect target
    m_pseq->getIndirectBP()->Update( getVPC(),
                                     &(m_pseq->getArchBPS()->indirect_state),
                                     m_actual.npc, m_proc );
  }

  m_pseq->setArchBPS(m_pred_state);
  
  // no need to update call&return, since we used checkpointed RAS
  // no update on traps right now
  SetStage(RETIRE_STAGE);

  /* retire any register overwritten by link register */
  retireRegisters(); 

  #if 0
  if(m_actual.pc == (my_addr_t) -1){
    char buf[128];
    s->printDisassemble(buf);
    ERROR_OUT("\tcontrol_inst_t::Retire %s seq_num[ %lld ] cycle[ %lld ] fetchPC[ 0x%llx ] fetchNPC[ 0x%llx ] fetched[ %lld ] executed[ %lld ]\n", buf, seq_num, m_pseq->getLocalCycle(), m_actual.pc, m_actual.npc, m_fetch_cycle, m_fetch_cycle+getEventTime(EVENT_TIME_EXECUTE_DONE));
    //print out writer cycle
    for(int i=0; i < SI_MAX_SOURCE; ++i){
      reg_id_t & source = getSourceReg(i);
      if(!source.isZero()){
        uint64 written_cycle = source.getARF()->getWrittenCycle( source, m_proc );
        uint64 writer_seqnum = source.getARF()->getWriterSeqnum( source, m_proc );
        ERROR_OUT("\tSource[ %d ] Vanilla[ %d ] Physical[ %d ] Arf[ %s ] written_cycle[ %lld ] writer_seqnum[ %lld ]\n", i, source.getVanilla(), source.getPhysical(), source.rid_type_menomic( source.getRtype() ), written_cycle, writer_seqnum);
      }
    }
  }
  #endif

  ASSERT( m_actual.pc != (my_addr_t) -1 );

  /* return pc, npc pair which are the results of execution */
  a->pc  = m_actual.pc;
  a->npc = m_actual.npc;
 
  markEvent( EVENT_FINALIZED );

  #ifdef DEBUG_DYNAMIC_RET
     DEBUG_OUT("control_inst_t:Retire END, proc[%d]\n",m_proc);
  #endif
}