spu: c64x: fix cache handling, enable l2
authornotaz <notasas@gmail.com>
Mon, 2 Feb 2015 02:13:30 +0000 (04:13 +0200)
committernotaz <notasas@gmail.com>
Mon, 2 Feb 2015 02:13:30 +0000 (04:13 +0200)
plugins/dfsound/Makefile.c64p
plugins/dfsound/dma.c
plugins/dfsound/externals.h
plugins/dfsound/freeze.c
plugins/dfsound/spu.c
plugins/dfsound/spu_c64x.c
plugins/dfsound/spu_c64x.h
plugins/dfsound/spu_c64x_dspcode.c

index 45fe76a..5b97781 100644 (file)
@@ -5,7 +5,9 @@ endif
 include $(C64_TOOLS_DSP_ROOT)/install.mk
 
 TARGET_BASENAME = pcsxr_spu
 include $(C64_TOOLS_DSP_ROOT)/install.mk
 
 TARGET_BASENAME = pcsxr_spu
-OPTFLAGS += -O2
+OPTFLAGS += -o3
+CFLAGS += -mo
+#CFLAGS += -k -mw
 CFLAGS += -DNO_OS -DWANT_THREAD_CODE
 
 OBJ = \
 CFLAGS += -DNO_OS -DWANT_THREAD_CODE
 
 OBJ = \
index 4798a19..43019f1 100644 (file)
@@ -71,6 +71,7 @@ void CALLBACK SPUwriteDMA(unsigned short val)
 \r
  spu.spuAddr += 2;\r
  spu.spuAddr &= 0x7fffe;\r
 \r
  spu.spuAddr += 2;\r
  spu.spuAddr &= 0x7fffe;\r
+ spu.bMemDirty = 1;\r
 }\r
 \r
 ////////////////////////////////////////////////////////////////////////\r
 }\r
 \r
 ////////////////////////////////////////////////////////////////////////\r
@@ -83,6 +84,7 @@ void CALLBACK SPUwriteDMAMem(unsigned short *pusPSXMem, int iSize,
  int i;\r
  \r
  do_samples_if_needed(cycles, 1);\r
  int i;\r
  \r
  do_samples_if_needed(cycles, 1);\r
+ spu.bMemDirty = 1;\r
 \r
  if(spu.spuAddr + iSize*2 < 0x80000)\r
   {\r
 \r
  if(spu.spuAddr + iSize*2 < 0x80000)\r
   {\r
index 8bbf4e0..2db75ac 100644 (file)
@@ -189,6 +189,7 @@ typedef struct
  int             decode_dirty_ch;\r
  unsigned int    bSpuInit:1;\r
  unsigned int    bSPUIsOpen:1;\r
  int             decode_dirty_ch;\r
  unsigned int    bSpuInit:1;\r
  unsigned int    bSPUIsOpen:1;\r
+ unsigned int    bMemDirty:1;          // had external write to SPU RAM\r
 \r
  unsigned int    dwNoiseVal;           // global noise generator\r
  unsigned int    dwNoiseCount;\r
 \r
  unsigned int    dwNoiseVal;           // global noise generator\r
  unsigned int    dwNoiseCount;\r
index 72c9d22..43e6535 100644 (file)
@@ -279,6 +279,7 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
  memcpy(spu.spuMem,pF->cSPURam,0x80000);               // get ram\r
  memcpy(spu.regArea,pF->cSPUPort,0x200);\r
 \r
  memcpy(spu.spuMem,pF->cSPURam,0x80000);               // get ram\r
  memcpy(spu.regArea,pF->cSPUPort,0x200);\r
+ spu.bMemDirty = 1;\r
 \r
  if(pF->xaS.nsamples<=4032)                            // start xa again\r
   SPUplayADPCMchannel(&pF->xaS);\r
 \r
  if(pF->xaS.nsamples<=4032)                            // start xa again\r
   SPUplayADPCMchannel(&pF->xaS);\r
index 193a5d0..8e41d50 100644 (file)
@@ -842,6 +842,7 @@ static struct spu_worker {
    unsigned int i_ready;
    unsigned int i_reaped;
    unsigned int last_boot_cnt; // dsp
    unsigned int i_ready;
    unsigned int i_reaped;
    unsigned int last_boot_cnt; // dsp
+   unsigned int ram_dirty;
   };
   // aligning for C64X_DSP
   unsigned int _pad0[128/4];
   };
   // aligning for C64X_DSP
   unsigned int _pad0[128/4];
@@ -1055,6 +1056,7 @@ static void sync_worker_thread(int force)
 
  done = thread_get_i_done() - worker->i_reaped;
  used_space = worker->i_ready - worker->i_reaped;
 
  done = thread_get_i_done() - worker->i_reaped;
  used_space = worker->i_ready - worker->i_reaped;
+
  //printf("done: %d use: %d dsp: %u/%u\n", done, used_space,
  //  worker->boot_cnt, worker->i_done);
 
  //printf("done: %d use: %d dsp: %u/%u\n", done, used_space,
  //  worker->boot_cnt, worker->i_done);
 
index be10a6b..e0aa0da 100644 (file)
@@ -47,6 +47,25 @@ static struct {
  unsigned int req_sent:1;
 } f;
 
  unsigned int req_sent:1;
 } f;
 
+static noinline void dsp_fault(void)
+{
+ dsp_msg_t msg;
+
+ f.dsp_cache_inv_virt(worker, sizeof(*worker));
+ printf("dsp crash/fault/corruption:\n");
+ printf("state rdy/reap/done: %u %u %u\n",
+   worker->i_ready, worker->i_reaped, worker->i_done);
+ printf("active/boot: %u %u\n",
+   worker->active, worker->boot_cnt);
+
+ if (f.req_sent) {
+  f.dsp_rpc_recv(&msg);
+  f.req_sent = 0;
+ }
+ f.dsp_logbuf_print();
+ spu_config.iUseThread = 0;
+}
+
 static void thread_work_start(void)
 {
  struct region_mem *mem;
 static void thread_work_start(void)
 {
  struct region_mem *mem;
@@ -84,9 +103,11 @@ static void thread_work_start(void)
 
  f.dsp_cache_inv_virt(&worker->i_done, 64);
  worker->last_boot_cnt = worker->boot_cnt;
 
  f.dsp_cache_inv_virt(&worker->i_done, 64);
  worker->last_boot_cnt = worker->boot_cnt;
+ worker->ram_dirty = spu.bMemDirty;
+ spu.bMemDirty = 0;
 
  mem = (void *)f.region.virt_addr;
 
  mem = (void *)f.region.virt_addr;
- memcpy(&mem->spu_config, &spu_config, sizeof(mem->spu_config));
+ memcpy(&mem->in.spu_config, &spu_config, sizeof(mem->in.spu_config));
 
  DSP_MSG_INIT(&msg, f.compid, CCMD_DOIT, f.region.phys_addr, 0);
  ret = f.dsp_rpc_send(&msg);
 
  DSP_MSG_INIT(&msg, f.compid, CCMD_DOIT, f.region.phys_addr, 0);
  ret = f.dsp_rpc_send(&msg);
@@ -97,6 +118,11 @@ static void thread_work_start(void)
   return;
  }
  f.req_sent = 1;
   return;
  }
  f.req_sent = 1;
+
+#if 0
+ f.dsp_rpc_recv(&msg);
+ f.req_sent = 0;
+#endif
 }
 
 static int thread_get_i_done(void)
 }
 
 static int thread_get_i_done(void)
@@ -110,6 +136,11 @@ static void thread_work_wait_sync(struct work_item *work, int force)
  int limit = 1000;
  int ns_to;
 
  int limit = 1000;
  int ns_to;
 
+ if ((unsigned int)(worker->i_done - worker->i_reaped) > WORK_MAXCNT) {
+  dsp_fault();
+  return;
+ }
+
  while (worker->i_done == worker->i_reaped && limit-- > 0) {
   if (!f.req_sent) {
    printf("dsp: req not sent?\n");
  while (worker->i_done == worker->i_reaped && limit-- > 0) {
   if (!f.req_sent) {
    printf("dsp: req not sent?\n");
@@ -222,7 +253,7 @@ static void init_spu_thread(void)
  }
  mem = (void *)f.region.virt_addr;
 
  }
  mem = (void *)f.region.virt_addr;
 
- memcpy(&mem->spu_config, &spu_config, sizeof(mem->spu_config));
+ memcpy(&mem->in.spu_config, &spu_config, sizeof(mem->in.spu_config));
 
  DSP_MSG_INIT(&init_msg, f.compid, CCMD_INIT, f.region.phys_addr, 0);
  ret = f.dsp_rpc(&init_msg, &msg_in);
 
  DSP_MSG_INIT(&init_msg, f.compid, CCMD_INIT, f.region.phys_addr, 0);
  ret = f.dsp_rpc(&init_msg, &msg_in);
@@ -301,4 +332,23 @@ static void exit_spu_thread(void)
  worker = NULL;
 }
 
  worker = NULL;
 }
 
+/* debug: "access" shared mem from gdb */
+#if 0
+struct region_mem *dbg_dsp_mem;
+
+void dbg_dsp_mem_update(void)
+{
+ struct region_mem *mem;
+
+ if (dbg_dsp_mem == NULL)
+  dbg_dsp_mem = malloc(sizeof(*dbg_dsp_mem));
+ if (dbg_dsp_mem == NULL)
+  return;
+
+ mem = (void *)f.region.virt_addr;
+ f.dsp_cache_inv_virt(mem, sizeof(*mem));
+ memcpy(dbg_dsp_mem, mem, sizeof(*dbg_dsp_mem));
+}
+#endif
+
 // vim:shiftwidth=1:expandtab
 // vim:shiftwidth=1:expandtab
index 8210e63..7c4d565 100644 (file)
@@ -15,10 +15,10 @@ struct region_mem {
   // these are not to be modified by DSP
   SPUCHAN s_chan[24 + 1];
   REVERBInfo rvb;
   // these are not to be modified by DSP
   SPUCHAN s_chan[24 + 1];
   REVERBInfo rvb;
+  SPUConfig spu_config;
  } in;
  int _pad2[128/4 - ((sizeof(struct spu_in) / 4) & (128/4 - 1))];
  struct spu_worker worker;
  } in;
  int _pad2[128/4 - ((sizeof(struct spu_in) / 4) & (128/4 - 1))];
  struct spu_worker worker;
- SPUConfig spu_config;
  // init/debug
  int sizeof_region_mem;
  int offsetof_s_chan1;
  // init/debug
  int sizeof_region_mem;
  int offsetof_s_chan1;
index b0352a9..570da5e 100644 (file)
@@ -37,13 +37,40 @@ struct out_driver *out_current;
 void SetupSound(void) {}
 
 
 void SetupSound(void) {}
 
 
+static void enable_l2_cache(void)
+{
+ volatile uint32_t *L2CFG = (volatile uint32_t *)0x01840000;
+ uint32_t *MARi = (void *)0x01848000;
+ int i;
+
+ // program Memory Attribute Registers
+ // (old c64_tools has the defaults messed up)
+ // 00000000-0fffffff - not configurable
+ // 10000000-7fffffff - system
+ for (i = 0x10; i < 0x80; i++)
+  MARi[i] = 0;
+ // 80000000-9fffffff - RAM
+ for ( ; i < 0xa0; i++)
+  MARi[i] = 1;
+ // 0xa00000-ffffffff - reserved, etc
+ for ( ; i < 0x100; i++)
+  MARi[i] = 0;
+
+ // enable L2 (1 for 32k, 2 for 64k)
+ if (!(*L2CFG & 2)) {
+  *L2CFG = 2;
+  // wait the for the write
+  *L2CFG;
+ }
+}
+
 static void invalidate_cache(struct work_item *work)
 {
  // see comment in writeout_cache()
  //syscalls.cache_inv(work, offsetof(typeof(*work), SSumLR), 1);
 static void invalidate_cache(struct work_item *work)
 {
  // see comment in writeout_cache()
  //syscalls.cache_inv(work, offsetof(typeof(*work), SSumLR), 1);
- syscalls.cache_inv(spu.s_chan, sizeof(spu.s_chan[0]) * 24, 0);
+ syscalls.cache_inv(spu.s_chan, sizeof(spu.s_chan[0]) * 24, 1);
  syscalls.cache_inv(work->SSumLR,
  syscalls.cache_inv(work->SSumLR,
-   sizeof(work->SSumLR[0]) * 2 * work->ns_to, 0);
+   sizeof(work->SSumLR[0]) * 2 * work->ns_to, 1);
 }
 
 static void writeout_cache(struct work_item *work)
 }
 
 static void writeout_cache(struct work_item *work)
