#ifdef SYSTEMC /* * $Id: Commit_unit_genMealy_retire.cpp 139 2010-07-30 14:47:27Z rosiere $ * * [ Description ] * */ #include "Behavioural/Core/Multi_OOO_Engine/OOO_Engine/Commit_unit/include/Commit_unit.h" namespace morpheo { namespace behavioural { namespace core { namespace multi_ooo_engine { namespace ooo_engine { namespace commit_unit { #undef FUNCTION #define FUNCTION "Commit_unit::genMealy_retire" void Commit_unit::genMealy_retire (void) { log_begin(Commit_unit,FUNCTION); log_function(Commit_unit,FUNCTION,_name.c_str()); if (PORT_READ(in_NRESET)) { Tcontrol_t retire_val [_param->_nb_rename_unit][_param->_max_nb_inst_retire]; uint32_t num_inst_retire [_param->_nb_rename_unit]; bool can_retire [_param->_nb_rename_unit]; Tcontrol_t spr_write_val [_param->_nb_front_end][_param->_max_nb_context]; Tcontrol_t spr_write_sr_f_val [_param->_nb_front_end][_param->_max_nb_context]; Tcontrol_t spr_write_sr_f [_param->_nb_front_end][_param->_max_nb_context]; Tcontrol_t spr_write_sr_cy_val [_param->_nb_front_end][_param->_max_nb_context]; Tcontrol_t spr_write_sr_cy [_param->_nb_front_end][_param->_max_nb_context]; Tcontrol_t spr_write_sr_ov_val [_param->_nb_front_end][_param->_max_nb_context]; Tcontrol_t spr_write_sr_ov [_param->_nb_front_end][_param->_max_nb_context]; // Initialisation for (uint32_t i=0; i<_param->_nb_bank; i++) internal_BANK_RETIRE_VAL [i] = false; for (uint32_t i=0; i<_param->_nb_rename_unit; i++) { num_inst_retire [i] = 0; can_retire [i] = true ; for (uint32_t j=0; j<_param->_nb_inst_retire[i]; j++) retire_val [i][j] = false; } for (uint32_t i=0; i<_param->_nb_front_end; ++i) for (uint32_t j=0; j<_param->_nb_context[i]; ++j) { spr_write_val [i][j] = 0; spr_write_sr_f_val [i][j] = 0; spr_write_sr_cy_val [i][j] = 0; spr_write_sr_ov_val [i][j] = 0; spr_write_sr_f [i][j] = 0; // not necessary spr_write_sr_cy [i][j] = 0; // not necessary spr_write_sr_ov [i][j] = 0; // not necessary // Init internal update table // Test if an event occure // bool event = (PORT_READ(in_RETIRE_EVENT_STATE [i][j]) != EVENT_STATE_NO_EVENT); bool reset_update_table = (commit_event_state_to_event_state(reg_EVENT_STATE[i][j]) == EVENT_STATE_EVENT); log_printf(TRACE,Register_Address_Translation_unit,FUNCTION," * reset_update_table : %d",reset_update_table); // not event -> update_table == 1 -> always update // event -> update_table and not reset for (uint32_t k=0; k<_param->_nb_general_register_logic; ++k) internal_rat_gpr_update_table [i][j][k] = // not event or (not reset_update_table and rat_gpr_update_table [i][j][k]); for (uint32_t k=0; k<_param->_nb_special_register_logic; ++k) internal_rat_spr_update_table [i][j][k] = // not event or (not reset_update_table and rat_spr_update_table [i][j][k]); } // Scan Top of each bank internal_BANK_RETIRE_HEAD = reg_NUM_BANK_HEAD; for (uint32_t i=0; i<_param->_nb_bank; i++) { uint32_t num_bank = (internal_BANK_RETIRE_HEAD+i)%_param->_nb_bank; log_printf(TRACE,Commit_unit,FUNCTION," * BANK [%d]",num_bank); // Test if have instruction if (not _rob[num_bank].empty()) { // Scan all instruction in windows and test if instruction is speculative entry_t * entry = _rob [num_bank].front(); uint32_t x = entry->rename_unit_id; uint32_t y = num_inst_retire [x]; log_printf(TRACE,Commit_unit,FUNCTION," * num_rename_unit : %d",x); log_printf(TRACE,Commit_unit,FUNCTION," * num_inst_retire : %d",y); if (y < _param->_nb_inst_retire [x]) { #ifdef DEBUG_TEST if (x >= _param->_nb_rename_unit) throw ERRORMORPHEO(FUNCTION,toString(_("Invalid rename_unit number (%d, max is %d).\n"),x,_param->_nb_rename_unit)); #endif bool bypass= false; log_printf(TRACE,Commit_unit,FUNCTION," * can_retire : %d",can_retire [x]); log_printf(TRACE,Commit_unit,FUNCTION," * RETIRE_ACK : %d",PORT_READ(in_RETIRE_ACK [x][y])); // test if : // * can retire (all previous instruction is retired) // * all structure is ok (not busy) if (can_retire [x] and // in-order PORT_READ(in_RETIRE_ACK [x][y])) // not busy { log_printf(TRACE,Commit_unit,FUNCTION," * valid !!!"); rob_state_t state = entry->state; Tcontext_t front_end_id = entry->front_end_id; Tcontext_t context_id = entry->context_id; log_printf(TRACE,Commit_unit,FUNCTION," * state : %s",toString(state).c_str()); log_printf(TRACE,Commit_unit,FUNCTION," * front_end_id : %d",front_end_id); log_printf(TRACE,Commit_unit,FUNCTION," * context_id : %d",context_id ); if ((state == ROB_END_OK ) or (state == ROB_END_KO ) or (state == ROB_END_BRANCH_MISS) or (state == ROB_END_LOAD_MISS ) or (state == ROB_END_MISS )// or // (state == ROB_END_EXCEPTION) ) { Tcontrol_t write_rd = entry->write_rd; Tcontrol_t write_re = entry->write_re; Tgeneral_address_t num_reg_rd_log = entry->num_reg_rd_log; Tspecial_address_t num_reg_re_log = entry->num_reg_re_log; // if state is ok, when write flags in the SR regsiters bool spr_write_ack = true; // Write in SR the good flag if ((state == ROB_END_OK ) and write_re) // ROB_END_BRANCH_MISS is a valid branch instruction but don't modify RE { log_printf(TRACE,Commit_unit,FUNCTION," * need write SR flags"); log_printf(TRACE,Commit_unit,FUNCTION," * SPR_WRITE_ACK : %d",PORT_READ(in_SPR_WRITE_ACK [front_end_id][context_id])); spr_write_ack = PORT_READ(in_SPR_WRITE_ACK [front_end_id][context_id]); // retire_ack is set !!! spr_write_val [front_end_id][context_id] = 1; Tspecial_data_t flags = entry->flags; switch (num_reg_re_log) { case SPR_LOGIC_SR_F : { spr_write_sr_f_val [front_end_id][context_id] = 1; spr_write_sr_f [front_end_id][context_id] = (flags & FLAG_F )!=0; break; } case SPR_LOGIC_SR_CY_OV : { spr_write_sr_cy_val [front_end_id][context_id] = 1; spr_write_sr_ov_val [front_end_id][context_id] = 1; spr_write_sr_cy [front_end_id][context_id] = (flags & FLAG_CY)!=0; spr_write_sr_ov [front_end_id][context_id] = (flags & FLAG_OV)!=0; break; } default : { #ifdef DEBUG_TEST throw ERRORMORPHEO(FUNCTION,_("Invalid num_reg_re_log.\n")); #endif } } } // find an instruction can be retire, and in order if (spr_write_ack) { retire_val [x][y] = 1; num_inst_retire [x] ++; internal_BANK_RETIRE_VAL [num_bank] = true; } // Restore Old Register Tcontrol_t retire_restore = (commit_event_state_to_event_state(reg_EVENT_STATE[front_end_id][context_id]) != EVENT_STATE_NO_EVENT); // Test if event -> need restore ? if (retire_restore) { log_printf(TRACE,Commit_unit,FUNCTION," * Restore"); // Test and update update table if (write_rd) { internal_BANK_RETIRE_RESTORE_RD_PHY_OLD [num_bank] = (internal_rat_gpr_update_table[front_end_id][context_id][num_reg_rd_log] == 0); internal_rat_gpr_update_table[front_end_id][context_id][num_reg_rd_log] = 1; } if (write_re) { internal_BANK_RETIRE_RESTORE_RE_PHY_OLD [num_bank] = (internal_rat_spr_update_table[front_end_id][context_id][num_reg_re_log] == 0); internal_rat_spr_update_table[front_end_id][context_id][num_reg_re_log] = 1; } log_printf(TRACE,Commit_unit,FUNCTION," * restore_rd_phy_old : %d",internal_BANK_RETIRE_RESTORE_RD_PHY_OLD [num_bank]); log_printf(TRACE,Commit_unit,FUNCTION," * restore_re_phy_old : %d",internal_BANK_RETIRE_RESTORE_RE_PHY_OLD [num_bank]); } internal_BANK_RETIRE_NUM_RENAME_UNIT [num_bank] = x; internal_BANK_RETIRE_NUM_INST [num_bank] = y; if (_param->_have_port_front_end_id) PORT_WRITE(out_RETIRE_FRONT_END_ID [x][y], front_end_id ); if (_param->_have_port_context_id) PORT_WRITE(out_RETIRE_CONTEXT_ID [x][y], context_id ); // PORT_WRITE(out_RETIRE_RENAME_UNIT_ID [x][y], entry->rename_unit_id ); PORT_WRITE(out_RETIRE_USE_STORE_QUEUE [x][y], entry->use_store_queue ); PORT_WRITE(out_RETIRE_USE_LOAD_QUEUE [x][y], entry->use_load_queue ); PORT_WRITE(out_RETIRE_STORE_QUEUE_PTR_WRITE [x][y], entry->store_queue_ptr_write); if (_param->_have_port_load_queue_ptr) PORT_WRITE(out_RETIRE_LOAD_QUEUE_PTR_WRITE [x][y], entry->load_queue_ptr_write ); // PORT_WRITE(out_RETIRE_READ_RA [x][y], entry->read_ra ); // PORT_WRITE(out_RETIRE_NUM_REG_RA_PHY [x][y], entry->num_reg_ra_phy ); // PORT_WRITE(out_RETIRE_READ_RB [x][y], entry->read_rb ); // PORT_WRITE(out_RETIRE_NUM_REG_RB_PHY [x][y], entry->num_reg_rb_phy ); // PORT_WRITE(out_RETIRE_READ_RC [x][y], entry->read_rc ); // PORT_WRITE(out_RETIRE_NUM_REG_RC_PHY [x][y], entry->num_reg_rc_phy ); PORT_WRITE(out_RETIRE_WRITE_RD [x][y], entry->write_rd ); PORT_WRITE(out_RETIRE_NUM_REG_RD_LOG [x][y], entry->num_reg_rd_log ); PORT_WRITE(out_RETIRE_NUM_REG_RD_PHY_OLD [x][y], entry->num_reg_rd_phy_old ); PORT_WRITE(out_RETIRE_NUM_REG_RD_PHY_NEW [x][y], entry->num_reg_rd_phy_new ); PORT_WRITE(out_RETIRE_WRITE_RE [x][y], write_re ); PORT_WRITE(out_RETIRE_NUM_REG_RE_LOG [x][y], num_reg_re_log ); PORT_WRITE(out_RETIRE_NUM_REG_RE_PHY_OLD [x][y], entry->num_reg_re_phy_old ); PORT_WRITE(out_RETIRE_NUM_REG_RE_PHY_NEW [x][y], entry->num_reg_re_phy_new ); PORT_WRITE(out_RETIRE_RESTORE [x][y],retire_restore); PORT_WRITE(out_RETIRE_RESTORE_RD_PHY_OLD [x][y],internal_BANK_RETIRE_RESTORE_RD_PHY_OLD [num_bank]); PORT_WRITE(out_RETIRE_RESTORE_RE_PHY_OLD [x][y],internal_BANK_RETIRE_RESTORE_RE_PHY_OLD [num_bank]); // Event -> rob must be manage this event if ((state == ROB_END_BRANCH_MISS) or (state == ROB_END_LOAD_MISS)) can_retire [x] = false; } log_printf(TRACE,Commit_unit,FUNCTION," * bypass (before) : %d",bypass); bypass = ((state == ROB_END ) or (state == ROB_STORE_OK ) or (state == ROB_STORE_KO ) or (state == ROB_STORE_OK_WAIT_END) or (state == ROB_STORE_KO_WAIT_END)); log_printf(TRACE,Commit_unit,FUNCTION," * bypass (after) : %d",bypass); uint32_t packet = ((entry->ptr << _param->_shift_num_slot) | num_bank); log_printf(TRACE,Commit_unit,FUNCTION," * packet : %d",packet); // if future event, don't update after this event if ((reg_EVENT_STATE [front_end_id][context_id] == COMMIT_EVENT_STATE_NOT_YET_EVENT) and (reg_EVENT_PACKET [front_end_id][context_id] == packet)) { log_printf(TRACE,Commit_unit,FUNCTION," * is the event instruction, stop bypass !!!"); bypass = false; } } // Retire "in-order" can_retire [x] &= (retire_val [x][y] or bypass); } } } for (uint32_t i=0; i<_param->_nb_rename_unit; i++) for (uint32_t j=0; j<_param->_nb_inst_retire[i]; j++) PORT_WRITE(out_RETIRE_VAL [i][j],retire_val [i][j]); for (uint32_t i=0; i<_param->_nb_front_end; ++i) for (uint32_t j=0; j<_param->_nb_context[i]; ++j) { PORT_WRITE(out_SPR_WRITE_VAL [i][j], spr_write_val [i][j]); PORT_WRITE(out_SPR_WRITE_SR_F_VAL [i][j], spr_write_sr_f_val [i][j]); PORT_WRITE(out_SPR_WRITE_SR_F [i][j], spr_write_sr_f [i][j]); PORT_WRITE(out_SPR_WRITE_SR_CY_VAL [i][j], spr_write_sr_cy_val [i][j]); PORT_WRITE(out_SPR_WRITE_SR_CY [i][j], spr_write_sr_cy [i][j]); PORT_WRITE(out_SPR_WRITE_SR_OV_VAL [i][j], spr_write_sr_ov_val [i][j]); PORT_WRITE(out_SPR_WRITE_SR_OV [i][j], spr_write_sr_ov [i][j]); } } else { for (uint32_t i=0; i<_param->_nb_rename_unit; i++) for (uint32_t j=0; j<_param->_nb_inst_retire[i]; j++) PORT_WRITE(out_RETIRE_VAL [i][j],0); for (uint32_t i=0; i<_param->_nb_front_end; ++i) for (uint32_t j=0; j<_param->_nb_context[i]; ++j) PORT_WRITE(out_SPR_WRITE_VAL [i][j], 0); } log_end(Commit_unit,FUNCTION); }; }; // end namespace commit_unit }; // end namespace ooo_engine }; // end namespace multi_ooo_engine }; // end namespace core }; // end namespace behavioural }; // end namespace morpheo #endif