From 0c1151feca09186ec61485436912a3e563c40b54 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 2 Feb 2015 04:13:30 +0200 Subject: [PATCH] spu: c64x: fix cache handling, enable l2 --- plugins/dfsound/Makefile.c64p | 4 ++- plugins/dfsound/dma.c | 2 ++ plugins/dfsound/externals.h | 1 + plugins/dfsound/freeze.c | 1 + plugins/dfsound/spu.c | 2 ++ plugins/dfsound/spu_c64x.c | 54 ++++++++++++++++++++++++++++-- plugins/dfsound/spu_c64x.h | 2 +- plugins/dfsound/spu_c64x_dspcode.c | 52 ++++++++++++++++++++++------ 8 files changed, 103 insertions(+), 15 deletions(-) diff --git a/plugins/dfsound/Makefile.c64p b/plugins/dfsound/Makefile.c64p index 45fe76a4..5b977810 100644 --- a/plugins/dfsound/Makefile.c64p +++ b/plugins/dfsound/Makefile.c64p @@ -5,7 +5,9 @@ endif 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 = \ diff --git a/plugins/dfsound/dma.c b/plugins/dfsound/dma.c index 4798a19b..43019f1d 100644 --- a/plugins/dfsound/dma.c +++ b/plugins/dfsound/dma.c @@ -71,6 +71,7 @@ void CALLBACK SPUwriteDMA(unsigned short val) spu.spuAddr += 2; spu.spuAddr &= 0x7fffe; + spu.bMemDirty = 1; } //////////////////////////////////////////////////////////////////////// @@ -83,6 +84,7 @@ void CALLBACK SPUwriteDMAMem(unsigned short *pusPSXMem, int iSize, int i; do_samples_if_needed(cycles, 1); + spu.bMemDirty = 1; if(spu.spuAddr + iSize*2 < 0x80000) { diff --git a/plugins/dfsound/externals.h b/plugins/dfsound/externals.h index 8bbf4e02..2db75ac2 100644 --- a/plugins/dfsound/externals.h +++ b/plugins/dfsound/externals.h @@ -189,6 +189,7 @@ typedef struct int decode_dirty_ch; unsigned int bSpuInit:1; unsigned int bSPUIsOpen:1; + unsigned int bMemDirty:1; // had external write to SPU RAM unsigned int dwNoiseVal; // global noise generator unsigned int dwNoiseCount; diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c index 72c9d22e..43e6535c 100644 --- a/plugins/dfsound/freeze.c +++ b/plugins/dfsound/freeze.c @@ -279,6 +279,7 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF, memcpy(spu.spuMem,pF->cSPURam,0x80000); // get ram memcpy(spu.regArea,pF->cSPUPort,0x200); + spu.bMemDirty = 1; if(pF->xaS.nsamples<=4032) // start xa again SPUplayADPCMchannel(&pF->xaS); diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index 193a5d0d..8e41d50f 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -842,6 +842,7 @@ static struct spu_worker { 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]; @@ -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; + //printf("done: %d use: %d dsp: %u/%u\n", done, used_space, // worker->boot_cnt, worker->i_done); diff --git a/plugins/dfsound/spu_c64x.c b/plugins/dfsound/spu_c64x.c index be10a6bb..e0aa0da2 100644 --- a/plugins/dfsound/spu_c64x.c +++ b/plugins/dfsound/spu_c64x.c @@ -47,6 +47,25 @@ static struct { 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; @@ -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; + worker->ram_dirty = spu.bMemDirty; + spu.bMemDirty = 0; 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); @@ -97,6 +118,11 @@ static void thread_work_start(void) return; } f.req_sent = 1; + +#if 0 + f.dsp_rpc_recv(&msg); + f.req_sent = 0; +#endif } 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; + 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"); @@ -222,7 +253,7 @@ static void init_spu_thread(void) } 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); @@ -301,4 +332,23 @@ static void exit_spu_thread(void) 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 diff --git a/plugins/dfsound/spu_c64x.h b/plugins/dfsound/spu_c64x.h index 8210e63a..7c4d5659 100644 --- a/plugins/dfsound/spu_c64x.h +++ b/plugins/dfsound/spu_c64x.h @@ -15,10 +15,10 @@ struct region_mem { // 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; - SPUConfig spu_config; // init/debug int sizeof_region_mem; int offsetof_s_chan1; diff --git a/plugins/dfsound/spu_c64x_dspcode.c b/plugins/dfsound/spu_c64x_dspcode.c index b0352a9f..570da5ed 100644 --- a/plugins/dfsound/spu_c64x_dspcode.c +++ b/plugins/dfsound/spu_c64x_dspcode.c @@ -37,13 +37,40 @@ struct out_driver *out_current; 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); - 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, - 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) @@ -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_inv(work, offsetof(typeof(*work), SSumLR), 0); + syscalls.cache_inv(work, offsetof(typeof(*work), SSumLR), 1); } static void do_processing(void) @@ -112,6 +139,7 @@ static unsigned int exec(dsp_component_cmd_t cmd, switch (cmd) { case CCMD_INIT: + enable_l2_cache(); 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; - 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]); @@ -131,16 +159,18 @@ static unsigned int exec(dsp_component_cmd_t cmd, 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(); - // 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: -- 2.39.5