📄 profile-fr400.c
字号:
/* frv simulator fr400 dependent profiling code. Copyright (C) 2001 Free Software Foundation, Inc. Contributed by Red HatThis file is part of the GNU simulators.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith this program; if not, write to the Free Software Foundation, Inc.,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#define WANT_CPU#define WANT_CPU_FRVBF#include "sim-main.h"#include "bfd.h"#if WITH_PROFILE_MODEL_P#include "profile.h"#include "profile-fr400.h"/* These functions get and set flags representing the use of registers/resources. */static void set_use_not_fp_load (SIM_CPU *, INT);static void set_use_not_media_p4 (SIM_CPU *, INT);static void set_use_not_media_p6 (SIM_CPU *, INT);static void set_acc_use_not_media_p2 (SIM_CPU *, INT);static void set_acc_use_not_media_p4 (SIM_CPU *, INT);voidfr400_reset_gr_flags (SIM_CPU *cpu, INT fr){ set_use_not_gr_complex (cpu, fr);}voidfr400_reset_fr_flags (SIM_CPU *cpu, INT fr){ set_use_not_fp_load (cpu, fr); set_use_not_media_p4 (cpu, fr); set_use_not_media_p6 (cpu, fr);}voidfr400_reset_acc_flags (SIM_CPU *cpu, INT acc){ set_acc_use_not_media_p2 (cpu, acc); set_acc_use_not_media_p4 (cpu, acc);}static voidset_use_is_fp_load (SIM_CPU *cpu, INT fr, INT fr_double){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) { fr400_reset_fr_flags (cpu, fr); d->cur_fp_load |= (((DI)1) << fr); } if (fr_double != -1) { fr400_reset_fr_flags (cpu, fr_double); d->cur_fp_load |= (((DI)1) << fr_double); if (fr_double < 63) { fr400_reset_fr_flags (cpu, fr_double + 1); d->cur_fp_load |= (((DI)1) << (fr_double + 1)); } }}static voidset_use_not_fp_load (SIM_CPU *cpu, INT fr){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) d->cur_fp_load &= ~(((DI)1) << fr);}static intuse_is_fp_load (SIM_CPU *cpu, INT fr){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) return (d->prev_fp_load >> fr) & 1; return 0;}static voidset_acc_use_is_media_p2 (SIM_CPU *cpu, INT acc){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (acc != -1) { fr400_reset_acc_flags (cpu, acc); d->cur_acc_p2 |= (((DI)1) << acc); }}static voidset_acc_use_not_media_p2 (SIM_CPU *cpu, INT acc){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (acc != -1) d->cur_acc_p2 &= ~(((DI)1) << acc);}static intacc_use_is_media_p2 (SIM_CPU *cpu, INT acc){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (acc != -1) return d->cur_acc_p2 & (((DI)1) << acc); return 0;}static voidset_use_is_media_p4 (SIM_CPU *cpu, INT fr){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) { fr400_reset_fr_flags (cpu, fr); d->cur_fr_p4 |= (((DI)1) << fr); }}static voidset_use_not_media_p4 (SIM_CPU *cpu, INT fr){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) d->cur_fr_p4 &= ~(((DI)1) << fr);}static intuse_is_media_p4 (SIM_CPU *cpu, INT fr){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) return d->cur_fr_p4 & (((DI)1) << fr); return 0;}static voidset_acc_use_is_media_p4 (SIM_CPU *cpu, INT acc){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (acc != -1) { fr400_reset_acc_flags (cpu, acc); d->cur_acc_p4 |= (((DI)1) << acc); }}static voidset_acc_use_not_media_p4 (SIM_CPU *cpu, INT acc){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (acc != -1) d->cur_acc_p4 &= ~(((DI)1) << acc);}static intacc_use_is_media_p4 (SIM_CPU *cpu, INT acc){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (acc != -1) return d->cur_acc_p4 & (((DI)1) << acc); return 0;}static voidset_use_is_media_p6 (SIM_CPU *cpu, INT fr){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) { fr400_reset_fr_flags (cpu, fr); d->cur_fr_p6 |= (((DI)1) << fr); }}static voidset_use_not_media_p6 (SIM_CPU *cpu, INT fr){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) d->cur_fr_p6 &= ~(((DI)1) << fr);}static intuse_is_media_p6 (SIM_CPU *cpu, INT fr){ MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); if (fr != -1) return d->cur_fr_p6 & (((DI)1) << fr); return 0;}/* Initialize cycle counting for an insn. FIRST_P is non-zero if this is the first insn in a set of parallel insns. */voidfr400_model_insn_before (SIM_CPU *cpu, int first_p){ if (first_p) { MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu); ps->cur_gr_complex = ps->prev_gr_complex; d->cur_fp_load = d->prev_fp_load; d->cur_fr_p4 = d->prev_fr_p4; d->cur_fr_p6 = d->prev_fr_p6; d->cur_acc_p2 = d->prev_acc_p2; d->cur_acc_p4 = d->prev_acc_p4; }}/* Record the cycles computed for an insn. LAST_P is non-zero if this is the last insn in a set of parallel insns, and we update the total cycle count. CYCLES is the cycle count of the insn. */voidfr400_model_insn_after (SIM_CPU *cpu, int last_p, int cycles){ if (last_p) { MODEL_FR400_DATA *d = CPU_MODEL_DATA (cpu); FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (cpu); ps->prev_gr_complex = ps->cur_gr_complex; d->prev_fp_load = d->cur_fp_load; d->prev_fr_p4 = d->cur_fr_p4; d->prev_fr_p6 = d->cur_fr_p6; d->prev_acc_p2 = d->cur_acc_p2; d->prev_acc_p4 = d->cur_acc_p4; }}intfrvbf_model_fr400_u_exec (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced){ return idesc->timing->units[unit_num].done;}intfrvbf_model_fr400_u_integer (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT out_GRk, INT out_ICCi_1){ /* Modelling for this unit is the same as for fr500. */ return frvbf_model_fr500_u_integer (cpu, idesc, unit_num, referenced, in_GRi, in_GRj, out_GRk, out_ICCi_1);}intfrvbf_model_fr400_u_imul (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT out_GRk, INT out_ICCi_1){ /* Modelling for this unit is the same as for fr500. */ return frvbf_model_fr500_u_imul (cpu, idesc, unit_num, referenced, in_GRi, in_GRj, out_GRk, out_ICCi_1);}intfrvbf_model_fr400_u_idiv (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT out_GRk, INT out_ICCi_1){ int cycles; FRV_VLIW *vliw; int slot; /* icc0-icc4 are the upper 4 fields of the CCR. */ if (out_ICCi_1 >= 0) out_ICCi_1 += 4; vliw = CPU_VLIW (cpu); slot = vliw->next_slot - 1; slot = (*vliw->current_vliw)[slot] - UNIT_I0; if (model_insn == FRV_INSN_MODEL_PASS_1) { /* The entire VLIW insn must wait if there is a dependency on a register which is not ready yet. The latency of the registers may be less than previously recorded, depending on how they were used previously. See Table 13-8 in the LSI. */ if (in_GRi != out_GRk && in_GRi >= 0) { if (use_is_gr_complex (cpu, in_GRi)) decrease_GR_busy (cpu, in_GRi, 1); } if (in_GRj != out_GRk && in_GRj != in_GRi && in_GRj >= 0) { if (use_is_gr_complex (cpu, in_GRj)) decrease_GR_busy (cpu, in_GRj, 1); } vliw_wait_for_GR (cpu, in_GRi); vliw_wait_for_GR (cpu, in_GRj); vliw_wait_for_GR (cpu, out_GRk); vliw_wait_for_CCR (cpu, out_ICCi_1); vliw_wait_for_idiv_resource (cpu, slot); handle_resource_wait (cpu); load_wait_for_GR (cpu, in_GRi); load_wait_for_GR (cpu, in_GRj); load_wait_for_GR (cpu, out_GRk); trace_vliw_wait_cycles (cpu); return 0; } /* GRk has a latency of 19 cycles! */ cycles = idesc->timing->units[unit_num].done; update_GR_latency (cpu, out_GRk, cycles + 19); set_use_is_gr_complex (cpu, out_GRk); /* ICCi_1 has a latency of 18 cycles. */ update_CCR_latency (cpu, out_ICCi_1, cycles + 18); /* the idiv resource has a latency of 18 cycles! */ update_idiv_resource_latency (cpu, slot, cycles + 18); return cycles;}intfrvbf_model_fr400_u_branch (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT in_ICCi_2, INT in_ICCi_3){#define BRANCH_PREDICTED(ps) ((ps)->branch_hint & 2) FRV_PROFILE_STATE *ps; int cycles; if (model_insn == FRV_INSN_MODEL_PASS_1) { /* Modelling for this unit is the same as for fr500 in pass 1. */ return frvbf_model_fr500_u_branch (cpu, idesc, unit_num, referenced, in_GRi, in_GRj, in_ICCi_2, in_ICCi_3); } cycles = idesc->timing->units[unit_num].done; /* Compute the branch penalty, based on the the prediction and the out come. When counting branches taken or not taken, don't consider branches after the first taken branch in a vliw insn. */ ps = CPU_PROFILE_STATE (cpu); if (! ps->vliw_branch_taken) { int penalty; /* (1 << 4): The pc is the 5th element in inputs, outputs. ??? can be cleaned up */ PROFILE_DATA *p = CPU_PROFILE_DATA (cpu); int taken = (referenced & (1 << 4)) != 0; if (taken) { ++PROFILE_MODEL_TAKEN_COUNT (p); ps->vliw_branch_taken = 1; if (BRANCH_PREDICTED (ps)) penalty = 1; else penalty = 3; } else { ++PROFILE_MODEL_UNTAKEN_COUNT (p); if (BRANCH_PREDICTED (ps)) penalty = 3; else penalty = 0; } if (penalty > 0) { /* Additional 1 cycle penalty if the branch address is not 8 byte aligned. */ if (ps->branch_address & 7) ++penalty; update_branch_penalty (cpu, penalty); PROFILE_MODEL_CTI_STALL_CYCLES (p) += penalty; } } return cycles;}intfrvbf_model_fr400_u_trap (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT in_ICCi_2, INT in_FCCi_2){ /* Modelling for this unit is the same as for fr500. */ return frvbf_model_fr500_u_trap (cpu, idesc, unit_num, referenced, in_GRi, in_GRj, in_ICCi_2, in_FCCi_2);}intfrvbf_model_fr400_u_check (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_ICCi_3, INT in_FCCi_3){ /* Modelling for this unit is the same as for fr500. */ return frvbf_model_fr500_u_check (cpu, idesc, unit_num, referenced, in_ICCi_3, in_FCCi_3);}intfrvbf_model_fr400_u_set_hilo (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT out_GRkhi, INT out_GRklo){ /* Modelling for this unit is the same as for fr500. */ return frvbf_model_fr500_u_set_hilo (cpu, idesc, unit_num, referenced, out_GRkhi, out_GRklo);}intfrvbf_model_fr400_u_gr_load (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT out_GRk, INT out_GRdoublek){ /* Modelling for this unit is the same as for fr500. */ return frvbf_model_fr500_u_gr_load (cpu, idesc, unit_num, referenced, in_GRi, in_GRj, out_GRk, out_GRdoublek);}intfrvbf_model_fr400_u_gr_store (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT in_GRk, INT in_GRdoublek){ /* Modelling for this unit is the same as for fr500. */ return frvbf_model_fr500_u_gr_store (cpu, idesc, unit_num, referenced, in_GRi, in_GRj, in_GRk, in_GRdoublek);}intfrvbf_model_fr400_u_fr_load (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT out_FRk, INT out_FRdoublek){ int cycles; if (model_insn == FRV_INSN_MODEL_PASS_1) { /* Pass 1 is the same as for fr500. */ return frvbf_model_fr500_u_fr_load (cpu, idesc, unit_num, referenced, in_GRi, in_GRj, out_FRk, out_FRdoublek); } cycles = idesc->timing->units[unit_num].done; /* The latency of FRk for a load will depend on how long it takes to retrieve the the data from the cache or memory. */ update_FR_latency_for_load (cpu, out_FRk, cycles); update_FRdouble_latency_for_load (cpu, out_FRdoublek, cycles); set_use_is_fp_load (cpu, out_FRk, out_FRdoublek); return cycles;}intfrvbf_model_fr400_u_fr_store (SIM_CPU *cpu, const IDESC *idesc, int unit_num, int referenced, INT in_GRi, INT in_GRj, INT in_FRk, INT in_FRdoublek){ int cycles; if (model_insn == FRV_INSN_MODEL_PASS_1) { /* The entire VLIW insn must wait if there is a dependency on a register which is not ready yet. The latency of the registers may be less than previously recorded, depending on how they were used previously. See Table 13-8 in the LSI. */ if (in_GRi >= 0) { if (use_is_gr_complex (cpu, in_GRi)) decrease_GR_busy (cpu, in_GRi, 1); } if (in_GRj != in_GRi && in_GRj >= 0) { if (use_is_gr_complex (cpu, in_GRj)) decrease_GR_busy (cpu, in_GRj, 1); } if (in_FRk >= 0) { if (use_is_media_p4 (cpu, in_FRk) || use_is_media_p6 (cpu, in_FRk)) decrease_FR_busy (cpu, in_FRk, 1); else enforce_full_fr_latency (cpu, in_FRk); } vliw_wait_for_GR (cpu, in_GRi); vliw_wait_for_GR (cpu, in_GRj); vliw_wait_for_FR (cpu, in_FRk); vliw_wait_for_FRdouble (cpu, in_FRdoublek); handle_resource_wait (cpu); load_wait_for_GR (cpu, in_GRi); load_wait_for_GR (cpu, in_GRj); load_wait_for_FR (cpu, in_FRk); load_wait_for_FRdouble (cpu, in_FRdoublek); trace_vliw_wait_cycles (cpu); return 0; } cycles = idesc->timing->units[unit_num].done; return cycles;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -