simple profiler added
authornotaz <notasas@gmail.com>
Thu, 31 Dec 2009 15:51:40 +0000 (15:51 +0000)
committernotaz <notasas@gmail.com>
Thu, 31 Dec 2009 15:51:40 +0000 (15:51 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@850 be3aeb3a-fb24-0410-a615-afba39da0efa

12 files changed:
pico/32x/32x.c
pico/cd/pico.c
pico/draw.c
pico/memory.c
pico/pico.c
pico/pico_int.h
pico/sound/sound.c
platform/common/common.mak
platform/common/emu.c
platform/linux/Makefile
platform/linux/pprof.c [new file with mode: 0644]
platform/linux/pprof.h [new file with mode: 0644]

index 323b0b6..e945c8e 100644 (file)
@@ -165,6 +165,8 @@ static void p32x_start_blank(void)
 
 static __inline void run_m68k(int cyc)
 {
+  pprof_start(m68k);
+
 #if defined(EMU_C68K)
   PicoCpuCM68k.cycles = cyc;
   CycloneRun(&PicoCpuCM68k);
@@ -174,6 +176,8 @@ static __inline void run_m68k(int cyc)
 #elif defined(EMU_F68K)
   SekCycleCnt += fm68k_emulate(cyc+1, 0, 0);
 #endif
+
+  pprof_end(m68k);
 }
 
 // ~1463.8, but due to cache misses and slow mem
@@ -194,10 +198,18 @@ static __inline void run_m68k(int cyc)
     slice = SekCycleCnt - slice; /* real count from 68k */ \
     if (SekCycleCnt < SekCycleAim) \
       elprintf(EL_32X, "slice %d", slice); \
-    if (!(Pico32x.emu_flags & (P32XF_SSH2POLL|P32XF_SSH2VPOLL))) \
+    if (!(Pico32x.emu_flags & (P32XF_SSH2POLL|P32XF_SSH2VPOLL))) { \
+      pprof_start(ssh2); \
       sh2_execute(&ssh2, CYCLES_M68K2SH2(slice)); \
-    if (!(Pico32x.emu_flags & (P32XF_MSH2POLL|P32XF_MSH2VPOLL))) \
+      pprof_end(ssh2); \
+    } \
+    if (!(Pico32x.emu_flags & (P32XF_MSH2POLL|P32XF_MSH2VPOLL))) { \
+      pprof_start(msh2); \
       sh2_execute(&msh2, CYCLES_M68K2SH2(slice)); \
+      pprof_end(msh2); \
+    } \
+    pprof_start(dummy); \
+    pprof_end(dummy); \
   } \
 }
 
index 8b65f4f..383949c 100644 (file)
@@ -66,6 +66,9 @@ PICO_INTERNAL int PicoResetMCD(void)
 static __inline void SekRunM68k(int cyc)
 {
   int cyc_do;
+
+  pprof_start(m68k);
+
   SekCycleAim+=cyc;
   if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return;
 #if defined(EMU_CORE_DEBUG)
@@ -81,6 +84,7 @@ static __inline void SekRunM68k(int cyc)
   g_m68kcontext=&PicoCpuFM68k;
   SekCycleCnt+=fm68k_emulate(cyc_do, 0, 0);
 #endif
+  pprof_end(m68k);
 }
 
 static __inline void SekRunS68k(int cyc)
index e474168..6670ba3 100644 (file)
@@ -1485,6 +1485,8 @@ void PicoDrawSync(int to, int blank_last_line)
   int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight?\r
   int bgc = Pico.video.reg[7];\r
 \r
+  pprof_start(draw);\r
+\r
   if (rendlines != 240)\r
     offs = 8;\r
 \r
@@ -1516,6 +1518,8 @@ void PicoDrawSync(int to, int blank_last_line)
     line++;\r
   }\r
   DrawScanline = line;\r
+\r
+  pprof_end(draw);\r
 }\r
 \r
 void PicoDrawSetColorFormat(int which)\r
index f6c0eeb..d0b1697 100644 (file)
@@ -257,8 +257,11 @@ void NOINLINE ctl_write_z80busreq(u32 d)
     else\r
     {\r
       z80stopCycle = SekCyclesDone();\r
-      if ((PicoOpt&POPT_EN_Z80) && !Pico.m.z80_reset)\r
+      if ((PicoOpt&POPT_EN_Z80) && !Pico.m.z80_reset) {\r
+        pprof_start(m68k);\r
         PicoSyncZ80(z80stopCycle);\r
+        pprof_end_sub(m68k);\r
+      }\r
     }\r
     Pico.m.z80Run = d;\r
   }\r
@@ -272,8 +275,11 @@ void NOINLINE ctl_write_z80reset(u32 d)
   {\r
     if (d)\r
     {\r
-      if ((PicoOpt&POPT_EN_Z80) && Pico.m.z80Run)\r
+      if ((PicoOpt&POPT_EN_Z80) && Pico.m.z80Run) {\r
+        pprof_start(m68k);\r
         PicoSyncZ80(SekCyclesDone());\r
+        pprof_end_sub(m68k);\r
+      }\r
       YM2612ResetChip();\r
       timers_reset();\r
     }\r
index d312386..c63360c 100644 (file)
@@ -272,6 +272,8 @@ PICO_INTERNAL int CheckDMA(void)
 static __inline void SekRunM68k(int cyc)\r
 {\r
   int cyc_do;\r
+  pprof_start(m68k);\r
+\r
   SekCycleAim+=cyc;\r
   if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return;\r
 #if defined(EMU_CORE_DEBUG)\r
@@ -286,6 +288,8 @@ static __inline void SekRunM68k(int cyc)
 #elif defined(EMU_F68K)\r
   SekCycleCnt+=fm68k_emulate(cyc_do+1, 0, 0);\r
 #endif\r
+\r
+  pprof_end(m68k);\r
 }\r
 \r
 #include "pico_cmn.c"\r
@@ -303,38 +307,47 @@ PICO_INTERNAL void PicoSyncZ80(int m68k_cycles_done)
   z80_cycle_aim = cycles_68k_to_z80(m68k_cycles_done);\r
   cnt = z80_cycle_aim - z80_cycle_cnt;\r
 \r
+  pprof_start(z80);\r
+\r
   elprintf(EL_BUSREQ, "z80 sync %i (%i|%i -> %i|%i)", cnt, z80_cycle_cnt, z80_cycle_cnt / 228,\r
     z80_cycle_aim, z80_cycle_aim / 228);\r
 \r
   if (cnt > 0)\r
     z80_cycle_cnt += z80_run(cnt);\r
+\r
+  pprof_end(z80);\r
 }\r
 \r
 \r
 void PicoFrame(void)\r
 {\r
+  pprof_start(frame);\r
+\r
   Pico.m.frame_count++;\r
 \r
   if (PicoAHW & PAHW_SMS) {\r
     PicoFrameMS();\r
-    return;\r
+    goto end;\r
   }\r
 \r
   // TODO: MCD+32X\r
   if (PicoAHW & PAHW_MCD) {\r
     PicoFrameMCD();\r
-    return;\r
+    goto end;\r
   }\r
 \r
   if (PicoAHW & PAHW_32X) {\r
     PicoFrame32x();\r
-    return;\r
+    goto end;\r
   }\r
 \r
   //if(Pico.video.reg[12]&0x2) Pico.video.status ^= 0x10; // change odd bit in interlace mode\r
 \r
   PicoFrameStart();\r
   PicoFrameHints();\r
+\r
+end:\r
+  pprof_end(frame);\r
 }\r
 \r
 void PicoFrameDrawOnly(void)\r
index 2f4d1d3..f5481fc 100644 (file)
@@ -779,6 +779,18 @@ extern void lprintf(const char *fmt, ...);
 #define elprintf(w,f,...)\r
 #endif\r
 \r
+// profiling\r
+#ifdef PPROF\r
+#include <platform/linux/pprof.h>\r
+#else\r
+#define pprof_init()\r
+#define pprof_finish()\r
+#define pprof_start(x)\r
+#define pprof_end(...)\r
+#define pprof_end_sub(...)\r
+#endif\r
+\r
+// misc\r
 #ifdef _MSC_VER\r
 #define cdprintf\r
 #else\r
index dfa1d65..5bb8e9d 100644 (file)
@@ -308,6 +308,8 @@ static int PsndRender(int offset, int length)
                (Pico_mcd->pcm.control & 0x80) && Pico_mcd->pcm.enabled;\r
   offset <<= stereo;\r
 \r
+  pprof_start(sound);\r
+\r
 #if !SIMPLE_WRITE_SOUND\r
   if (offset == 0) { // should happen once per frame\r
     // compensate for float part of PsndLen\r
@@ -362,6 +364,8 @@ static int PsndRender(int offset, int length)
   // convert + limit to normal 16bit output\r
   PsndMix_32_to_16l(PsndOut+offset, buf32, length);\r
 \r
+  pprof_end(sound);\r
+\r
   return length;\r
 }\r
 \r
index f9958f4..3ddf3fb 100644 (file)
@@ -7,6 +7,10 @@ endif
 ifeq "$(profile)" "2"
 CFLAGS += -fprofile-use
 endif
+ifeq "$(pprof)" "1"
+DEFINES += PPROF
+OBJS += platform/linux/pprof.o
+endif
 
 # === Pico core ===
 # Pico
index bde10e4..f86526c 100644 (file)
@@ -1347,6 +1347,8 @@ void emu_init(void)
        mkdir_path(path, pos, "srm");\r
        mkdir_path(path, pos, "brm");\r
 \r
+       pprof_init();\r
+\r
        make_config_cfg(path);\r
        config_readlrom(path);\r
 \r
@@ -1373,6 +1375,8 @@ void emu_finish(void)
 #endif\r
        }\r
 \r
+       pprof_finish();\r
+\r
        PicoExit();\r
 }\r
 \r
@@ -1432,6 +1436,8 @@ void emu_loop(void)
                unsigned int timestamp;\r
                int diff, diff_lim;\r
 \r
+               pprof_start(main);\r
+\r
                timestamp = get_ticks();\r
                if (reset_timing) {\r
                        reset_timing = 0;\r
@@ -1537,7 +1543,7 @@ void emu_loop(void)
                PicoFrame();\r
                pemu_finalize_frame(fpsbuff, notice_msg);\r
 \r
-               //plat_video_flip();\r
+               // plat_video_flip();\r
 \r
                /* frame limiter */\r
                if (!reset_timing && !(currentConfig.EmuOpt & (EOPT_NO_FRMLIMIT|EOPT_EXT_FRMLIMIT)))\r
@@ -1560,6 +1566,8 @@ void emu_loop(void)
                plat_video_flip();\r
 \r
                pframes_done++; frames_done++; frames_shown++;\r
+\r
+               pprof_end(main);\r
        }\r
 \r
        emu_set_fastforward(0);\r
index 47a8dcc..3362a73 100644 (file)
@@ -88,6 +88,9 @@ PicoDrive : $(OBJS)
        @echo ">>>" $@
        $(CC) $(CFLAGS) $^ $(LDFLAGS) -Wl,-Map=PicoDrive.map -o $@
 
+pprof: pprof.c
+       $(CROSS)gcc -O2 -ggdb -DPPROF -DPPROF_TOOL -I../../ -I. $^ -o $@ -lrt
+
 %.o : %.asm
        @echo ">>>" $<
        nasm -f elf $< -o $@
diff --git a/platform/linux/pprof.c b/platform/linux/pprof.c
new file mode 100644 (file)
index 0000000..e1ecd1f
--- /dev/null
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#include <pico/pico_int.h>
+
+struct pp_counters *pp_counters;
+static int shmemid;
+
+void pprof_init(void)
+{
+       int this_is_new_shmem = 1;
+       key_t shmemkey;
+       void *shmem;
+
+#ifndef PPROF_TOOL
+       unsigned int tmp = pprof_get_one();
+       printf("pprof: measured diff is %u\n", pprof_get_one() - tmp);
+#endif
+
+       shmemkey = ftok(".", 0x02ABC32E);
+       if (shmemkey == -1)
+       {
+               perror("pprof: ftok failed");
+               return;
+       }
+
+#ifndef PPROF_TOOL
+       shmemid = shmget(shmemkey, sizeof(*pp_counters),
+               IPC_CREAT | IPC_EXCL | 0644);
+       if (shmemid == -1)
+#endif
+       {
+               shmemid = shmget(shmemkey, sizeof(*pp_counters),
+                               0644);
+               if (shmemid == -1)
+               {
+                       perror("pprof: shmget failed");
+                       return;
+               }
+               this_is_new_shmem = 0;
+       }
+
+       shmem = shmat(shmemid, NULL, 0);
+       if (shmem == (void *)-1)
+       {
+               perror("pprof: shmat failed");
+               return;
+       }
+
+       pp_counters = shmem;
+       if (this_is_new_shmem) {
+               memset(pp_counters, 0, sizeof(*pp_counters));
+               printf("pprof: pp_counters cleared.\n");
+       }
+}
+
+void pprof_finish(void)
+{
+       shmdt(pp_counters);
+       shmctl(shmemid, IPC_RMID, NULL);
+}
+
+#ifdef PPROF_TOOL
+
+#define IT(n) { pp_##n, #n }
+static const struct {
+       enum pprof_points pp;
+       const char *name;
+} pp_tab[] = {
+       IT(main),
+       IT(frame),
+       IT(draw),
+       IT(sound),
+       IT(m68k),
+       IT(z80),
+       IT(msh2),
+       IT(ssh2),
+       IT(dummy),
+};
+
+int main(int argc, char *argv[])
+{
+       unsigned long long old[pp_total_points], new[pp_total_points];
+       int base = 0;
+       int l, i;
+
+       pprof_init();
+       if (pp_counters == NULL)
+               return 1;
+
+       if (argc >= 2)
+               base = atoi(argv[1]);
+
+       memset(old, 0, sizeof(old));
+       for (l = 0; ; l++)
+       {
+               if ((l & 0x1f) == 0) {
+                       for (i = 0; i < ARRAY_SIZE(pp_tab); i++)
+                               printf("%6s ", pp_tab[i].name);
+                       printf("\n");
+               }
+
+               memcpy(new, pp_counters->counter, sizeof(new));
+               for (i = 0; i < ARRAY_SIZE(pp_tab); i++)
+               {
+                       unsigned long long idiff = new[i] - old[i];
+                       unsigned long long bdiff = (new[base] - old[base]) | 1;
+                       printf("%6.2f ", (double)idiff * 100.0 / bdiff);
+               }
+               printf("\n");
+               memcpy(old, new, sizeof(old));
+
+               if (argc < 3)
+                       break;
+               usleep(atoi(argv[2]));
+       }
+
+       return 0;
+}
+
+#endif // PPROF_TOOL
+
diff --git a/platform/linux/pprof.h b/platform/linux/pprof.h
new file mode 100644 (file)
index 0000000..88a97e3
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __PPROF_H__
+#define __PPROF_H__
+
+enum pprof_points {
+  pp_main,
+  pp_frame,
+  pp_draw,
+  pp_sound,
+  pp_m68k,
+  pp_z80,
+  pp_msh2,
+  pp_ssh2,
+  pp_dummy,
+  pp_total_points
+};
+
+struct pp_counters
+{
+       unsigned long long counter[pp_total_points];
+};
+
+extern struct pp_counters *pp_counters;
+
+#ifdef __i386__
+static __attribute__((always_inline)) inline unsigned int pprof_get_one(void)
+{
+  unsigned long long ret;
+  __asm__ __volatile__ ("rdtsc" : "=A" (ret));
+  return (unsigned int)ret;
+}
+
+#elif defined(__GP2X__)
+// XXX: MMSP2 only
+extern volatile unsigned long *gp2x_memregl;
+#define pprof_get_one() (unsigned int)gp2x_memregl[0x0a00 >> 2]
+
+#else
+#error no timer
+#endif
+
+#define pprof_start(point) { \
+    unsigned int pp_start_##point = pprof_get_one()
+#define pprof_end(point) \
+    pp_counters->counter[pp_##point] += pprof_get_one() - pp_start_##point; \
+  }
+// subtract for recursive stuff
+#define pprof_end_sub(point) \
+    pp_counters->counter[pp_##point] -= pprof_get_one() - pp_start_##point; \
+  }
+
+extern void pprof_init(void);
+extern void pprof_finish(void);
+
+#endif // __PPROF_H__