OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

[/] [openarty/] [trunk/] [sw/] [board/] [cputest.c] - Blame information for rev 49

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 41 dgisselq
///////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    cputest.c
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     To test the CPU, it's instructions, cache, and pipeline, to make
8
//              certain that it works.  This includes testing that each of the
9
//      instructions works, as well as any strange instruction combinations.
10
//
11
//
12
// Creator:     Dan Gisselquist, Ph.D.
13
//              Gisselquist Technology, LLC
14
//
15
///////////////////////////////////////////////////////////////////////////////
16
//
17
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
18
//
19
// This program is free software (firmware): you can redistribute it and/or
20
// modify it under the terms of  the GNU General Public License as published
21
// by the Free Software Foundation, either version 3 of the License, or (at
22
// your option) any later version.
23
//
24
// This program is distributed in the hope that it will be useful, but WITHOUT
25
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
26
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
27
// for more details.
28
//
29
// License:     GPL, v3, as defined and found on www.gnu.org,
30
//              http://www.gnu.org/licenses/gpl.html
31
//
32
//
33
///////////////////////////////////////////////////////////////////////////////
34
//
35
//
36 49 dgisselq
#include "zipcpu.h"
37 41 dgisselq
#include "zipsys.h"
38
#include "artyboard.h"
39
 
40
#ifndef NULL
41
#define NULL    (void *)0
42
#endif
43
 
44
static volatile int     *const UARTTX = &((IOSPACE *)0x0100)->io_uart_tx,
45
                        *const UART_CTRL = &((IOSPACE *)0x0100)->io_auxsetup;
46 49 dgisselq
static volatile int * const PIC = (volatile int *)0xff000000;
47 41 dgisselq
static const int        INT_UARTTX = SYSINT_UARTTX; // 0x2000;
48 49 dgisselq
static volatile int     *const COUNTER = &((ZIPSYS *)ZIPSYS_ADDR)->z_m.ac_ck;
49 41 dgisselq
 
50
#define HAVE_COUNTER
51
#define HAVE_SCOPE
52
#define SCOPEc  sys->io_scope[0].s_ctrl
53
#define SCOPE_DELAY             4
54
#define TRIGGER_SCOPE_NOW       (SCOPE_TRIGGER|SCOPE_DELAY)
55
#define PREPARE_SCOPE           SCOPE_DELAY
56
 
57
unsigned        zip_ucc(void);
58 49 dgisselq
unsigned        zip_cc(void);
59 41 dgisselq
void            zip_save_context(int *);
60
void            zip_halt(void);
61
 
62
 
63
void    txchr(char v);
64
void    txstr(const char *str);
65
void    txhex(int num);
66
void    tx4hex(int num);
67
 
68
 
69
asm("\t.section\t.start\n"
70
        "\t.global\t_start\n"
71
        "\t.type\t_start,@function\n"
72
"_start:\n"
73
        "\tCLR\tR0\n"
74
        "\tCLR\tR1\n"
75
        "\tCLR\tR2\n"
76
        "\tCLR\tR3\n"
77
        "\tCLR\tR4\n"
78
        "\tCLR\tR5\n"
79
        "\tCLR\tR6\n"
80
        "\tCLR\tR7\n"
81
        "\tCLR\tR8\n"
82
        "\tCLR\tR9\n"
83
        "\tCLR\tR10\n"
84
        "\tCLR\tR11\n"
85
        "\tCLR\tR12\n"
86
        "\tLDI\t_top_of_stack,SP\n"
87
        "\tCLR\tCC\n"
88
        "\tMOV\tbusy_failure(PC),R0\n"
89
        "\tBRA\tentry\n"
90
"busy_failure:\n"
91
        "\tBUSY\n"
92
        "\t.section\t.text");
93
 
94
#ifdef  HAVE_COUNTER
95
#define MARKSTART       start_time = *COUNTER
96
#define MARKSTOP        stop_time  = *COUNTER
97
#else
98
#ifdef  HAVE_TIMER
99
#define MARKSTART       start_time = *TIMER
100
#define MARKSTOP        stop_time  = *TIMER
101
#else
102
#define MARKSTART
103
#define MARKSTOP
104
#endif
105
#endif
106
 
107
 
108
extern  int     run_test(void *pc, void *stack);
109
asm("\t.text\n\t.global\trun_test\n"
110
        "\t.type\trun_test,@function\n"
111
"run_test:\n"
112
        "\tCLR\tR3\n"
113
        "\tMOV\ttest_return(PC),uR0\n"
114
        "\tMOV\tR3,uR1\n"
115
        "\tMOV\tR3,uR2\n"
116
        "\tMOV\tR3,uR3\n"
117
        "\tMOV\tR3,uR4\n"
118
        "\tMOV\tR3,uR5\n"
119
        "\tMOV\tR3,uR6\n"
120
        "\tMOV\tR3,uR7\n"
121
        "\tMOV\tR3,uR8\n"
122
        "\tMOV\tR3,uR9\n"
123
        "\tMOV\tR3,uR10\n"
124 49 dgisselq
        "\tMOV\tR3,uR11\n"
125
        "\tMOV\tR3,uR12\n"
126 41 dgisselq
        "\tMOV\tR2,uSP\n"       // uSP = stack
127
        "\tMOV\t0x20+R3,uCC\n"  // Clear uCC of all but the GIE bit
128
        "\tMOV\tR1,uPC\n"       // uPC = pc
129
        "\tRTU\n"
130
"test_return:\n"
131
        "\tMOV\tuR1,R1\n"
132
        "\tAND\t0xffffffdf,CC\n"
133
        // Works with 5 NOOPS, works with 3 NOOPS, works with 1 NOOP
134
        "\tJMP\tR0\n");
135
 
136
extern  int     idle_test(void);
137
asm("\t.text\n\t.global\tidle_test\n"
138
        "\t.type\tidle_test,@function\n"
139
"idle_test:\n"
140
        "\tCLR\tR1\n"
141
        "\tMOV\tidle_loop(PC),uR0\n"
142
        "\tMOV\tR1,uR1\n"
143
        "\tMOV\tR1,uR2\n"
144
        "\tMOV\tR1,uR3\n"
145
        "\tMOV\tR1,uR4\n"
146
        "\tMOV\tR1,uR5\n"
147
        "\tMOV\tR1,uR6\n"
148
        "\tMOV\tR1,uR7\n"
149
        "\tMOV\tR1,uR8\n"
150
        "\tMOV\tR1,uR9\n"
151
        "\tMOV\tR1,uR10\n"
152
        "\tMOV\tR1,uR11\n"
153
        "\tMOV\tR1,uR12\n"
154
        "\tMOV\tR1,uSP\n"
155
        "\tMOV\t0x20+R1,uCC\n"
156
        "\tMOV\tidle_loop(PC),uPC\n"
157
        "\tWAIT\n"
158
        "\tMOV uPC,R1\n"
159
        "\tCMP idle_loop(PC),R1\n"
160
        "\tLDI   0,R1\n"
161
        "\tLDI.NZ 1,R1\n"
162
        "\nRETN\n"
163
"idle_loop:\n"
164
        "\tWAIT\n"
165
        "\tBRA idle_loop\n");
166
 
167
void    break_one(void);
168
asm("\t.text\n\t.global\tbreak_one\n"
169
        "\t.type\tbreak_one,@function\n"
170
"break_one:\n"
171
        "\tLDI\t0,R1\n"
172
        "\tBREAK\n"
173
        "\tLDI\t1,R1\n" // Test fails
174
        "\tJMP\tR0");
175
 
176
void    break_two(void);
177
        // Can we stop a break before we hit it?
178
asm("\t.text\n\t.global\tbreak_two\n"
179
        "\t.type\tbreak_two,@function\n"
180
"break_two:\n"
181
        "\tLDI\t0,R1\n"
182
        "\tJMP\tR0\n"
183
        "\tBREAK\n");
184
 
185 49 dgisselq
void    break_three(void);
186
        // Can we jump to a break, and still have the uPC match
187
asm("\t.text\n\t.global\tbreak_three\n"
188
        "\t.type\tbreak_three,@function\n"
189
        // R1 = 0 by default from calling.  This will return as though
190
        // we had succeeded.
191
"break_three:\n"
192
        "\tBREAK\n");
193
 
194 41 dgisselq
void    early_branch_test(void);
195
asm("\t.text\n\t.global\tearly_branch_test\n"
196
        "\t.type\tearly_branch_test,@function\n"
197
"early_branch_test:\n"
198
        "\tLDI\t1,R1\n"
199
        "\tBRA\t_eb_a\n"
200
        "\tBREAK\n"
201
"_eb_a:\n"
202
        "\tLDI\t2,R1\n"
203
        "\tBRA\t_eb_b\n"
204
        "\tNOP\n"
205
        "\tBREAK\n"
206
"_eb_b:\n"
207
        "\tLDI\t3,R1\n"
208
        "\tBRA\t_eb_c\n"
209
        "\tNOP\n"
210
        "\tNOP\n"
211
        "\tBREAK\n"
212
"_eb_c:\n"
213
        "\tLDI\t4,R1\n"
214
        "\tBRA\t_eb_d\n"
215
        "\tNOP\n"
216
        "\tNOP\n"
217
        "\tNOP\n"
218
        "\tBREAK\n"
219
"_eb_d:\n"
220
        "\tLDI\t5,R1\n"
221
        "\tBRA\t_eb_e\n"
222
        "\tNOP\n"
223
        "\tNOP\n"
224
        "\tNOP\n"
225
        "\tNOP\n"
226
        "\tBREAK\n"
227
"_eb_e:\n"
228
        "\tLDI\t6,R1\n"
229
        "\tBRA\t_eb_f\n"
230
        "\tNOP\n"
231
        "\tNOP\n"
232
        "\tNOP\n"
233
        "\tNOP\n"
234
        "\tNOP\n"
235
        "\tBREAK\n"
236
"_eb_f:\n"
237
        "\tLDI\t0,R1\n"
238
        "\tJMP\tR0");
239
 
240
void    trap_test_and(void);
241
asm("\t.text\n\t.global\ttrap_test_and\n"
242
        "\t.type\ttrap_test_and,@function\n"
243
"trap_test_and:\n"
244
        "\tLDI\t0,R1\n"
245
        "\tAND\t0xffffffdf,CC\n"
246
        "\tLDI\t1,R1\n" // Test fails
247
        "\tJMP\tR0");
248
 
249
void    trap_test_clr(void);
250
asm("\t.text\n\t.global\ttrap_test_clr\n"
251
        "\t.type\ttrap_test_clr,@function\n"
252
"trap_test_clr:\n"
253
        "\tLDI\t0,R1\n"
254
        "\tCLR\tCC\n"
255
        "\tLDI\t1,R1\n" // Test fails
256
        "\tJMP\tR0");
257
 
258
void    overflow_test(void);
259
asm("\t.text\n\t.global\toverflow_test\n"
260
        "\t.type\toverflow_test,@function\n"
261
"overflow_test:\n"
262
        "\tLDI\t0,R1\n"
263
        "\tLDI\t0,R3\n"         // Clear our scorecard
264
// First test: does adding one to the maximum integer cause an overflow?
265
        "\tLDI\t-1,R2\n"
266
        "\tLSR\t1,R2\n"
267
        "\tADD\t1,R2\n"
268
        "\tOR.V\t1,R3\n"
269
// Second test: does subtracting one to the minimum integer cause an overflow?
270
        "\tLDI\t0x80000000,R2\n"
271
        "\tSUB\t1,R2\n"
272
        "\tOR.V\t2,R3\n"
273
// Third test, overflow from LSR
274
        "\tLDI\t0x80000000,R2\n"
275
        "\tLSR\t1,R2\n"         // Overflows 'cause the sign changes
276
        "\tOR.V\t4,R3\n"
277
// Fourth test, overflow from LSL
278
        "\tLDI\t0x40000000,R2\n"
279
        "\tLSL\t1,R2\n"
280
        "\tOR.V\t8,R3\n"
281
// Fifth test, overflow from LSL, negative to positive
282
        "\tLDI\t0x80000000,R2\n"
283
        "\tLSL\t1,R2\n"
284
        "\tOR.V\t16,R3\n"
285
// Record our scores
286
        "\tXOR\t31,R3\n"
287
        "\tOR\tR3,R1\n"
288
// And return the results
289
        "\tJMP\tR0");
290
 
291
 
292
void    carry_test(void);
293
asm("\t.text\n\t.global\tcarry_test\n"
294
        "\t.type\tcarry_test,@function\n"
295
"carry_test:\n"
296
        "\tLDI\t0,R1\n"
297
        "\tLDI\t0,R3\n"
298
// First, in adding
299
        "\tLDI\t-1,R2\n"
300
        "\tADD\t1,R2\n"
301
        "\tOR.C\t1,R3\n"
302
// Then, in subtraction
303
        "\tSUB\t1,R2\n"
304
        "\tOR.C\t2,R3\n"
305
// From a right shift
306
        "\tLDI\t1,R2\n"
307
        "\tLSR\t1,R2\n"
308
        "\tOR.C\t4,R3\n"
309
        "\tLDI\t1,R2\n"
310
        "\tASR\t1,R2\n"
311
        "\tOR.C\t8,R3\n"
312
// Or from a compare
313
        "\tLDI\t0,R2\n"
314
        "\tCMP\t1,R2\n"
315
        "\tOR.C\t16,R3\n"
316
// Set our return and clean up
317
        "\tXOR\t31,R3\n"
318
        "\tOR\tR3,R1\n"
319
        "\tJMP\tR0");
320
 
321
void    loop_test(void);
322
asm("\t.text\n\t.global\tloop_test\n"
323
        "\t.type\tloop_test,@function\n"
324
"loop_test:\n"
325
        "\tLDI\t0,R1\n"
326
// Let's try a loop: for(i=0; i<5; i++)
327
        "\tLDI\t0,R2\n"
328
        "\tLDI\t0,R3\n"
329
        "\tCMP\t5,R2\n"
330
        "\tBGE\tend_for_loop_test\n"
331
"for_loop_test:"
332
        "\tADD\t1,R2\n"
333
        "\tADD\t1,R3\n"
334
        "\tCMP\t5,R2\n"
335
        "\tBLT\tfor_loop_test\n"
336
"end_for_loop_test:"
337
        "\tCMP\t5,R3\n"
338
        "\tOR.NZ\t1,R1\n"
339
// How about a reverse do{} while loop?  These are usually cheaper than for()
340
// loops.
341
        "\tLDI\t0,R2\n"
342
        "\tLDI\t5,R3\n"
343
"bgt_loop_test:\n"
344
        "\tADD\t1,R2\n"
345
        "\tSUB\t1,R3\n"
346
        "\tBGT\tbgt_loop_test\n"
347
        "\tCMP\t5,R2\n"
348
        "\tOR.NZ\t2,R1\n"
349
// What if we use >=?
350
        "\tLDI\t0,R2\n"
351
        "\tLDI\t5,R3\n"
352
"bge_loop_test:\n"
353
        "\tADD\t1,R2\n"
354
        "\tSUB\t1,R3\n"
355
        "\tBGE\tbge_loop_test\n"
356
        "\tCMP\t6,R2\n"
357
        "\tOR.NZ\t4,R1\n"
358
// Once more with the reverse loop, this time storing the loop variable in
359
// memory
360
        "\tSUB\t1,SP\n"
361
        "\tLDI\t0,R2\n"
362
        "\tLDI\t5,R3\n"
363
        "\tSTO\tR3,(SP)\n"
364
"mem_loop_test:\n"
365
        "\tADD\t1,R2\n"
366
        "\tADD\t14,R3\n"
367
        "\tLOD\t(SP),R3\n"
368
        "\tSUB\t1,R3\n"
369
        "\tSTO\tR3,(SP)\n"
370
        "\tBGT\tmem_loop_test\n"
371
        "\tCMP\t5,R2\n"
372
        "\tOR.NZ\t8,R1\n"
373
        "\tADD\t1,SP\n"
374
//
375
        "\tJMP\tR0\n");
376
 
377
// Test whether or not LSL, LSR, and ASR instructions work, together with their
378
// carry flags
379
void    shift_test(void);
380
asm("\t.text\n\t.global\tshift_test\n"
381
        "\t.type\tshift_test,@function\n"
382
"shift_test:\n"
383
        "\tLDI\t0,R1\n"
384
        "\tLDI\t0,R3\n"
385
        "\tLDI\t0,R4\n"
386
// Does shifting right by 32 result in a zero?
387
        "\tLDI\t-1,R2\n"
388
        "\tLSR\t32,R2\n"
389
        "\tOR.Z\t1,R3\n"
390
        "\tOR.C\t2,R3\n"
391
        "\tCMP\t0,R2\n"
392
        "\tOR.Z\t4,R3\n"
393
// Does shifting a -1 right arithmetically by 32 result in a -1?
394
        "\tLDI\t-1,R2\n"
395
        "\tASR\t32,R2\n"
396
        "\tOR.LT\t8,R3\n"
397
        "\tOR.C\t16,R3\n"
398
        "\tCMP\t-1,R2\n"
399
        "\tOR.Z\t32,R3\n"
400
// Does shifting a -4 right arithmetically by 2 result in a -1?
401
        "\tLDI\t-4,R2\n"
402
        "\tASR\t2,R2\n"
403
        "\tOR.LT\t64,R3\n"
404
        "\tOR.C\t128,R1\n"
405
        "\tOR\t128,R3\n" // Artificially declare passing, so as not to fail it
406
        "\tCMP\t-1,R2\n"
407
        "\tOR.Z\t256,R3\n"
408
// Does one more set the carry flag as desired?
409
        "\tASR\t1,R2\n"
410
        "\tOR.LT\t512,R3\n"
411
        "\tOR.C\t1024,R3\n"
412
        "\tCMP\t-1,R2\n"
413
        "\tOR.Z\t2048,R3\n"
414
// Does shifting -1 left by 32 result in a zero?
415
        "\tLDI\t-1,R2\n"
416
        "\tLSL\t32,R2\n"
417
        "\tOR.Z\t4096,R3\n"
418
        "\tOR.C\t8192,R3\n"
419
        "\tCMP\t0,R2\n"
420
        "\tOR.Z\t16384,R3\n"
421
// How about shifting by zero?
422
        "\tLDI\t-1,R2\n"
423
        "\tASR\t0,R2\n"
424
        "\tOR.C\t32768,R1\n"
425
        "\tOR\t32768,R3\n"
426
        "\tCMP\t-1,R2\n"
427
        "\tOR.Z\t1,R4\n"
428
// 
429
        "\tLSR\t0,R2\n"
430
        "\tOR.C\t131072,R1\n"
431
        "\tCMP\t-1,R2\n"
432
        "\tOR.Z\t2,R4\n"
433
//
434
        "\tLSL\t0,R2\n"
435
        "\tOR.C\t524288,R1\n"
436
        "\tCMP\t-1,R2\n"
437
        "\tOR.Z\t4,R4\n"
438
// Tally up our results and return
439
        "\tXOR\t7,R4\n"
440
        "\tXOR\t65535,R3\n"
441
        "\tLSL\t16,R4\n"
442
        "\tOR\tR4,R3\n"
443
        "\tOR\tR3,R1\n"
444
        "\tJMP\tR0");
445
 
446
int     sw_brev(int v);
447
asm("\t.text\n\t.global\tsw_brev\n"
448
        "\t.type\tsw_brev,@function\n"
449
"sw_brev:\n"
450
        "\tSUB\t2,SP\n"
451
        "\tSTO\tR2,(SP)\n"
452
        "\tSTO\tR3,1(SP)\n"
453
        "\tLDI\t-1,R2\n"
454
        "\tCLR\tR3\n"
455
"sw_brev_loop:\n"
456
        "\tLSL\t1,R3\n"
457
        "\tLSR\t1,R1\n"
458
        "\tOR.C\t1,R3\n"
459
        "\tLSR\t1,R2\n"
460
        "\tBZ\tsw_brev_endloop\n"
461
        "\tBRA\tsw_brev_loop\n"
462
"sw_brev_endloop:\n"
463
        "\tMOV\tR3,R1\n"
464
        "\tLOD\t(SP),R2\n"
465
        "\tLOD\t1(SP),R3\n"
466
        "\tADD\t2,SP\n"
467
        "\tJMP\tR0");
468
 
469
void    pipeline_stack_test(void);
470
asm("\t.text\n\t.global\tpipeline_stack_test\n"
471
        "\t.type\tpipeline_stack_test,@function\n"
472
"pipeline_stack_test:\n"
473
        "\tSUB\t1,SP\n"
474
        "\tSTO\tR0,(SP)\n"
475
        "\tLDI\t0,R0\n"
476
        "\tMOV\t1(R0),R1\n"
477
        "\tMOV\t1(R1),R2\n"
478
        "\tMOV\t1(R2),R3\n"
479
        "\tMOV\t1(R3),R4\n"
480
        "\tMOV\t1(R4),R5\n"
481
        "\tMOV\t1(R5),R6\n"
482
        "\tMOV\t1(R6),R7\n"
483
        "\tMOV\t1(R7),R8\n"
484
        "\tMOV\t1(R8),R9\n"
485
        "\tMOV\t1(R9),R10\n"
486
        "\tMOV\t1(R10),R11\n"
487
        "\tMOV\t1(R11),R12\n"
488
        "\tMOV\tpipeline_stack_test_component_return(PC),R0\n"
489
        // "\tLJMP\tpipeline_stack_test_component\n"
490
        "\tBRA\tpipeline_stack_test_component\n"
491
"pipeline_stack_test_component_return:\n"
492
        "\tCMP\t1,R1\n"
493
        "\tLDI.Z\t0,R1\n"
494
        "\tCMP\t2,R2\n"
495
        "\tCMP.Z\t3,R3\n"
496
        "\tCMP.Z\t4,R4\n"
497
        "\tCMP.Z\t5,R5\n"
498
        "\tCMP.Z\t6,R6\n"
499
        "\tCMP.Z\t7,R7\n"
500
        "\tCMP.Z\t8,R8\n"
501
        "\tCMP.Z\t9,R9\n"
502
        "\tCMP.Z\t10,R10\n"
503
        "\tCMP.Z\t11,R11\n"
504
        "\tCMP.Z\t12,R12\n"
505
        "\tBREV.NZ\t-1,R1\n"
506
        "\tLOD\t(SP),R0\n"
507
        "\tADD\t1,SP\n"
508
        "\tJMP\tR0\n"
509
        );
510
 
511
void    pipeline_stack_test_component(void);
512
asm("\t.text\n\t.global\tpipeline_stack_test_component\n"
513
        "\t.type\tpipeline_stack_test_component,@function\n"
514
"pipeline_stack_test_component:\n"
515
        "\tSUB\t13,SP\n"
516
        "\tSTO\tR0,(SP)\n"
517
        "\tSTO\tR1,1(SP)\n"
518
        "\tSTO\tR2,2(SP)\n"
519
        "\tSTO\tR3,3(SP)\n"
520
        "\tSTO\tR4,4(SP)\n"
521
        "\tSTO\tR5,5(SP)\n"
522
        "\tSTO\tR6,6(SP)\n"
523
        "\tSTO\tR7,7(SP)\n"
524
        "\tSTO\tR8,8(SP)\n"
525
        "\tSTO\tR9,9(SP)\n"
526
        "\tSTO\tR10,10(SP)\n"
527
        "\tSTO\tR11,11(SP)\n"
528
        "\tSTO\tR12,12(SP)\n"
529
        "\tXOR\t-1,R0\n"
530
        "\tXOR\t-1,R1\n"
531
        "\tXOR\t-1,R2\n"
532
        "\tXOR\t-1,R3\n"
533
        "\tXOR\t-1,R4\n"
534
        "\tXOR\t-1,R5\n"
535
        "\tXOR\t-1,R6\n"
536
        "\tXOR\t-1,R7\n"
537
        "\tXOR\t-1,R8\n"
538
        "\tXOR\t-1,R9\n"
539
        "\tXOR\t-1,R10\n"
540
        "\tXOR\t-1,R11\n"
541
        "\tXOR\t-1,R12\n"
542
        "\tLOD\t(SP),R0\n"
543
        "\tLOD\t1(SP),R1\n"
544
        "\tLOD\t2(SP),R2\n"
545
        "\tLOD\t3(SP),R3\n"
546
        "\tLOD\t4(SP),R4\n"
547
        "\tLOD\t5(SP),R5\n"
548
        "\tLOD\t6(SP),R6\n"
549
        "\tLOD\t7(SP),R7\n"
550
        "\tLOD\t8(SP),R8\n"
551
        "\tLOD\t9(SP),R9\n"
552
        "\tLOD\t10(SP),R10\n"
553
        "\tLOD\t11(SP),R11\n"
554
        "\tLOD\t12(SP),R12\n"
555
        "\tADD\t13,SP\n"
556
        "\tJMP\tR0\n");
557
 
558
//mpy_test
559
void    mpy_test(void);
560
asm("\t.text\n\t.global\tmpy_test\n"
561
        "\t.type\tmpy_test,@function\n"
562
"mpy_test:\n"
563
        "\tCLR\tR1\n"
564
        // First test: let's count multiples of 137
565
        "\tLDI\t137,R2\n"       // What we're doing multiples of
566
        "\tCLR\tR3\n"           // Our accumulator via addition
567
        "\tCLR\tR4\n"           // Our index for multiplication
568
        "mpy_137_test_loop:\n"
569
        "\tMOV\tR2,R5\n"
570
        "\tMPY\tR4,R5\n"
571
        "\tCMP\tR3,R5\n"
572
        "\tBNZ\tend_mpy_137_test_loop_failed\n"
573
        // Let's try negative while we are at it
574
        "\tMOV\tR2,R6\n"
575
        "\tNEG\tR6\n"
576
        "\tMPY\tR4,R6\n"
577
        "\tNEG\tR6\n"
578
        "\tCMP\tR3,R6\n"
579
        "\tBNZ\tend_mpy_137_test_loop_failed\n"
580
        "\tCLR\tR6\n"
581
        "\tTEST\t0xffff0000,R3\n"
582
        "\tBNZ\tend_mpy_137_test_loop\n"
583
        "\tADD\tR2,R3\n"
584
        "\tADD\t1,R4\n"
585
        "\tBRA\tmpy_137_test_loop\n"
586
"end_mpy_137_test_loop_failed:\n"
587
        "\tOR\t1,R1\n"
588
"end_mpy_137_test_loop:\n"
589
        // Second test ... whatever that might be
590
        "\tJMP\tR0\n");
591
 
592
unsigned        soft_mpyuhi(unsigned, unsigned);
593
int             soft_mpyshi(int,int);
594
 
595
unsigned        hard_mpyuhi(unsigned, unsigned);
596
asm("\t.text\n\t.global\thard_mpyuhi\n"
597
        "\t.type\thard_mpyuhi,@function\n"
598
"hard_mpyuhi:\n"
599
        "\tNOOP\n"
600
        "\tNOOP\n"
601
        "\tMPYUHI\tR2,R1\n"
602
        "\tRETN\n");
603
 
604
int     hard_mpyshi(int, int);
605
asm("\t.text\n\t.global\thard_mpyshi\n"
606
        "\t.type\thard_mpyshi,@function\n"
607
"hard_mpyshi:\n"
608
        "\tMPYSHI\tR2,R1\n"
609
        "\tRETN\n");
610
 
611
void    debugmpy(char *str, int a, int b, int s, int r) {
612
#ifdef  HAVE_SCOPE
613
        // Trigger the scope, if it hasn't been triggered yet
614
        // but ... dont reset it if it has been.
615
        SCOPEc = TRIGGER_SCOPE_NOW;
616
#endif
617
        txstr("\r\n"); txstr(str); txhex(a);
618
        txstr(" x "); txhex(b);
619
        txstr(" = "); txhex(s);
620
        txstr("(Soft) = "); txhex(r);
621
        txstr("(Hard)\r\n");
622
}
623
 
624
int     mpyhi_test(void) {
625
        int     a = 0xf97e27ab, b = 0;
626
 
627
        while(b<0x6fffffff) {
628
                int     r, sr;
629
 
630
                sr = soft_mpyuhi(a, b);
631
                r = hard_mpyuhi(a,b);
632
                if (r != sr) {
633
                        debugmpy("MPYUHI: ", a,b,sr,r);
634
                        return 1;
635
                }
636
 
637
                sr = soft_mpyshi(a, b);
638
                r = hard_mpyshi(a,b);
639
                if (r != sr) {
640
                        debugmpy("MPYSHI: ", a,b,sr,r);
641
                        return 2;
642
                }
643
 
644
                sr = soft_mpyshi(-a, b);
645
                r = hard_mpyshi(-a,b);
646
                if (r != sr) {
647
                        debugmpy("MPYSHI-NEG: ", -a,b,sr,r);
648
                        return 3;
649
                }
650
 
651
                b += 0x197e2*7;
652
        }
653
 
654
        return 0;
655
}
656
 
657
unsigned        soft_mpyuhi(unsigned a, unsigned b) {
658
        unsigned        alo, ahi, blo, bhi;
659
        unsigned        rhi, rlhi, rllo;
660
 
661
        alo = (a     & 0x0ffff);
662
        ahi = (a>>16)& 0x0ffff;
663
        blo = (b     & 0x0ffff);
664
        bhi = (b>>16)& 0x0ffff;
665
 
666
        rhi = 0;
667
        rlhi = 0;
668
        rllo = 0;
669
 
670
        for(int i=0; i<16; i++) {
671
                if (b&(1<<i)) {
672
                        unsigned slo, shi, sup;
673
                        slo = (alo << i);
674
                        shi = (ahi << i);
675
                        shi |= (slo>>16) & 0x0ffff;
676
                        slo &= 0x0ffff;
677
                        sup = (shi>>16)&0x0ffff;
678
                        shi &= 0x0ffff;
679
 
680
                        rhi  += sup;
681
                        rlhi += shi;
682
                        rllo += slo;
683
 
684
                        rlhi += (rllo >> 16)&0x0ffff;
685
                        rllo &= 0x0ffff;
686
 
687
                        rhi  += (rlhi >> 16)&0x0ffff;
688
                        rlhi &= 0x0ffff;
689
                }
690
        }
691
 
692
        for(int i=16; i<32; i++) {
693
                if (b&(1<<i)) {
694
                        unsigned slo, shi, sup;
695
                        slo = (alo << (i-16));
696
                        shi = (ahi << (i-16));
697
                        shi |= (slo>>16) & 0x0ffff;
698
                        slo &= 0x0ffff;
699
                        sup = (shi>>16)&0x0ffff;
700
                        shi &= 0x0ffff;
701
 
702
                        rhi  += sup << 16;
703
                        rhi  += shi;
704
                        rlhi += slo;
705
 
706
                        rhi  += (rlhi >> 16)&0x0ffff;
707
                        rlhi &= 0x0ffff;
708
                }
709
        }
710
 
711
        return rhi;
712
}
713
 
714
int     soft_mpyshi(int a, int b) {
715
        unsigned        sgn, r, p;
716
 
717
        sgn = ((a^b)>>31)&0x01;
718
 
719
        if (a<0) a = -a;
720
        if (b<0) b = -b;
721
 
722
        p = a * b;
723
 
724
        // This will only fail if the lower 32-bits of of a*b are 0,
725
        // at which point our following negation won't capture the carry it
726
        // needs.
727
        r = soft_mpyuhi(a, b);
728
 
729
        r = (sgn)?(r^-1):r;
730
        if ((sgn)&&(p==0))
731
                r += 1;
732
        return r;
733
}
734
 
735
//brev_test
736
//pipeline_test -- used to be called pipeline memory race conditions
737
void    pipeline_test(void);
738
asm("\t.text\n\t.global\tpipeline_test\n"
739
        "\t.type\tpipeline_test,@function\n"
740
"pipeline_test:\n"
741
        "\tSUB\t2,SP\n"
742
        // Test setup
743
        "\tLDI\t275,R2\n"
744
        "\tSTO\tR2,1(SP)\n"
745
        "\tMOV\t1(SP),R2\n"
746
        "\tSTO\tR2,(SP)\n"
747
        "\tCLR\tR2\n"
748
        //
749
        "\tMOV\tSP,R2\n"
750
        "\tLOD\t(R2),R2\n"
751
        "\tLOD\t(R2),R2\n"
752
        "\tCMP\t275,R2\n"
753
        "\tOR.NZ\t1,R1\n"
754
        //
755
        "\tMOV\tSP,R2\n"
756
        // Here's the test sequence
757
        "\tLOD\t(R2),R3\n"
758
        "\tLOD\t1(R2),R4\n"
759
        "\tSTO\tR4,1(R3)\n"
760
        // Make sure we clear the load pipeline
761
        "\tLOD\t(R2),R3\n"
762
        // Load our written value
763
        "\tLOD\t2(R2),R4\n"
764
        "\tCMP\t275,R4\n"
765
        "\tOR.NZ\t2,R1\n"
766
        //
767
        //
768
        // Next (once upon a time) failing sequence:
769
        //      LOD -x(R12),R0
770
        //      LOD y(R0),R0
771
        "\tMOV\tSP,R2\n"
772
        "\tMOV\t1(R2),R3\n"
773
        "\tSTO\tR3,1(R2)\n"
774
        "\tLDI\t3588,R4\n"      // Just some random value
775
        "\tSTO\tR4,2(R2)\n"
776
        "\tMOV\tR2,R3\n"
777
        // Here's the test sequence
778
        "\tLOD\t(R2),R3\n"
779
        "\tLOD\t1(R3),R3\n"
780
        "\tCMP\tR4,R3\n"
781
        "\tOR.NZ\t4,R1\n"
782
        //
783
        "\tADD\t2,SP\n"
784
        "\tJMP\tR0\n");
785
 
786
//mempipe_test
787
void    mempipe_test(void);
788
asm("\t.text\n\t.global\tmempipe_test\n"
789
        "\t.type\tmempipe_test,@function\n"
790
"mempipe_test:\n"
791
        "\tSUB\t4,SP\n"
792
        "\tSTO\tR0,(SP)\n"
793
        "\tLDI\t0x1000,R11\n"
794
        // Test #1 ... Let's start by writing a value to memory
795
        "\tLDI\t-1,R2\n"
796
        "\tCLR\tR3\n"
797
        "\tSTO\tR2,2(SP)\n"
798
        "\tLOD\t2(SP),R3\n"
799
        "\tCMP\tR3,R2\n"
800
        "\tOR.NZ\t1,R1\n"
801
        // Test #2, reading and then writing a value from memory
802
        "\tNOOP\n"
803
        "\tNOOP\n"
804
        "\tCLR\tR2\n"
805
        "\tCLR\tR3\n"
806
        "\tLOD\t2(SP),R2\n"     // This should load back up our -1 value
807
        "\tSTO\tR2,3(SP)\n"
808
        // Insist that the pipeline clear
809
        "\tLOD\t2(SP),R2\n"
810
        // Now let's try loading into R3
811
        "\tNOOP\n"
812
        "\tNOOP\n"
813
        "\tNOOP\n"
814
        "\tNOOP\n"
815
        "\tLOD\t3(SP),R3\n"
816
        "\tCMP\tR3,R2\n"
817
        "\tOR.NZ\t2,R1\n"
818
        //
819
        "\tLOD\t(SP),R0\n"
820
        "\tADD\t4,SP\n"
821
        "\tJMP\tR0\n");
822
 
823
//cexec_test
824
void    cexec_test(void);
825
asm("\t.text\n\t.global\tcexec_test\n"
826
        "\t.type\tcexec_test,@function\n"
827
"cexec_test:\n"
828
        "\tSUB\t1,SP\n"
829
        "\tSTO\tR0,(SP)\n"
830
        //
831
        "\tXOR\tR2,R2\n"
832
        "\tADD.Z\t1,R2\n"
833
        "\tADD.NZ\t1,R1\n"
834
        "\tCMP.Z\t0,R2\n"
835
        "\tOR.Z\t2,R1\n"
836
        //
837
        "\tLOD\t(SP),R0\n"
838
        "\tADD\t1,SP\n"
839
        "\tJMP\tR0\n");
840
 
841
// Pipeline stalls have been hideous problems for me.  The CPU has been modified
842
// with special logic to keep stages from stalling.  For the most part, this
843
// means that ALU and memory results may be accessed either before or as they
844
// are written to the register file.  This set of code is designed to test
845
// whether this bypass logic works.
846
//
847
//nowaitpipe_test
848
void    nowaitpipe_test(void);
849
asm("\t.text\n\t.global\tnowaitpipe_test\n"
850
        "\t.type\tnowaitpipe_test,@function\n"
851
"nowaitpipe_test:\n"
852
        "\tSUB\t2,SP\n"
853
        //
854
        // Let's start with ALU-ALU testing
855
        //      AA: result->input A
856
        "\tLDI\t-1,R2\n"
857
        "\tCLR\tR2\n"
858
        "\tADD\t1,R2\n"
859
        "\tCMP\t1,R2\n"
860
        "\tOR.NZ\t1,R1\n"
861
        //
862
        //      AA: result -> input B
863
        "\tCLR\tR2\n"
864
        "\tCLR\tR3\n"
865
        "\tADD\t1,R2\n"
866
        "\tCMP\tR2,R3\n"
867
        "\tOR.Z\t2,R1\n"
868
        //      AA: result -> input A on condition
869
        "\tXOR\tR2,R2\n"
870
        "\tADD.Z\t5,R2\n"
871
        "\tCMP\t5,R2\n"
872
        "\tOR.NZ\t4,R1\n"
873
        //      AA: result -> input B on condition
874
        "\tCLR\tR2\n"
875
        "\tXOR\tR3,R3\n"
876
        "\tADD.Z\t5,R2\n"
877
        "\tCMP\tR2,R3\n"
878
        "\tOR.Z\t8,R1\n"
879
        //      AA: result->input B plus offset
880
        "\tCLR\tR2\n"
881
        "\tXOR\tR3,R3\n"
882
        "\tADD\t5,R2\n"
883
        "\tCMP\t-5(R2),R3\n"
884
        "\tOR.NZ\t16,R1\n"
885
        //      AA: result->input B plus offset on condition
886
        "\tCLR\tR2\n"
887
        "\tXOR\tR3,R3\n"
888
        "\tADD.Z\t5,R2\n"
889
        "\tCMP\t-5(R2),R3\n"
890
        "\tOR.NZ\t32,R1\n"
891
        //
892
        // Then we need to do the ALU-MEM input testing
893
        //
894
        "\tCLR\tR2\n"
895
        "\tSTO\tR2,1(SP)\n"
896
        "\tLDI\t8352,R2\n"
897
        "\tLOD\t1(SP),R2\n"
898
        "\tTST\t-1,R2\n"
899
        "\tOR.NZ\t64,R1\n"
900
        // Let's try again, this time with something that's not zero
901
        "\tLDI\t937,R2\n"
902
        "\tSTO\tR2,1(SP)\n"
903
        "\tNOOP\n"
904
        "\tLOD\t1(SP),R2\n"
905
        "\tCMP\t938,R2\n"
906
        "\tOR.GE\t128,R1\n"
907
        "\tCMP\t936,R2\n"
908
        "\tOR.LT\t256,R1\n"
909
        // Mem output->ALU input testing
910
        //      Okay, we just did that as part of our last test
911
        // Mem output->mem input testing
912
        "\tLDI\t5328,R2\n"
913
        "\tLOD\t1(SP),R2\n"
914
        "\tSTO\tR2,1(SP)\n"
915
        "\tLOD\t1(SP),R3\n"
916
        "\tCMP\t937,R3\n"
917
        "\tOR.NZ\t512,R1\n"
918
        //
919
        "\tADD\t2,SP\n"
920
        "\tJMP\tR0\n");
921
 
922
//bcmem_test
923
void    bcmem_test(void);
924
asm("\t.text\n.global\tbcmem_test\n"
925
        "\t.type\tbcmem_test,@function\n"
926
"bcmem_test:\n"
927
        "\tSUB\t1,SP\n"
928
        "\tCLR\tR1\n"
929
        "\tCLR\tR2\n"
930
        "\tLDI\t-1,R3\n"
931
        "\tLDI\t0x13000,R4\n"
932
        "\tSTO\tR2,(SP)\n"
933
        "\tLOD\t(SP),R3\n"
934
        "\tCMP\tR2,R3\n"
935
        "\tOR.NZ\t1,R1\n"
936
        "\tCMP\t0x13000,R4\n"
937
        "\tBZ\tbcmem_test_cmploc_1\n"
938
        "\tSTO\tR4,(SP)\n"
939
"bcmem_test_cmploc_1:\n"
940
        "\tLOD\t(SP),R2\n"
941
        "\tCMP\tR2,R4\n"
942
        "\tOR.Z\t2,R1\n"
943
        "\tCLR\tR2\n"
944
        "\tCMP\tR2,R4\n"
945
        "\tBZ\tbcmem_test_cmploc_2\n"
946
        "\tSTO.NZ\tR4,(SP)\n"
947
"bcmem_test_cmploc_2:\n"
948
        "\tLOD\t(SP),R2\n"
949
        "\tCMP\tR2,R4\n"
950
        "\tOR.NZ\t4,R1\n"
951
//
952
        "\tADD\t1,SP\n"
953
        "\tJMP\tR0\n");
954
 
955
// The illegal instruction test.  Specifically, illegal instructions cannot be
956
// allowed to execute.  The PC must, upon completion, point to the illegal
957
// instruction that caused the exception.
958
//
959
// To create our illegal instruction, we assume that the only the three
960
// operations without arguments are NOOP, BREAK, LOCK, and so we envision a
961
// fourth instruction to create.
962
void    ill_test(void);
963
asm("\t.text\n.global\till_test\n"
964
        "\t.type\till_test,@function\n"
965
"ill_test:\n"
966
        "\t.word\t0x7ff00000\n"
967
        "\tJMP\tR0\n");
968
 
969
//
970
// The CC register has some ... unique requirements associated with it.
971
// Particularly, flags are unavailable until after an ALU operation completes,
972
// and they can't really be bypassed for the CC register.  After writeback,
973
// the "new" CC register isn't really available for another clock.  Trying to
974
// bypass this extra clock can have problems, since ... some bits are fixed,
975
// some bits can only be changed by the supervisor, and others can/will change
976
// and even have effects--like sending the CPU to supervisor mode or
977
// alternatively to sleep.
978
//
979
// Here, let's see if our pipeline can successfully navigate any of these
980
// issues.
981
//
982
void    ccreg_test(void);
983
asm("\t.text\n.global\tccreg_test\n"
984
        "\t.type\tccreg_test,@function\n"
985
"ccreg_test:\n"
986
        // First test: If we try to change the fixed bits, will they change
987
        // because the pipeline tries to bypass the write-back stage
988
        "\tCLR\tR1\n"   // We'll start with an "answer" of success
989
        "\tMOV\tCC,R2\n"
990
        "\tMOV\tR2,R4\n"        // Keep a copy
991
        "\tBREV\t0x0ff,R3\n"    // Attempt to change the top fixed bits
992
        "\tXOR\tR3,R2\n"        // Arrange for the changes
993
        "\tMOV\tR2,CC\n"        // Set the changes (they won't take)
994
        "\tMOV\tCC,R5\n"        // See if the pipeline makes them take
995
        "\tXOR\tR4,R5\n"        // Let's look for anything that has changed
996
        "\tOR.NZ\t1,R1\n"       // If anything has changed, then we fail the tst
997
        // 
998
        // Test #2: Can we set the flags?
999
        "\tMOV\tCC,R6\n"
1000
        "\tOR\t15,R6\n"
1001
        "\tMOV\tR6,CC\n"
1002
        "\tMOV\tCC,R7\n"
1003
        "\tAND\t15,R7\n"
1004
        "\tCMP\t15,R7\n"
1005
        "\tOR.NZ\t2,R1\n"
1006
        //
1007
        // Test #3: How about setting specific flags, and immediately acting
1008
        // on them?
1009
        "\tXOR\t1+R8,R8\n"      // Turn off the Z bit
1010
        "\tOR\t1,CC\n"          // Turn on the Z bit
1011
        "\tOR.NZ\t4,R1\n"
1012
        //
1013
        // Test #4: Can we load the CC plus a value into a register?
1014
        //      I don't think so ...
1015
        "\tJMP\tR0\n");
1016
 
1017
// Multiple argument test
1018
__attribute__((noinline))
1019
int     multiarg_subroutine(int a, int b, int c, int d, int e, int f, int g) {
1020
        if (a!=0)        return 1;
1021
        if (b!=1)       return 2;
1022
        if (c!=2)       return 4;
1023
        if (d!=3)       return 8;
1024
        if (e!=4)       return 16;
1025
        if (f!=5)       return 32;
1026
        if (g!=6)       return 64;
1027
        return 0;
1028
}
1029
 
1030
int     multiarg_test(void) {
1031
        return multiarg_subroutine(0,1,2,3,4,5,6);
1032
}
1033
 
1034
__attribute__((noinline))
1035
void    wait(unsigned int msk) {
1036
        *PIC = 0x7fff0000|msk;
1037
        asm("MOV\tidle_task(PC),uPC\n");
1038
        *PIC = 0x80000000|(msk<<16);
1039
        asm("WAIT\n");
1040
        *PIC = 0; // Turn interrupts back off, lest they confuse the test
1041
}
1042
 
1043
asm("\n\t.text\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n");
1044
 
1045
__attribute__((noinline))
1046
void    txchr(char v) {
1047
        if (zip_cc() & CC_GIE) {
1048
                while(*UARTTX & 0x100)
1049
                        ;
1050
        } else
1051
                wait(INT_UARTTX);
1052
        *UARTTX = v;
1053
}
1054
 
1055
__attribute__((noinline))
1056
void    txstr(const char *str) {
1057
        const char *ptr = str;
1058
        while(*ptr)
1059
                txchr(*ptr++);
1060
}
1061
 
1062
__attribute__((noinline))
1063
void    txhex(int num) {
1064
        for(int ds=28; ds>=0; ds-=4) {
1065
                int     ch;
1066
                ch = (num >> ds)&0x0f;
1067
                if (ch >= 10)
1068
                        ch = 'A'+ch-10;
1069
                else
1070
                        ch += '0';
1071
                txchr(ch);
1072
        }
1073
}
1074
 
1075
__attribute__((noinline))
1076
void    tx4hex(int num) {
1077
        if (num & 0xffff0000){
1078
                txhex(num);
1079
                return;
1080
        } for(int ds=12; ds>=0; ds-=4) {
1081
                int     ch;
1082
                ch = (num >> ds)&0x0f;
1083
                if (ch >= 10)
1084
                        ch = 'A'+ch-10;
1085
                else
1086
                        ch += '0';
1087
                txchr(ch);
1088
        }
1089
}
1090
 
1091
__attribute__((noinline))
1092
void    txreg(const char *name, int val) {
1093
        txstr(name);    // 4 characters
1094
        txstr("0x");    // 2 characters
1095
        txhex(val);     // 8 characters
1096
        txstr("    ");  // 4 characters
1097
}
1098
 
1099
__attribute__((noinline))
1100
void    save_context(int *context) {
1101
        zip_save_context(context);
1102
}
1103
 
1104
__attribute__((noinline))
1105
void    test_fails(int start_time, int *listno) {
1106
        int     context[16], stop_time;
1107
 
1108
        // Trigger the scope, if it hasn't already triggered.  Otherwise,
1109
        // if it has triggered, don't clear it.
1110
#ifdef  HAVE_SCOPE
1111
        SCOPEc = TRIGGER_SCOPE_NOW;
1112
#endif
1113
 
1114
        MARKSTOP;
1115
        save_context(context);
1116
        *listno++ = context[1];
1117
        *listno++ = context[14];
1118
        *listno++ = context[15];
1119
#ifdef  HAVE_COUNTER
1120
        *listno   = stop_time;
1121
#endif
1122
 
1123
        txstr("FAIL!\r\n\r\n");
1124
        txstr("Between 0x"); txhex(start_time);
1125
                txstr(" and 0x"); txhex(stop_time); txstr("\r\n\r\n");
1126
        txstr("Core-dump:\r\n");
1127
        txreg("uR0 : ", context[0]);
1128
        txreg("uR1 : ", context[1]);
1129
        txreg("uR2 : ", context[2]);
1130
        txreg("uR3 : ", context[3]);
1131
        txstr("\r\n");
1132
 
1133
        txreg("uR4 : ", context[4]);
1134
        txreg("uR5 : ", context[5]);
1135
        txreg("uR6 : ", context[6]);
1136
        txreg("uR7 : ", context[7]);
1137
        txstr("\r\n");
1138
 
1139
        txreg("uR8 : ", context[8]);
1140
        txreg("uR9 : ", context[9]);
1141
        txreg("uR10: ", context[10]);
1142
        txreg("uR11: ", context[11]);
1143
        txstr("\r\n");
1144
 
1145
        txreg("uR12: ", context[12]);
1146
        txreg("uSP : ", context[13]);
1147
        txreg("uCC : ", context[14]);
1148
        txreg("uPC : ", context[15]);
1149
        txstr("\r\n\r\n");
1150
 
1151 49 dgisselq
        // While previous versions of cputest.c called zip_busy(), here we
1152
        // reject that notion for the simple reason that zip_busy may not
1153
        // necessarily halt any Verilator simulation.  Instead, we try to 
1154
        // halt the CPU.
1155 41 dgisselq
        while(1)
1156
                zip_halt();
1157
}
1158
 
1159
void    testid(const char *str) {
1160
        const int       WIDTH=32;
1161
        txstr(str);
1162
        const char *ptr = str;
1163
        int     i = 0;
1164
        while(0 != *ptr++)
1165
                i++;
1166
        i = WIDTH-i;
1167
        while(i-- > 0)
1168
                txchr(' ');
1169
}
1170
 
1171
int     testlist[32];
1172
 
1173
void entry(void) {
1174
        int     context[16];
1175
        int     user_stack[256], *user_stack_ptr = &user_stack[256];
1176
        int     start_time, i;
1177
 
1178
        for(i=0; i<32; i++)
1179
                testlist[i] = -1;
1180
 
1181
#ifdef  HAVE_TIMER
1182
        *TIMER = 0x7fffffff;
1183
#endif
1184
#ifdef  HAVE_COUNTER
1185
        *COUNTER = 0;
1186
#endif
1187
#ifdef  HAVE_SCOPE
1188
        SCOPEc = PREPARE_SCOPE;
1189
#endif
1190
 
1191
        // *UART_CTRL = 8333; // 9600 Baud, 8-bit chars, no parity, one stop bit
1192
        // *UART_CTRL = 25; // 9600 Baud, 8-bit chars, no parity, one stop bit
1193
        //
1194
 
1195
        txstr("\r\n");
1196
        txstr("Running CPU self-test\r\n");
1197
        txstr("-----------------------------------\r\n");
1198
 
1199
        int     tnum = 0;
1200
 
1201
        // Test break instruction in user mode
1202
        // Make sure the break works as designed
1203
        testid("Break test #1"); MARKSTART;
1204
 
1205
        if ((run_test(break_one, user_stack_ptr))||(zip_ucc()&0x1f50))
1206
                test_fails(start_time, &testlist[tnum]);
1207
 
1208
        save_context(context);
1209
        if ((context[15] != (int)break_one+1)||(0==(zip_ucc()&0x80)))
1210
                test_fails(start_time, &testlist[tnum]);
1211
        txstr("Pass\r\n"); testlist[tnum++] = 0; // 0
1212
 
1213
        // Test break instruction in user mode
1214
        // Make sure that a decision on the clock prior won't still cause a 
1215
        // break condition
1216
        testid("Break test #2"); MARKSTART;
1217
        if ((run_test(break_two, user_stack_ptr))||(zip_ucc()&0x1d90))
1218
                test_fails(start_time, &testlist[tnum]);
1219
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #1
1220
 
1221 49 dgisselq
        // Test break instruction in user mode
1222
        // Make sure that a decision on the clock prior won't still cause a 
1223
        // break condition
1224
        testid("Break test #3"); MARKSTART;
1225
        run_test(break_three, user_stack_ptr);
1226
        if ((context[15] != (int)break_three)   // Insist we stop at the break
1227
                        ||(0==(zip_ucc()&0x80))  // insn, that the break flag is
1228
                        ||(zip_ucc()&0x01d10))  // set, and no other excpt flags
1229
                test_fails(start_time, &testlist[tnum]);
1230
        txstr("Pass\r\n"); testlist[tnum++] = 0; // 0
1231
 
1232 41 dgisselq
        // LJMP test ... not (yet) written
1233
 
1234
        // Test the early branching capability
1235
        //      Does it successfully clear whatever else is in the pipeline?
1236
        testid("Early Branch test"); MARKSTART;
1237
        if ((run_test(early_branch_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1238
                test_fails(start_time, &testlist[tnum]);
1239
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #2
1240
 
1241
        // TRAP test
1242
        testid("Trap test/AND"); MARKSTART;
1243
        if ((run_test(trap_test_and, user_stack_ptr))||(zip_ucc()&0x01d90))
1244
                test_fails(start_time, &testlist[tnum]);
1245
        if ((zip_ucc() & 0x0200)==0)
1246
                test_fails(start_time, &testlist[tnum]);
1247
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #3
1248
 
1249
        testid("Trap test/CLR"); MARKSTART;
1250
        if ((run_test(trap_test_clr, user_stack_ptr))||(zip_ucc()&0x01d90))
1251
                test_fails(start_time, &testlist[tnum]);
1252
        if ((zip_ucc() & 0x0200)==0)
1253
                test_fails(start_time, &testlist[tnum]);
1254
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #4
1255
 
1256
        // Overflow test
1257
        testid("Overflow test"); MARKSTART;
1258
        if ((run_test(overflow_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1259
                test_fails(start_time, &testlist[tnum]);
1260
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #5
1261
 
1262
        // Carry test
1263
        testid("Carry test"); MARKSTART;
1264
        if ((run_test(carry_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1265
                test_fails(start_time, &testlist[tnum]);
1266
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #6
1267
 
1268
        // LOOP_TEST
1269
        testid("Loop test"); MARKSTART;
1270
        if ((run_test(loop_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1271
                test_fails(start_time, &testlist[tnum]);
1272
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #7 -- FAILS
1273
 
1274
        // SHIFT_TEST
1275
        testid("Shift test"); MARKSTART;
1276
        if ((run_test(shift_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1277
                test_fails(start_time, &testlist[tnum]);
1278
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #8
1279
 
1280
        // BREV_TEST
1281
        //testid("BREV/stack test"); MARKSTART;
1282
        //if ((run_test(brev_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1283
                //test_fails(start_time);
1284
        //txstr("Pass\r\n");
1285
 
1286
        // PIPELINE_TEST
1287
        testid("Pipeline test"); MARKSTART;
1288
        if ((run_test(pipeline_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1289
                test_fails(start_time, &testlist[tnum]);
1290
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #10
1291
 
1292
        // MEM_PIPELINE_STACK_TEST
1293
        testid("Mem-Pipeline test"); MARKSTART;
1294
        if ((run_test(mempipe_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1295
                test_fails(start_time, &testlist[tnum]);
1296
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #11
1297
 
1298
        // CONDITIONAL EXECUTION test
1299
        testid("Conditional Execution test"); MARKSTART;
1300
        if ((run_test(cexec_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1301
                test_fails(start_time, &testlist[tnum]);
1302
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #12 -- FAILS
1303
 
1304
        // NOWAIT pipeline test
1305
        testid("No-waiting pipeline test"); MARKSTART;
1306
        if ((run_test(nowaitpipe_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1307
                test_fails(start_time, &testlist[tnum]);
1308
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #13
1309
 
1310
        // BCMEM test
1311
        testid("Conditional Branching test"); MARKSTART;
1312
        if ((run_test(bcmem_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1313
                test_fails(start_time, &testlist[tnum]);
1314
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #14
1315
 
1316
        // Illegal Instruction test
1317
        testid("Ill Instruction test, NULL PC"); MARKSTART;
1318
        if ((run_test(NULL, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
1319
                test_fails(start_time, &testlist[tnum]);
1320
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1321
 
1322
        // Illegal Instruction test
1323
        testid("Ill Instruction test, two"); MARKSTART;
1324
        if ((run_test(ill_test, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
1325
                test_fails(start_time, &testlist[tnum]);
1326
        save_context(context);
1327
        if (context[15] != (int)&ill_test)
1328
                test_fails(start_time, &testlist[tnum]);
1329
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1330
 
1331
        // Pipeline memory race condition test
1332
        // DIVIDE test
1333
 
1334
        // CC Register test
1335
        testid("CC Register test"); MARKSTART;
1336
        if ((run_test(ccreg_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1337
                test_fails(start_time, &testlist[tnum]);
1338
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1339
 
1340
        // Multiple argument test
1341
        testid("Multi-Arg test"); MARKSTART;
1342
        if ((run_test(multiarg_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1343
                test_fails(start_time, &testlist[tnum]);
1344
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1345
 
1346
        // MPY_TEST
1347
        testid("Multiply test"); MARKSTART;
1348
        if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1349
                test_fails(start_time, &testlist[tnum]);
1350
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
1351
 
1352
        // MPYxHI_TEST
1353
        testid("Multiply HI-word test"); MARKSTART;
1354
        if ((run_test(mpyhi_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1355
                test_fails(start_time, &testlist[tnum]);
1356
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
1357
 
1358
        txstr("\r\n");
1359
        txstr("-----------------------------------\r\n");
1360
        txstr("All tests passed.  Halting CPU.\r\n");
1361
        zip_halt();
1362
}
1363
 
1364
// To build this:
1365
//      zip-gcc -O3 -Wall -Wextra -nostdlib -fno-builtin -T xula.ld -Wl,-Map,cputest.map cputest.cpp -o cputest
1366
//      zip-objdump -D cputest > cputest.txt
1367
//

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.