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 = \
\r
spu.spuAddr += 2;\r
spu.spuAddr &= 0x7fffe;\r
+ spu.bMemDirty = 1;\r
}\r
\r
////////////////////////////////////////////////////////////////////////\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
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
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
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];
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);
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;
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);
return;
}
f.req_sent = 1;
+
+#if 0
+ f.dsp_rpc_recv(&msg);
+ f.req_sent = 0;
+#endif
}
static int thread_get_i_done(void)
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");
}
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);
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
// 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;
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)
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)
switch (cmd) {
case CCMD_INIT:
+ enable_l2_cache();
InitADSR();
spu.spuMemC = mem->spu_ram;
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]);
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: