void X86CpuDumpReport(X86Cpu *self, FILE *f) { X86Emu *emu = self->emu; X86Core *core; X86Thread *thread; long long now; int i; int j; /* Get CPU timer value */ now = m2s_timer_get_value(asEmu(emu)->timer); /* Dump CPU configuration */ fprintf(f, ";\n; CPU Configuration\n;\n\n"); X86DumpCpuConfig(f); /* Report for the complete processor */ fprintf(f, ";\n; Simulation Statistics\n;\n\n"); fprintf(f, "; Global statistics\n"); fprintf(f, "[ Global ]\n\n"); fprintf(f, "Cycles = %lld\n", asTiming(self)->cycle); fprintf(f, "Time = %.2f\n", (double)now / 1000000); fprintf(f, "CyclesPerSecond = %.0f\n", now ? (double)asTiming(self)->cycle / now * 1000000 : 0.0); fprintf(f, "MemoryUsed = %lu\n", (long)mem_mapped_space); fprintf(f, "MemoryUsedMax = %lu\n", (long)mem_max_mapped_space); fprintf(f, "\n"); /* Dispatch stage */ fprintf(f, "; Dispatch stage\n"); X86CpuDumpUopReport(self, f, self->num_dispatched_uinst_array, "Dispatch", x86_cpu_dispatch_width); /* Issue stage */ fprintf(f, "; Issue stage\n"); X86CpuDumpUopReport(self, f, self->num_issued_uinst_array, "Issue", x86_cpu_issue_width); /* Commit stage */ fprintf(f, "; Commit stage\n"); X86CpuDumpUopReport(self, f, self->num_committed_uinst_array, "Commit", x86_cpu_commit_width); /* Committed branches */ fprintf(f, "; Committed branches\n"); fprintf(f, "; Branches - Number of committed control uops\n"); fprintf( f, "; Squashed - Number of mispredicted uops squashed from the ROB\n"); fprintf( f, "; Mispred - Number of mispredicted branches in the correct path\n"); fprintf(f, "; PredAcc - Prediction accuracy\n"); fprintf(f, "Commit.Branches = %lld\n", self->num_branch_uinst); fprintf(f, "Commit.Squashed = %lld\n", self->num_squashed_uinst); fprintf(f, "Commit.Mispred = %lld\n", self->num_mispred_branch_uinst); fprintf( f, "Commit.PredAcc = %.4g\n", self->num_branch_uinst ? (double)(self->num_branch_uinst - self->num_mispred_branch_uinst) / self->num_branch_uinst : 0.0); fprintf(f, "\n"); /* Report for each core */ for (i = 0; i < x86_cpu_num_cores; i++) { /* Core */ core = self->cores[i]; fprintf(f, "\n; Statistics for core %d\n", core->id); fprintf(f, "[ c%d ]\n\n", core->id); /* Functional units */ X86CoreDumpFunctionalUnitsReport(core, f); /* Dispatch slots */ if (x86_cpu_dispatch_kind == x86_cpu_dispatch_kind_timeslice) { fprintf(f, "; Dispatch slots usage (sum = cycles * dispatch width)\n"); fprintf(f, "; used - dispatch slot was used by a non-spec uop\n"); fprintf(f, "; spec - used by a mispeculated uop\n"); fprintf(f, "; ctx - no context allocated to thread\n"); fprintf(f, "; uopq,rob,iq,lsq,rename - no space in structure\n"); DUMP_DISPATCH_STAT(used); DUMP_DISPATCH_STAT(spec); DUMP_DISPATCH_STAT(uop_queue); DUMP_DISPATCH_STAT(rob); DUMP_DISPATCH_STAT(iq); DUMP_DISPATCH_STAT(lsq); DUMP_DISPATCH_STAT(rename); DUMP_DISPATCH_STAT(ctx); fprintf(f, "\n"); } /* Dispatch stage */ fprintf(f, "; Dispatch stage\n"); X86CpuDumpUopReport(self, f, core->num_dispatched_uinst_array, "Dispatch", x86_cpu_dispatch_width); /* Issue stage */ fprintf(f, "; Issue stage\n"); X86CpuDumpUopReport(self, f, core->num_issued_uinst_array, "Issue", x86_cpu_issue_width); /* Commit stage */ fprintf(f, "; Commit stage\n"); X86CpuDumpUopReport(self, f, core->num_committed_uinst_array, "Commit", x86_cpu_commit_width); /* Committed branches */ fprintf(f, "; Committed branches\n"); fprintf(f, "Commit.Branches = %lld\n", core->num_branch_uinst); fprintf(f, "Commit.Squashed = %lld\n", core->num_squashed_uinst); fprintf(f, "Commit.Mispred = %lld\n", core->num_mispred_branch_uinst); fprintf(f, "Commit.PredAcc = %.4g\n", core->num_branch_uinst ? (double)(core->num_branch_uinst - core->num_mispred_branch_uinst) / core->num_branch_uinst : 0.0); fprintf(f, "\n"); /* Occupancy stats */ fprintf(f, "; Structure statistics (reorder buffer, instruction queue,\n"); fprintf(f, "; load-store queue, and integer/floating-point register file)\n"); fprintf(f, "; Size - Available size\n"); fprintf(f, "; Occupancy - Average number of occupied entries\n"); fprintf(f, "; Full - Number of cycles when the structure was full\n"); fprintf(f, "; Reads, Writes - Accesses to the structure\n"); if (x86_rob_kind == x86_rob_kind_shared) DUMP_CORE_STRUCT_STATS(ROB, rob); if (x86_iq_kind == x86_iq_kind_shared) { DUMP_CORE_STRUCT_STATS(IQ, iq); fprintf(f, "IQ.WakeupAccesses = %lld\n", core->iq_wakeup_accesses); } if (x86_lsq_kind == x86_lsq_kind_shared) DUMP_CORE_STRUCT_STATS(LSQ, lsq); if (x86_reg_file_kind == x86_reg_file_kind_shared) { DUMP_CORE_STRUCT_STATS(RF_Int, reg_file_int); DUMP_CORE_STRUCT_STATS(RF_Fp, reg_file_fp); } fprintf(f, "\n"); /* Report for each thread */ for (j = 0; j < x86_cpu_num_threads; j++) { thread = core->threads[j]; fprintf(f, "\n; Statistics for core %d - thread %d\n", core->id, thread->id_in_core); fprintf(f, "[ %s ]\n\n", thread->name); /* Dispatch stage */ fprintf(f, "; Dispatch stage\n"); X86CpuDumpUopReport(self, f, thread->num_dispatched_uinst_array, "Dispatch", x86_cpu_dispatch_width); /* Issue stage */ fprintf(f, "; Issue stage\n"); X86CpuDumpUopReport(self, f, thread->num_issued_uinst_array, "Issue", x86_cpu_issue_width); /* Commit stage */ fprintf(f, "; Commit stage\n"); X86CpuDumpUopReport(self, f, thread->num_committed_uinst_array, "Commit", x86_cpu_commit_width); /* Committed branches */ fprintf(f, "; Committed branches\n"); fprintf(f, "Commit.Branches = %lld\n", thread->num_branch_uinst); fprintf(f, "Commit.Squashed = %lld\n", thread->num_squashed_uinst); fprintf(f, "Commit.Mispred = %lld\n", thread->num_mispred_branch_uinst); fprintf(f, "Commit.PredAcc = %.4g\n", thread->num_branch_uinst ? (double)(thread->num_branch_uinst - thread->num_mispred_branch_uinst) / thread->num_branch_uinst : 0.0); fprintf(f, "\n"); /* Occupancy stats */ fprintf(f, "; Structure statistics (reorder buffer, instruction queue, " "load-store queue,\n"); fprintf(f, "; integer/floating-point register file, and renaming table)\n"); if (x86_rob_kind == x86_rob_kind_private) DUMP_THREAD_STRUCT_STATS(ROB, rob); if (x86_iq_kind == x86_iq_kind_private) { DUMP_THREAD_STRUCT_STATS(IQ, iq); fprintf(f, "IQ.WakeupAccesses = %lld\n", thread->iq_wakeup_accesses); } if (x86_lsq_kind == x86_lsq_kind_private) DUMP_THREAD_STRUCT_STATS(LSQ, lsq); if (x86_reg_file_kind == x86_reg_file_kind_private) { DUMP_THREAD_STRUCT_STATS(RF_Int, reg_file_int); DUMP_THREAD_STRUCT_STATS(RF_Fp, reg_file_fp); } fprintf(f, "RAT.IntReads = %lld\n", thread->rat_int_reads); fprintf(f, "RAT.IntWrites = %lld\n", thread->rat_int_writes); fprintf(f, "RAT.FpReads = %lld\n", thread->rat_fp_reads); fprintf(f, "RAT.FpWrites = %lld\n", thread->rat_fp_writes); fprintf(f, "BTB.Reads = %lld\n", thread->btb_reads); fprintf(f, "BTB.Writes = %lld\n", thread->btb_writes); fprintf(f, "\n"); /* Trace cache stats */ if (thread->trace_cache) X86ThreadDumpTraceCacheReport(thread, f); } } }
static void x86_cpu_dump_report(void) { FILE *f; int core, thread; long long now; /* Open file */ f = file_open_for_write(x86_cpu_report_file_name); if (!f) return; /* Get CPU timer value */ now = m2s_timer_get_value(x86_emu->timer); /* Dump CPU configuration */ fprintf(f, ";\n; CPU Configuration\n;\n\n"); x86_cpu_config_dump(f); /* Report for the complete processor */ fprintf(f, ";\n; Simulation Statistics\n;\n\n"); fprintf(f, "; Global statistics\n"); fprintf(f, "[ Global ]\n\n"); fprintf(f, "Cycles = %lld\n", x86_cpu->cycle); fprintf(f, "Time = %.2f\n", (double) now / 1000000); fprintf(f, "CyclesPerSecond = %.0f\n", now ? (double) x86_cpu->cycle / now * 1000000 : 0.0); fprintf(f, "MemoryUsed = %lu\n", (long) mem_mapped_space); fprintf(f, "MemoryUsedMax = %lu\n", (long) mem_max_mapped_space); fprintf(f, "\n"); /* Dispatch stage */ fprintf(f, "; Dispatch stage\n"); x86_cpu_dump_uop_report(f, x86_cpu->num_dispatched_uinst_array, "Dispatch", x86_cpu_dispatch_width); /* Issue stage */ fprintf(f, "; Issue stage\n"); x86_cpu_dump_uop_report(f, x86_cpu->num_issued_uinst_array, "Issue", x86_cpu_issue_width); /* Commit stage */ fprintf(f, "; Commit stage\n"); x86_cpu_dump_uop_report(f, x86_cpu->num_committed_uinst_array, "Commit", x86_cpu_commit_width); /* Committed branches */ fprintf(f, "; Committed branches\n"); fprintf(f, "; Branches - Number of committed control uops\n"); fprintf(f, "; Squashed - Number of mispredicted uops squashed from the ROB\n"); fprintf(f, "; Mispred - Number of mispredicted branches in the correct path\n"); fprintf(f, "; PredAcc - Prediction accuracy\n"); fprintf(f, "Commit.Branches = %lld\n", x86_cpu->num_branch_uinst); fprintf(f, "Commit.Squashed = %lld\n", x86_cpu->num_squashed_uinst); fprintf(f, "Commit.Mispred = %lld\n", x86_cpu->num_mispred_branch_uinst); fprintf(f, "Commit.PredAcc = %.4g\n", x86_cpu->num_branch_uinst ? (double) (x86_cpu->num_branch_uinst - x86_cpu->num_mispred_branch_uinst) / x86_cpu->num_branch_uinst : 0.0); fprintf(f, "\n"); /* Report for each core */ X86_CORE_FOR_EACH { /* Core */ fprintf(f, "\n; Statistics for core %d\n", core); fprintf(f, "[ c%d ]\n\n", core); /* Functional units */ fprintf(f, "; Functional unit pool\n"); fprintf(f, "; Accesses - Number of uops issued to a f.u.\n"); fprintf(f, "; Denied - Number of requests denied due to busy f.u.\n"); fprintf(f, "; WaitingTime - Average number of waiting cycles to reserve f.u.\n"); DUMP_FU_STAT(IntAdd, x86_fu_intadd); DUMP_FU_STAT(IntMult, x86_fu_intmult); DUMP_FU_STAT(IntDiv, x86_fu_intdiv); DUMP_FU_STAT(Effaddr, x86_fu_effaddr); DUMP_FU_STAT(Logic, x86_fu_logic); DUMP_FU_STAT(FPSimple, x86_fu_fpsimple); DUMP_FU_STAT(FPAdd, x86_fu_fpadd); DUMP_FU_STAT(FPMult, x86_fu_fpmult); DUMP_FU_STAT(FPDiv, x86_fu_fpdiv); DUMP_FU_STAT(FPComplex, x86_fu_fpcomplex); fprintf(f, "\n"); /* Dispatch slots */ if (x86_cpu_dispatch_kind == x86_cpu_dispatch_kind_timeslice) { fprintf(f, "; Dispatch slots usage (sum = cycles * dispatch width)\n"); fprintf(f, "; used - dispatch slot was used by a non-spec uop\n"); fprintf(f, "; spec - used by a mispeculated uop\n"); fprintf(f, "; ctx - no context allocated to thread\n"); fprintf(f, "; uopq,rob,iq,lsq,rename - no space in structure\n"); DUMP_DISPATCH_STAT(used); DUMP_DISPATCH_STAT(spec); DUMP_DISPATCH_STAT(uop_queue); DUMP_DISPATCH_STAT(rob); DUMP_DISPATCH_STAT(iq); DUMP_DISPATCH_STAT(lsq); DUMP_DISPATCH_STAT(rename); DUMP_DISPATCH_STAT(ctx); fprintf(f, "\n"); } /* Dispatch stage */ fprintf(f, "; Dispatch stage\n"); x86_cpu_dump_uop_report(f, X86_CORE.num_dispatched_uinst_array, "Dispatch", x86_cpu_dispatch_width); /* Issue stage */ fprintf(f, "; Issue stage\n"); x86_cpu_dump_uop_report(f, X86_CORE.num_issued_uinst_array, "Issue", x86_cpu_issue_width); /* Commit stage */ fprintf(f, "; Commit stage\n"); x86_cpu_dump_uop_report(f, X86_CORE.num_committed_uinst_array, "Commit", x86_cpu_commit_width); /* Committed branches */ fprintf(f, "; Committed branches\n"); fprintf(f, "Commit.Branches = %lld\n", X86_CORE.num_branch_uinst); fprintf(f, "Commit.Squashed = %lld\n", X86_CORE.num_squashed_uinst); fprintf(f, "Commit.Mispred = %lld\n", X86_CORE.num_mispred_branch_uinst); fprintf(f, "Commit.PredAcc = %.4g\n", X86_CORE.num_branch_uinst ? (double) (X86_CORE.num_branch_uinst - X86_CORE.num_mispred_branch_uinst) / X86_CORE.num_branch_uinst : 0.0); fprintf(f, "\n"); /* Occupancy stats */ fprintf(f, "; Structure statistics (reorder buffer, instruction queue,\n"); fprintf(f, "; load-store queue, and integer/floating-point register file)\n"); fprintf(f, "; Size - Available size\n"); fprintf(f, "; Occupancy - Average number of occupied entries\n"); fprintf(f, "; Full - Number of cycles when the structure was full\n"); fprintf(f, "; Reads, Writes - Accesses to the structure\n"); if (x86_rob_kind == x86_rob_kind_shared) DUMP_CORE_STRUCT_STATS(ROB, rob); if (x86_iq_kind == x86_iq_kind_shared) { DUMP_CORE_STRUCT_STATS(IQ, iq); fprintf(f, "IQ.WakeupAccesses = %lld\n", X86_CORE.iq_wakeup_accesses); } if (x86_lsq_kind == x86_lsq_kind_shared) DUMP_CORE_STRUCT_STATS(LSQ, lsq); if (x86_reg_file_kind == x86_reg_file_kind_shared) { DUMP_CORE_STRUCT_STATS(RF_Int, reg_file_int); DUMP_CORE_STRUCT_STATS(RF_Fp, reg_file_fp); } fprintf(f, "\n"); /* Report for each thread */ X86_THREAD_FOR_EACH { fprintf(f, "\n; Statistics for core %d - thread %d\n", core, thread); fprintf(f, "[ c%dt%d ]\n\n", core, thread); /* Dispatch stage */ fprintf(f, "; Dispatch stage\n"); x86_cpu_dump_uop_report(f, X86_THREAD.num_dispatched_uinst_array, "Dispatch", x86_cpu_dispatch_width); /* Issue stage */ fprintf(f, "; Issue stage\n"); x86_cpu_dump_uop_report(f, X86_THREAD.num_issued_uinst_array, "Issue", x86_cpu_issue_width); /* Commit stage */ fprintf(f, "; Commit stage\n"); x86_cpu_dump_uop_report(f, X86_THREAD.num_committed_uinst_array, "Commit", x86_cpu_commit_width); /* Committed branches */ fprintf(f, "; Committed branches\n"); fprintf(f, "Commit.Branches = %lld\n", X86_THREAD.num_branch_uinst); fprintf(f, "Commit.Squashed = %lld\n", X86_THREAD.num_squashed_uinst); fprintf(f, "Commit.Mispred = %lld\n", X86_THREAD.num_mispred_branch_uinst); fprintf(f, "Commit.PredAcc = %.4g\n", X86_THREAD.num_branch_uinst ? (double) (X86_THREAD.num_branch_uinst - X86_THREAD.num_mispred_branch_uinst) / X86_THREAD.num_branch_uinst : 0.0); fprintf(f, "\n"); /* Occupancy stats */ fprintf(f, "; Structure statistics (reorder buffer, instruction queue, load-store queue,\n"); fprintf(f, "; integer/floating-point register file, and renaming table)\n"); if (x86_rob_kind == x86_rob_kind_private) DUMP_THREAD_STRUCT_STATS(ROB, rob); if (x86_iq_kind == x86_iq_kind_private) { DUMP_THREAD_STRUCT_STATS(IQ, iq); fprintf(f, "IQ.WakeupAccesses = %lld\n", X86_THREAD.iq_wakeup_accesses); } if (x86_lsq_kind == x86_lsq_kind_private) DUMP_THREAD_STRUCT_STATS(LSQ, lsq); if (x86_reg_file_kind == x86_reg_file_kind_private) { DUMP_THREAD_STRUCT_STATS(RF_Int, reg_file_int); DUMP_THREAD_STRUCT_STATS(RF_Fp, reg_file_fp); } fprintf(f, "RAT.IntReads = %lld\n", X86_THREAD.rat_int_reads); fprintf(f, "RAT.IntWrites = %lld\n", X86_THREAD.rat_int_writes); fprintf(f, "RAT.FpReads = %lld\n", X86_THREAD.rat_fp_reads); fprintf(f, "RAT.FpWrites = %lld\n", X86_THREAD.rat_fp_writes); fprintf(f, "BTB.Reads = %lld\n", X86_THREAD.btb_reads); fprintf(f, "BTB.Writes = %lld\n", X86_THREAD.btb_writes); fprintf(f, "\n"); /* Trace cache stats */ if (X86_THREAD.trace_cache) x86_trace_cache_dump_report(X86_THREAD.trace_cache, f); } } /* Close */ fclose(f); }