Example #1
0
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);
    }
  }
}
Example #2
0
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);
}