Add interrupts to MulticoreRunHaltStepiTest.
[riscv-tests.git] / debug / programs / multicore.c
1 #include <stdint.h>
2
3 #include "init.h"
4
5 typedef struct {
6 int counter;
7 } atomic_t;
8
9 static inline int atomic_xchg(atomic_t *v, int n)
10 {
11 register int c;
12
13 __asm__ __volatile__ (
14 "amoswap.w.aqrl %0, %2, %1"
15 : "=r" (c), "+A" (v->counter)
16 : "r" (n));
17 return c;
18 }
19
20 static inline void mb(void)
21 {
22 __asm__ __volatile__ ("fence");
23 }
24
25 void get_lock(atomic_t *lock)
26 {
27 while (atomic_xchg(lock, 1) == 1)
28 ;
29 mb();
30 }
31
32 void put_lock(atomic_t *lock)
33 {
34 mb();
35 atomic_xchg(lock, 0);
36 }
37
38 static atomic_t buf_lock = { .counter = 0 };
39 static char buf[32];
40 static int buf_initialized;
41 static unsigned hart_count[NHARTS];
42 static unsigned interrupt_count[NHARTS];
43
44 static unsigned delta = 0x100;
45 void *increment_count(unsigned hartid, unsigned mcause, void *mepc, void *sp)
46 {
47 interrupt_count[hartid]++;
48 MTIMECMP[hartid] = MTIME + delta;
49 return mepc;
50 }
51
52 int main()
53 {
54 uint32_t hartid = csr_read(mhartid);
55 hart_count[hartid] = 0;
56 interrupt_count[hartid] = 0;
57
58 set_trap_handler(increment_count);
59 // Despite being memory-mapped, there appears to be one mtimecmp
60 // register per hart. The spec does not address this.
61 MTIMECMP[hartid] = MTIME + delta;
62 enable_timer_interrupts();
63
64 while (1) {
65 get_lock(&buf_lock);
66
67 if (!buf_initialized) {
68 for (unsigned i = 0; i < sizeof(buf); i++) {
69 buf[i] = 'A' + (i % 26);
70 }
71 buf_initialized = 1;
72 }
73
74 char first = buf[0];
75 int offset = (first & ~0x20) - 'A';
76 for (unsigned i = 0; i < sizeof(buf); i++) {
77 while (buf[i] != (first - offset + ((offset + i) % 26)))
78 ;
79
80 if (hartid & 1)
81 buf[i] = 'A' + ((i + hartid + hart_count[hartid]) % 26);
82 else
83 buf[i] = 'a' + ((i + hartid + hart_count[hartid]) % 26);
84 }
85 put_lock(&buf_lock);
86 hart_count[hartid]++;
87 }
88 }