15#ifndef SPU_IRQ_EXPECTED_UNSET
16#define SPU_IRQ_EXPECTED_UNSET 0xffffffffu
19#ifndef SPU_IRQ_EXPECTED_ALIGNED_POLLS
20#define SPU_IRQ_EXPECTED_ALIGNED_POLLS SPU_IRQ_EXPECTED_UNSET
22#ifndef SPU_IRQ_EXPECTED_ALIGNED_FIRST_NONZERO
23#define SPU_IRQ_EXPECTED_ALIGNED_FIRST_NONZERO 0u
25#ifndef SPU_IRQ_EXPECTED_ALIGNED_LAST_NONZERO
26#define SPU_IRQ_EXPECTED_ALIGNED_LAST_NONZERO SPU_IRQ_EXPECTED_UNSET
28#ifndef SPU_IRQ_EXPECTED_ALIGNED_NONZERO_COUNT
29#define SPU_IRQ_EXPECTED_ALIGNED_NONZERO_COUNT 345u
31#ifndef SPU_IRQ_EXPECTED_ALIGNED_SUM
32#define SPU_IRQ_EXPECTED_ALIGNED_SUM 18806188u
35#ifndef SPU_IRQ_EXPECTED_REARM_FIRST_POLLS
36#define SPU_IRQ_EXPECTED_REARM_FIRST_POLLS SPU_IRQ_EXPECTED_UNSET
38#ifndef SPU_IRQ_EXPECTED_REARM_SECOND_POLLS
39#define SPU_IRQ_EXPECTED_REARM_SECOND_POLLS 1u
42#ifndef SPU_IRQ_EXPECTED_MIDBLOCK_HITS
43#define SPU_IRQ_EXPECTED_MIDBLOCK_HITS 2u
45#ifndef SPU_IRQ_EXPECTED_MIDBLOCK_FIRST_POLLS
46#define SPU_IRQ_EXPECTED_MIDBLOCK_FIRST_POLLS SPU_IRQ_EXPECTED_UNSET
49#define SPU_IRQ_TEST_ADDR 0x2000
50#define SPU_IRQ_DUMMY_ADDR 0x7000
51#define SPU_IRQ_POLL_TIMEOUT 2000000u
52#define SPU_IRQ_REARM_TIMEOUT 6000000u
71static void spu_irq_make_sample(
void) {
72 for (
int block = 0; block < 8; block++) {
73 uint8_t *p = &s_irqSample[block * 16];
76 if (block == 0) p[1] = 0x06;
77 if (block == 7) p[1] = 0x03;
78 uint8_t nybble = (uint8_t)((block + 1) & 7);
79 uint8_t packed = (uint8_t)(nybble | (nybble << 4));
80 for (
int i = 2;
i < 16;
i++) p[
i] = packed;
84static void spu_irq_arm(
uint32_t byteAddr) {
87 for (
volatile int i = 0;
i < 120;
i++) ;
106static void spu_irq_quiet_unused_voices(
void) {
107 for (
int v = 0; v < 24; v++) {
123static void spu_irq_prepare(
void) {
125 spu_irq_make_sample();
131 spu_irq_quiet_unused_voices();
135static void spu_irq_start_voice1(
void) {
141static void spu_irq_analyze_capture(SpuIrqMeasurement *m) {
149 uint16_t v = s_capture[
i];
151 if (first == 0xffffffffu) first =
i;
158 m->captureFirstNonzero = first;
159 m->captureLastNonzero = last;
160 m->captureNonzeroCount =
count;
164static void spu_irq_measure_once(
uint32_t irqByteAddr, SpuIrqMeasurement *m) {
166 m->irqAddr = irqByteAddr;
173 spu_wait_status_bit11_flip();
174 spu_irq_arm(irqByteAddr);
175 spu_irq_start_voice1();
178 m->fired = (
m->polls != 0);
180 m->currentVolumeAtFire =
SPU_VOICES[1].currentVolume;
183 spu_irq_analyze_capture(m);
190static void spu_irq_print_measurement(
const char *name,
const SpuIrqMeasurement *m) {
192 "OBS spu_irq %s irq=0x%05lx fired=%lu polls=%lu statusFire=0x%04lx "
193 "ackCleared=%lu statusAck=0x%04lx envx=0x%04lx capFirst=%lu capLast=%lu "
194 "capCount=%lu capSum=0x%08lx\n",
195 name,
m->irqAddr,
m->fired,
m->polls,
m->statusAtFire & 0xffff,
196 m->ackCleared,
m->statusAfterAck & 0xffff,
m->currentVolumeAtFire & 0xffff,
197 m->captureFirstNonzero,
m->captureLastNonzero,
m->captureNonzeroCount,
m->captureSum);
212 spu_irq_print_measurement(
"aligned_block1", &m);
214 uint32_t statusFlagAfterAck =
m.statusAfterAck & 0x0040;
226 SpuIrqMeasurement first;
228 spu_wait_status_bit11_flip();
230 spu_irq_start_voice1();
233 first.fired = (first.polls != 0);
240 uint32_t secondFired = (secondPolls != 0);
245 "OBS spu_irq rearm firstFired=%lu firstPolls=%lu firstStatus=0x%04lx "
246 "firstAck=%lu firstStatusAck=0x%04lx secondFired=%lu secondPolls=%lu "
247 "secondStatus=0x%04lx secondAck=%lu\n",
248 first.fired, first.polls, first.statusAtFire & 0xffff, first.ackCleared,
249 first.statusAfterAck & 0xffff, secondFired, secondPolls, secondStatus & 0xffff,
269 spu_wait_status_bit11_flip();
271 spu_irq_start_voice1();
273 for (
uint32_t attempt = 0; attempt < 8; attempt++) {
277 if (firstPolls == 0) firstPolls = polls;
cester_assert_uint_eq(5, cause1)
__attribute__((weak))
Definition clz.c:56
#define SPU_VOICES
Definition spu.h:42
#define SPU_STATUS
Definition spu.h:106
#define SPU_KEY_ON_LOW
Definition spu.h:88
#define SPU_VOL_MAIN_LEFT
Definition spu.h:84
#define SPU_CTRL
Definition spu.h:104
#define SPU_VOL_MAIN_RIGHT
Definition spu.h:85
#define SPU_IRQ_ADDR
Definition spu.h:101
#define SPU_KEY_ON_HIGH
Definition spu.h:89
#define CESTER_MAYBE_TEST
Definition cop0.c:34
int i
Definition gte-regio.c:297
__asm__(" .section .text.monitorSlotEntry, \"ax\", @progbits\n" " .align 2\n" " .global monitorSlotEntry\n" " .type monitorSlotEntry, @function\n" " .set push\n" " .set noreorder\n" " .set noat\n" "monitorSlotEntry:\n" " mfc0 $v0, $13\n" " nop\n" " andi $v0, $v0, 0x7c\n" " beqz $v0, 1f\n" " srl $v0, $v0, 2\n" " li $v1, " MON_STR(MON_SLOT_EXCMASK) "\n" " srlv $v1, $v1, $v0\n" " andi $v1, $v1, 1\n" " bnez $v1, 2f\n" " nop\n" " jr $ra\n" " nop\n" "1:\n" MON_SLOT_RX_TEST " jr $ra\n" " nop\n" "2:\n" " sw $a0, 0x10($k0)\n" " sw $a1, 0x14($k0)\n" " sw $a2, 0x18($k0)\n" " sw $a3, 0x1c($k0)\n" " mfc0 $a0, $12\n" " nop\n" " sw $a0, 0x8c($k0)\n" " mfc0 $a1, $13\n" " nop\n" " sw $a1, 0x90($k0)\n" " sw $k1, 0x6c($k0)\n" " sw $s0, 0x40($k0)\n" " sw $s1, 0x44($k0)\n" " sw $s2, 0x48($k0)\n" " sw $s3, 0x4c($k0)\n" " sw $s4, 0x50($k0)\n" " sw $s5, 0x54($k0)\n" " sw $s6, 0x58($k0)\n" " sw $s7, 0x5c($k0)\n" " sw $t0, 0x20($k0)\n" " sw $t1, 0x24($k0)\n" " sw $t2, 0x28($k0)\n" " sw $t3, 0x2c($k0)\n" " sw $t4, 0x30($k0)\n" " sw $t5, 0x34($k0)\n" " sw $t6, 0x38($k0)\n" " sw $t7, 0x3c($k0)\n" " sw $t8, 0x60($k0)\n" " sw $t9, 0x64($k0)\n" " sw $gp, 0x70($k0)\n" " sw $sp, 0x74($k0)\n" " sw $fp, 0x78($k0)\n" " mfhi $a0\n" " nop\n" " sw $a0, 0x84($k0)\n" " mflo $a0\n" " nop\n" " sw $a0, 0x88($k0)\n" " move $s0, $ra\n" " la $sp, monitorSlotStack + " MON_STR(MONITOR_SLOT_STACK_WORDS) " * 4 - 16\n" " jal monitorSlotDispatch\n" " nop\n" " lw $k0, 0x108($zero)\n" " move $ra, $s0\n" " lw $k0, 0($k0)\n" " nop\n" " addiu $k0, $k0, 8\n" " lw $a0, 0x84($k0)\n" " lw $a1, 0x88($k0)\n" " mthi $a0\n" " mtlo $a1\n" " lw $a0, 0x10($k0)\n" " lw $a1, 0x14($k0)\n" " lw $a2, 0x18($k0)\n" " lw $a3, 0x1c($k0)\n" " lw $t0, 0x20($k0)\n" " lw $t1, 0x24($k0)\n" " lw $t2, 0x28($k0)\n" " lw $t3, 0x2c($k0)\n" " lw $t4, 0x30($k0)\n" " lw $t5, 0x34($k0)\n" " lw $t6, 0x38($k0)\n" " lw $t7, 0x3c($k0)\n" " lw $t8, 0x60($k0)\n" " lw $t9, 0x64($k0)\n" " lw $s0, 0x40($k0)\n" " lw $sp, 0x74($k0)\n" " jr $ra\n" " nop\n" " .set pop\n" " .size monitorSlotEntry, . - monitorSlotEntry\n" " .previous\n")
m
Definition gentable.py:52
spu_tests
Definition spu-adpcm-edge.c:189
#define SPU_IRQ_POLL_TIMEOUT
Definition spu-irq.c:51
#define SPU_IRQ_TEST_ADDR
Definition spu-irq.c:49
#define SPU_IRQ_EXPECTED_REARM_SECOND_POLLS
Definition spu-irq.c:39
spu_irq_expect_u32("midblock.hits", SPU_IRQ_EXPECTED_MIDBLOCK_HITS, hits)
CESTER_BODY(typedef struct { uint32_t irqAddr;uint32_t fired;uint32_t polls;uint32_t statusAtFire;uint32_t statusAfterAck;uint32_t ackCleared;uint32_t currentVolumeAtFire;uint32_t captureFirstNonzero;uint32_t captureLastNonzero;uint32_t captureNonzeroCount;uint32_t captureSum;} SpuIrqMeasurement;static uint8_t s_irqSample __attribute__((aligned(4)));static void spu_irq_make_sample(void) { for(int block=0;block< 8;block++) { uint8_t *p=&s_irqSample[block *16];p[0]=0x00;p[1]=0x00;if(block==0) p[1]=0x06;if(block==7) p[1]=0x03;uint8_t nybble=(uint8_t)((block+1) &7);uint8_t packed=(uint8_t)(nybble|(nybble<< 4));for(int i=2;i< 16;i++) p[i]=packed;} } static void spu_irq_arm(uint32_t byteAddr) { SPU_IRQ_ADDR=(uint16_t)(byteAddr > > 3);SPU_CTRL=(SPU_CTRL &~0x0030)|0x8000|0x4000|0x0040;for(volatile int i=0;i< 120;i++) ;} static uint32_t spu_irq_ack_by_disable(void) { SPU_CTRL=SPU_CTRL &~0x0040;for(uint32_t i=0;i< 100000;i++) { if((SPU_STATUS &0x0040)==0) return 1;} return 0;} static uint32_t spu_irq_poll_until(uint32_t maxPolls) { for(uint32_t i=0;i< maxPolls;i++) { if(SPU_STATUS &0x0040) return i+1;__asm__ volatile("");} return 0;} static void spu_irq_quiet_unused_voices(void) { for(int v=0;v< 24;v++) { SPU_VOICES[v].volumeLeft=0;SPU_VOICES[v].volumeRight=0;SPU_VOICES[v].sampleRate=0x1000;SPU_VOICES[v].sampleStartAddr=SPU_IRQ_DUMMY_ADDR > > 3;SPU_VOICES[v].sampleRepeatAddr=SPU_IRQ_DUMMY_ADDR > > 3;SPU_VOICES[v].adsrLo=0x000f;SPU_VOICES[v].adsrHi=0x1fc0;} SPU_KEY_OFF_LOW=0;SPU_KEY_OFF_HIGH=0;SPU_KEY_ON_LOW=0xffff;SPU_KEY_ON_HIGH=0x00ff;spu_busy_wait(200000);} static void spu_irq_prepare(void) { spu_reset_quiet();spu_irq_make_sample();spu_write_sync(SPU_IRQ_DUMMY_ADDR, kAdpcmSilent, sizeof(kAdpcmSilent));spu_write_sync(SPU_IRQ_TEST_ADDR, s_irqSample, sizeof(s_irqSample));SPU_CTRL=0x8000|0x4000;SPU_VOL_MAIN_LEFT=0;SPU_VOL_MAIN_RIGHT=0;spu_irq_quiet_unused_voices();(void) spu_irq_ack_by_disable();} static void spu_irq_start_voice1(void) { SPU_VOICES[1].volumeLeft=0;SPU_VOICES[1].volumeRight=0;spu_voice1_keyon(SPU_IRQ_TEST_ADDR, 0x1000);} static void spu_irq_analyze_capture(SpuIrqMeasurement *m) { uint32_t first=0xffffffffu;uint32_t last=0;uint32_t count=0;uint32_t sum=0;spu_read_sync(0x0800, s_capture, 1024);for(uint32_t i=0;i< 512;i++) { uint16_t v=s_capture[i];if(v !=0) { if(first==0xffffffffu) first=i;last=i;count++;sum+=v;} } m->captureFirstNonzero=first;m->captureLastNonzero=last;m->captureNonzeroCount=count;m->captureSum=sum;} static void spu_irq_measure_once(uint32_t irqByteAddr, SpuIrqMeasurement *m) { spu_irq_prepare();m->irqAddr=irqByteAddr;spu_wait_status_bit11_flip();spu_irq_arm(irqByteAddr);spu_irq_start_voice1();m->polls=spu_irq_poll_until(SPU_IRQ_POLL_TIMEOUT);m->fired=(m->polls !=0);m->statusAtFire=SPU_STATUS;m->currentVolumeAtFire=SPU_VOICES[1].currentVolume;m->ackCleared=spu_irq_ack_by_disable();m->statusAfterAck=SPU_STATUS;spu_irq_analyze_capture(m);SPU_KEY_OFF_LOW=0xffff;SPU_KEY_OFF_HIGH=0xffff;muteSpu();} static void spu_irq_print_measurement(const char *name, const SpuIrqMeasurement *m) { ramsyscall_printf("OBS spu_irq %s irq=0x%05lx fired=%lu polls=%lu statusFire=0x%04lx " "ackCleared=%lu statusAck=0x%04lx envx=0x%04lx capFirst=%lu capLast=%lu " "capCount=%lu capSum=0x%08lx\n", name, m->irqAddr, m->fired, m->polls, m->statusAtFire &0xffff, m->ackCleared, m->statusAfterAck &0xffff, m->currentVolumeAtFire &0xffff, m->captureFirstNonzero, m->captureLastNonzero, m->captureNonzeroCount, m->captureSum);} static void spu_irq_expect_u32(const char *name, uint32_t expected, uint32_t got) { if(expected==SPU_IRQ_EXPECTED_UNSET) { ramsyscall_printf("OBS spu_irq expected %s=%lu\n", name, got);} else { cester_assert_uint_eq(expected, got);} }[128])
Definition spu-irq.c:54
#define SPU_IRQ_EXPECTED_MIDBLOCK_FIRST_POLLS
Definition spu-irq.c:46
void spu_irq_ack_by_disable()
SPU_KEY_OFF_LOW
Definition spu-irq.c:288
#define SPU_IRQ_EXPECTED_MIDBLOCK_HITS
Definition spu-irq.c:43
#define SPU_IRQ_EXPECTED_REARM_FIRST_POLLS
Definition spu-irq.c:36
SPU_KEY_OFF_HIGH
Definition spu-irq.c:289
#define SPU_IRQ_EXPECTED_ALIGNED_LAST_NONZERO
Definition spu-irq.c:26
#define SPU_IRQ_DUMMY_ADDR
Definition spu-irq.c:50
#define SPU_IRQ_REARM_TIMEOUT
Definition spu-irq.c:52
#define SPU_IRQ_EXPECTED_ALIGNED_POLLS
Definition spu-irq.c:20
#define SPU_IRQ_EXPECTED_ALIGNED_FIRST_NONZERO
Definition spu-irq.c:23
#define SPU_IRQ_EXPECTED_ALIGNED_NONZERO_COUNT
Definition spu-irq.c:29
#define SPU_IRQ_EXPECTED_ALIGNED_SUM
Definition spu-irq.c:32
#define SPU_IRQ_EXPECTED_UNSET
Definition spu-irq.c:16
ramsyscall_printf("OBS spu_irq midblock irq=0x%05x hits=%lu firstPolls=%lu\n", SPU_IRQ_TEST_ADDR+8, hits, firstPolls)
spu_write_sync(0x1000, s_upload, 128)
spu_read_sync(0x1000, s_readback, 0x80)
static const void size_t count
Definition syscalls.h:146
void uint32_t(classId, spec)