@@ -53,7 +80,7 @@ static void writeout_cache(struct work_item *work)
  syscalls.cache_wb(work->SSumLR, sizeof(work->SSumLR[0]) * 2 * ns_to, 1);
  // have to invalidate now, otherwise there is a race between
  // DSP evicting dirty lines and ARM writing new data to this area
  syscalls.cache_wb(work->SSumLR, sizeof(work->SSumLR[0]) * 2 * ns_to, 1);
  // have to invalidate now, otherwise there is a race between
  // DSP evicting dirty lines and ARM writing new data to this area
- syscalls.cache_inv(work, offsetof(typeof(*work), SSumLR), 0);
+ syscalls.cache_inv(work, offsetof(typeof(*work), SSumLR), 1);
 }
 
 static void do_processing(void)
 }
 
 static void do_processing(void)
@@ -112,6 +139,7 @@ static unsigned int exec(dsp_component_cmd_t cmd,
 
  switch (cmd) {
   case CCMD_INIT:
 
  switch (cmd) {
   case CCMD_INIT:
+   enable_l2_cache();
    InitADSR();
 
    spu.spuMemC = mem->spu_ram;
    InitADSR();
 
    spu.spuMemC = mem->spu_ram;
@@ -119,7 +147,7 @@ static unsigned int exec(dsp_component_cmd_t cmd,
    spu.s_chan = mem->in.s_chan;
    spu.rvb = &mem->in.rvb;
    worker = &mem->worker;
    spu.s_chan = mem->in.s_chan;
    spu.rvb = &mem->in.rvb;
    worker = &mem->worker;
-   memcpy(&spu_config, &mem->spu_config, sizeof(spu_config));
+   memcpy(&spu_config, &mem->in.spu_config, sizeof(spu_config));
 
    mem->sizeof_region_mem = sizeof(*mem);
    mem->offsetof_s_chan1 = offsetof(typeof(*mem), in.s_chan[1]);
 
    mem->sizeof_region_mem = sizeof(*mem);
    mem->offsetof_s_chan1 = offsetof(typeof(*mem), in.s_chan[1]);
@@ -131,16 +159,18 @@ static unsigned int exec(dsp_component_cmd_t cmd,
   case CCMD_DOIT:
    worker->active = ACTIVE_CNT;
    worker->boot_cnt++;
   case CCMD_DOIT:
    worker->active = ACTIVE_CNT;
    worker->boot_cnt++;
-   syscalls.cache_wb(&worker->i_done, 64, 1);
-   memcpy(&spu_config, &mem->spu_config, sizeof(spu_config));
+   syscalls.cache_inv(worker, 128, 1);
+   syscalls.cache_wb(&worker->i_done, 128, 1);
+   memcpy(&spu_config, &mem->in.spu_config, sizeof(spu_config));
+
+   if (worker->ram_dirty)
+    // it's faster to do it all than just a 512k buffer
+    syscalls.cache_wbInvAll();
 
    do_processing();
 
 
    do_processing();
 
-   // c64_tools lib does BCACHE_wbInvAll() when it receives mailbox irq,
-   // but invalidate anyway in case c64_tools is ever fixed..
-   // XXX edit: don't bother as reverb is not handled, will fix if needed
-   //syscalls.cache_inv(mem, sizeof(mem->spu_ram) + sizeof(mem->SB), 0);
-   //syscalls.cache_inv(&mem->in, sizeof(mem->in), 0);
+   syscalls.cache_inv(&mem->SB, sizeof(mem->SB), 0);
+   syscalls.cache_inv(&mem->in, sizeof(mem->in), 0);
    break;
 
   default:
    break;
 
   default: