interrupts: Isolated runtime data
[simavr] / tests / tests.c
1 #include "tests.h"
2 #include "sim_avr.h"
3 #include "sim_elf.h"
4 #include "sim_core.h"
5 #include "avr_uart.h"
6 #include <stdio.h>
7 #include <setjmp.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdarg.h>
11 #include <unistd.h>
12
13 avr_cycle_count_t tests_cycle_count = 0;
14 int tests_disable_stdout = 1;
15
16 static char *test_name = "(uninitialized test)";
17 static FILE *orig_stderr = NULL;
18 static int finished = 0;
19
20 static void atexit_handler(void) {
21         if (!finished)
22                 _fail(NULL, 0, "Test exit without indicating success.");
23 }
24
25 void tests_success(void) {
26         if (orig_stderr)
27                 stderr = orig_stderr;
28         fprintf(stderr, "OK: %s\n", test_name);
29         finished = 1;
30 }
31
32 void tests_init(int argc, char **argv) {
33         test_name = strdup(argv[0]);
34         atexit(atexit_handler);
35 }
36
37 static avr_cycle_count_t
38 cycle_timer_longjmp_cb(struct avr_t *avr, avr_cycle_count_t when, void *param) {
39         jmp_buf *jmp = param;
40         longjmp(*jmp, LJR_CYCLE_TIMER);
41 }
42
43 static jmp_buf *special_deinit_jmpbuf = NULL;
44
45 static void special_deinit_longjmp_cb(struct avr_t *avr) {
46         if (special_deinit_jmpbuf)
47                 longjmp(*special_deinit_jmpbuf, LJR_SPECIAL_DEINIT);
48 }
49
50 static int my_avr_run(avr_t * avr)
51 {
52         if (avr->state == cpu_Stopped)
53                 return avr->state;
54
55         uint16_t new_pc = avr->pc;
56
57         if (avr->state == cpu_Running)
58                 new_pc = avr_run_one(avr);
59
60         // if we just re-enabled the interrupts...
61         // double buffer the I flag, to detect that edge
62         if (avr->sreg[S_I] && !avr->i_shadow)
63                 avr->interrupts.pending_wait++;
64         avr->i_shadow = avr->sreg[S_I];
65
66         // run the cycle timers, get the suggested sleep time
67         // until the next timer is due
68         avr_cycle_count_t sleep = avr_cycle_timer_process(avr);
69
70         avr->pc = new_pc;
71
72         if (avr->state == cpu_Sleeping) {
73                 if (!avr->sreg[S_I]) {
74                         printf("simavr: sleeping with interrupts off, quitting gracefully\n");
75                         avr_terminate(avr);
76                         fail("Test case error: special_deinit() returned?");
77                         exit(0);
78                 }
79                 /*
80                  * try to sleep for as long as we can (?)
81                  */
82                 // uint32_t usec = avr_cycles_to_usec(avr, sleep);
83                 // printf("sleep usec %d cycles %d\n", usec, sleep);
84                 // usleep(usec);
85                 avr->cycle += 1 + sleep;
86         }
87         // Interrupt servicing might change the PC too, during 'sleep'
88         if (avr->state == cpu_Running || avr->state == cpu_Sleeping)
89                 avr_service_interrupts(avr);
90         
91         // if we were stepping, use this state to inform remote gdb
92
93         return avr->state;
94 }
95
96 avr_t *tests_init_avr(const char *elfname) {
97         tests_cycle_count = 0;
98         if (tests_disable_stdout) {
99                 orig_stderr = stderr;
100                 fclose(stdout);
101                 stderr = stdout;
102         }
103         elf_firmware_t fw;
104         if (elf_read_firmware(elfname, &fw))
105                 fail("Failed to read ELF firmware \"%s\"", elfname);
106         avr_t *avr = avr_make_mcu_by_name(fw.mmcu);
107         if (!avr)
108                 fail("Creating AVR failed.");
109         avr_init(avr);
110         avr_load_firmware(avr, &fw);
111         return avr;
112 }
113
114 int tests_run_test(avr_t *avr, unsigned long run_usec) {
115         if (!avr)
116                 fail("Internal test error: avr == NULL in run_test()");
117         // register a cycle timer to fire after 100 seconds (simulation time);
118         // assert that the simulation has not finished before that.
119         jmp_buf jmp;
120         special_deinit_jmpbuf = &jmp;
121         avr->special_deinit = special_deinit_longjmp_cb;
122         avr_cycle_timer_register_usec(avr, run_usec,
123                                       cycle_timer_longjmp_cb, &jmp);
124         int reason = setjmp(jmp);
125         tests_cycle_count = avr->cycle;
126         if (reason == 0) {
127                 // setjmp() returned directly, run avr
128                 while (1)
129                         my_avr_run(avr);
130         } else if (reason == 1) {
131                 // returned from longjmp(); cycle timer fired
132                 return reason;
133         } else if (reason == 2) {
134                 // returned from special deinit, avr stopped
135                 return reason;
136         }
137         fail("Error in test case: Should never reach this.");
138         return 0;       
139 }
140
141 int tests_init_and_run_test(const char *elfname, unsigned long run_usec) {
142         avr_t *avr = tests_init_avr(elfname);
143         return tests_run_test(avr, run_usec);
144 }
145
146 struct output_buffer {
147         char *str;
148         int currlen;
149         int alloclen;
150         int maxlen;
151 };
152
153 /* static void buf_output_cb(avr_t *avr, avr_io_addr_t addr, uint8_t v, */
154 /*                        void *param) { */
155 static void buf_output_cb(struct avr_irq_t *irq, uint32_t value, void *param) {
156         struct output_buffer *buf = param;
157         if (!buf)
158                 fail("Internal error: buf == NULL in buf_output_cb()");
159         if (buf->currlen > buf->alloclen-1)
160                 fail("Internal error");
161         if (buf->alloclen == 0)
162                 fail("Internal error");
163         if (buf->currlen == buf->alloclen-1) {
164                 buf->alloclen *= 2;
165                 buf->str = realloc(buf->str, buf->alloclen);
166         }
167         buf->str[buf->currlen++] = value;
168         buf->str[buf->currlen] = 0;
169 }
170
171 static void init_output_buffer(struct output_buffer *buf) {
172         buf->str = malloc(128);
173         buf->str[0] = 0;
174         buf->currlen = 0;
175         buf->alloclen = 128;
176         buf->maxlen = 4096;
177 }
178
179 void tests_assert_uart_receive_avr(avr_t *avr,
180                                unsigned long run_usec,
181                                const char *expected,
182                                char uart) {
183         struct output_buffer buf;
184         init_output_buffer(&buf);
185
186         avr_irq_register_notify(avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUTPUT),
187                                 buf_output_cb, &buf);
188         enum tests_finish_reason reason = tests_run_test(avr, run_usec);
189         if (reason == LJR_CYCLE_TIMER) {
190                 if (strcmp(buf.str, expected) == 0) {
191                         _fail(NULL, 0, "Simulation did not finish within %lu simulated usec. "
192                              "UART output is correct and complete.", run_usec);
193                 }
194                 _fail(NULL, 0, "Simulation did not finish within %lu simulated usec. "
195                      "UART output so far: \"%s\"", run_usec, buf.str);
196         }
197         if (strcmp(buf.str, expected) != 0)
198                 _fail(NULL, 0, "UART outputs differ: expected \"%s\", got \"%s\"", expected, buf.str);
199 }
200
201 void tests_assert_uart_receive(const char *elfname,
202                                unsigned long run_usec,
203                                const char *expected,
204                                char uart) {
205         avr_t *avr = tests_init_avr(elfname);
206
207         tests_assert_uart_receive_avr(avr,
208                                run_usec,
209                                expected,
210                                uart);
211 }
212
213 void tests_assert_cycles_at_least(unsigned long n) {
214         if (tests_cycle_count < n)
215                 _fail(NULL, 0, "Program ran for too few cycles (%"
216                       PRI_avr_cycle_count " < %lu)", tests_cycle_count, n);
217 }
218
219 void tests_assert_cycles_at_most(unsigned long n) {
220         if (tests_cycle_count > n)
221                 _fail(NULL, 0, "Program ran for too many cycles (%"
222                       PRI_avr_cycle_count " > %lu)", tests_cycle_count, n);
223 }
224
225 void tests_assert_cycles_between(unsigned long min, unsigned long max) {
226         tests_assert_cycles_at_least(min);
227         tests_assert_cycles_at_most(max);
228 }
229
230 void _fail(const char *filename, int linenum, const char *fmt, ...) {
231         if (orig_stderr)
232                 stderr = orig_stderr;
233
234         if (filename)
235                 fprintf(stderr, "%s:%d: ", filename, linenum);
236
237         fprintf(stderr, "Test ");
238         if (test_name)
239                 fprintf(stderr, "%s ", test_name);
240         fprintf(stderr, "FAILED.\n");
241
242         if (filename)
243                 fprintf(stderr, "%s:%d: ", filename, linenum);
244
245         va_list va;
246         va_start(va, fmt);
247         vfprintf(stderr, fmt, va);
248         putc('\n', stderr);
249
250         finished = 1;
251         _exit(1);
252 }