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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [bench/] [asm/] [cputest.c] - Blame information for rev 168

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

Line No. Rev Author Line
1 168 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
#define NULL    (void *)0
37
volatile        int     *const UARTTX = (volatile int *)0x010b,
38
        * const UART_CTRL = (int *)0x0107;
39
// #define      ZIPSYS
40
#ifdef  ZIPSYS
41
#define HAVE_COUNTER
42
volatile        int * const PIC = (volatile int *)0xc0000000;
43
const int       INT_UARTTX = 0x2000;
44
volatile        int     *const COUNTER = (volatile int *)0xc0000008;
45
 
46
#define HAVE_SCOPE
47
 
48
#else
49
volatile        int     * const PIC = (volatile int *)0x0102;
50
const int       INT_UARTTX = 0x080;
51
volatile        int     *const TIMER = (volatile int *)0x0104;
52
#define HAVE_TIMER
53
#endif
54
 
55
#ifdef  HAVE_SCOPE
56
volatile        int     *const SCOPE = (volatile int *)0x011e;
57
#endif
58
 
59
unsigned        zip_ucc(void);
60
void            zip_save_context(int *);
61
void            zip_halt(void);
62
 
63
asm("\t.section\t.start\n"
64
        "\t.global\t_start\n"
65
        "\t.type\t_start,@function\n"
66
"_start:\n"
67
#ifdef  HAVE_SCOPE
68
        "\tNOOP\n"
69
        "\tLOD\t286,R0\n"
70
        "\tROL\t16,R0\n"
71
        "\tTST\t0x1000,R0\n"
72
        "\tBZ\t_start\n"
73
        "\tOR\t0x0f00,R0\n"
74
        "\tROL\t16,R0\n"
75
        "\tSTO\tR0,286\n"
76
#endif
77
        "\tCLR\tR0\n"
78
        "\tCLR\tR1\n"
79
        "\tCLR\tR2\n"
80
        "\tCLR\tR3\n"
81
        "\tCLR\tR4\n"
82
        "\tCLR\tR5\n"
83
        "\tCLR\tR6\n"
84
        "\tCLR\tR7\n"
85
        "\tCLR\tR8\n"
86
        "\tCLR\tR9\n"
87
        "\tCLR\tR10\n"
88
        "\tCLR\tR11\n"
89
        "\tCLR\tR12\n"
90
        "\tLDI\t_top_of_stack,SP\n"
91
        "\tCLR\tCC\n"
92
        "\tMOV\tbusy_failure(PC),R0\n"
93
        "\tBRA\tentry\n"
94
"busy_failure:\n"
95
        "\tBUSY\n"
96
        "\t.section\t.text");
97
 
98
#ifdef  HAVE_COUNTER
99
#define MARKSTART       start_time = *COUNTER
100
#define MARKSTOP        stop_time  = *COUNTER
101
#else
102
#ifdef  HAVE_TIMER
103
#define MARKSTART       start_time = *TIMER
104
#define MARKSTOP        stop_time  = *TIMER
105
#else
106
#define MARKSTART
107
#define MARKSTOP
108
#endif
109
#endif
110
 
111
 
112
extern  int     run_test(void *pc, void *stack);
113
asm("\t.global\trun_test\n"
114
        "\t.type\trun_test,@function\n"
115
"run_test:\n"
116
        "\tCLR\tR3\n"
117
        "\tMOV\ttest_return(PC),uR0\n"
118
        "\tMOV\tR3,uR1\n"
119
        "\tMOV\tR3,uR2\n"
120
        "\tMOV\tR3,uR3\n"
121
        "\tMOV\tR3,uR4\n"
122
        "\tMOV\tR3,uR5\n"
123
        "\tMOV\tR3,uR6\n"
124
        "\tMOV\tR3,uR7\n"
125
        "\tMOV\tR3,uR8\n"
126
        "\tMOV\tR3,uR9\n"
127
        "\tMOV\tR3,uR10\n"
128
        "\tMOV\tR1,uR11\n"
129
        "\tMOV\tR1,uR12\n"
130
        "\tMOV\tR2,uSP\n"
131
        "\tMOV\t0x20+R3,uCC\n"
132
        "\tMOV\tR1,uPC\n"
133
        "\tRTU\n"
134
"test_return:\n"
135
        "\tMOV\tuR1,R1\n"
136
        "\tAND\t0xffffffdf,CC\n"
137
        // Works with 5 NOOPS, works with 3 NOOPS, works with 1 NOOP
138
        "\tJMP\tR0\n");
139
 
140
void    break_one(void);
141
asm("\t.global\tbreak_one\n"
142
        "\t.type\tbreak_one,@function\n"
143
"break_one:\n"
144
        "\tLDI\t0,R1\n"
145
        "\tBREAK\n"
146
        "\tLDI\t1,R1\n" // Test fails
147
        "\tJMP\tR0");
148
 
149
void    break_two(void);
150
asm("\t.global\tbreak_two\n"
151
        "\t.type\tbreak_two,@function\n"
152
"break_two:\n"
153
        "\tLDI\t0,R1\n"
154
        "\tJMP\tR0\n"
155
        "\tBREAK\n");
156
 
157
void    early_branch_test(void);
158
asm("\t.global\tearly_branch_test\n"
159
        "\t.type\tearly_branch_test,@function\n"
160
"early_branch_test:\n"
161
        "\tLDI\t1,R1\n"
162
        "\tBRA\t_eb_a\n"
163
        "\tBREAK\n"
164
"_eb_a:\n"
165
        "\tLDI\t2,R1\n"
166
        "\tBRA\t_eb_b\n"
167
        "\tNOP\n"
168
        "\tBREAK\n"
169
"_eb_b:\n"
170
        "\tLDI\t3,R1\n"
171
        "\tBRA\t_eb_c\n"
172
        "\tNOP\n"
173
        "\tNOP\n"
174
        "\tBREAK\n"
175
"_eb_c:\n"
176
        "\tLDI\t4,R1\n"
177
        "\tBRA\t_eb_d\n"
178
        "\tNOP\n"
179
        "\tNOP\n"
180
        "\tNOP\n"
181
        "\tBREAK\n"
182
"_eb_d:\n"
183
        "\tLDI\t5,R1\n"
184
        "\tBRA\t_eb_e\n"
185
        "\tNOP\n"
186
        "\tNOP\n"
187
        "\tNOP\n"
188
        "\tNOP\n"
189
        "\tBREAK\n"
190
"_eb_e:\n"
191
        "\tLDI\t6,R1\n"
192
        "\tBRA\t_eb_f\n"
193
        "\tNOP\n"
194
        "\tNOP\n"
195
        "\tNOP\n"
196
        "\tNOP\n"
197
        "\tNOP\n"
198
        "\tBREAK\n"
199
"_eb_f:\n"
200
        "\tLDI\t0,R1\n"
201
        "\tJMP\tR0");
202
 
203
void    trap_test_and(void);
204
asm("\t.global\ttrap_test_and\n"
205
        "\t.type\ttrap_test_and,@function\n"
206
"trap_test_and:\n"
207
        "\tLDI\t0,R1\n"
208
        "\tAND\t0xffffffdf,CC\n"
209
        "\tLDI\t1,R1\n" // Test fails
210
        "\tJMP\tR0");
211
 
212
void    trap_test_clr(void);
213
asm("\t.global\ttrap_test_clr\n"
214
        "\t.type\ttrap_test_clr,@function\n"
215
"trap_test_clr:\n"
216
        "\tLDI\t0,R1\n"
217
        "\tCLR\tCC\n"
218
        "\tLDI\t1,R1\n" // Test fails
219
        "\tJMP\tR0");
220
 
221
void    overflow_test(void);
222
asm("\t.global\toverflow_test\n"
223
        "\t.type\toverflow_test,@function\n"
224
"overflow_test:\n"
225
        "\tLDI\t0,R1\n"
226
        "\tLDI\t0,R3\n"         // Clear our scorecard
227
// First test: does adding one to the maximum integer cause an overflow?
228
        "\tLDI\t-1,R2\n"
229
        "\tLSR\t1,R2\n"
230
        "\tADD\t1,R2\n"
231
        "\tOR.V\t1,R3\n"
232
// Second test: does subtracting one to the minimum integer cause an overflow?
233
        "\tLDI\t0x80000000,R2\n"
234
        "\tSUB\t1,R2\n"
235
        "\tOR.V\t2,R3\n"
236
// Third test, overflow from LSR
237
        "\tLDI\t0x80000000,R2\n"
238
        "\tLSR\t1,R2\n"         // Overflows 'cause the sign changes
239
        "\tOR.V\t4,R3\n"
240
// Fourth test, overflow from LSL
241
        "\tLDI\t0x40000000,R2\n"
242
        "\tLSL\t1,R2\n"
243
        "\tOR.V\t8,R3\n"
244
// Fifth test, overflow from LSL, negative to positive
245
        "\tLDI\t0x80000000,R2\n"
246
        "\tLSL\t1,R2\n"
247
        "\tOR.V\t16,R3\n"
248
// Record our scores
249
        "\tXOR\t31,R3\n"
250
        "\tOR\tR3,R1\n"
251
// And return the results
252
        "\tJMP\tR0");
253
 
254
 
255
void    carry_test(void);
256
asm("\t.global\tcarry_test\n"
257
        "\t.type\tcarry_test,@function\n"
258
"carry_test:\n"
259
        "\tLDI\t0,R1\n"
260
        "\tLDI\t0,R3\n"
261
// First, in adding
262
        "\tLDI\t-1,R2\n"
263
        "\tADD\t1,R2\n"
264
        "\tOR.C\t1,R3\n"
265
// Then, in subtraction
266
        "\tSUB\t1,R2\n"
267
        "\tOR.C\t2,R3\n"
268
// From a right shift
269
        "\tLDI\t1,R2\n"
270
        "\tLSR\t1,R2\n"
271
        "\tOR.C\t4,R3\n"
272
        "\tLDI\t1,R2\n"
273
        "\tASR\t1,R2\n"
274
        "\tOR.C\t8,R3\n"
275
// Or from a compare
276
        "\tLDI\t0,R2\n"
277
        "\tCMP\t1,R2\n"
278
        "\tOR.C\t16,R3\n"
279
// Set our return and clean up
280
        "\tXOR\t31,R3\n"
281
        "\tOR\tR3,R1\n"
282
        "\tJMP\tR0");
283
 
284
void    loop_test(void);
285
asm("\t.global\tloop_test\n"
286
        "\t.type\tloop_test,@function\n"
287
"loop_test:\n"
288
        "\tLDI\t0,R1\n"
289
// Let's try a loop: for(i=0; i<5; i++)
290
        "\tLDI\t0,R2\n"
291
        "\tLDI\t0,R3\n"
292
        "\tCMP\t5,R2\n"
293
        "\tBGE\tend_for_loop_test\n"
294
"for_loop_test:"
295
        "\tADD\t1,R2\n"
296
        "\tADD\t1,R3\n"
297
        "\tCMP\t5,R2\n"
298
        "\tBLT\tfor_loop_test\n"
299
"end_for_loop_test:"
300
        "\tCMP\t5,R3\n"
301
        "\tOR.NZ\t1,R1\n"
302
// How about a reverse do{} while loop?  These are usually cheaper than for()
303
// loops.
304
        "\tLDI\t0,R2\n"
305
        "\tLDI\t5,R3\n"
306
"bgt_loop_test:\n"
307
        "\tADD\t1,R2\n"
308
        "\tSUB\t1,R3\n"
309
        "\tBGT\tbgt_loop_test\n"
310
        "\tCMP\t5,R2\n"
311
        "\tOR.NZ\t2,R1\n"
312
// What if we use >=?
313
        "\tLDI\t0,R2\n"
314
        "\tLDI\t5,R3\n"
315
"bge_loop_test:\n"
316
        "\tADD\t1,R2\n"
317
        "\tSUB\t1,R3\n"
318
        "\tBGE\tbge_loop_test\n"
319
        "\tCMP\t6,R2\n"
320
        "\tOR.NZ\t4,R1\n"
321
// Once more with the reverse loop, this time storing the loop variable in
322
// memory
323
        "\tSUB\t1,SP\n"
324
        "\tLDI\t0,R2\n"
325
        "\tLDI\t5,R3\n"
326
        "\tSTO\tR3,(SP)\n"
327
"mem_loop_test:\n"
328
        "\tADD\t1,R2\n"
329
        "\tADD\t14,R3\n"
330
        "\tLOD\t(SP),R3\n"
331
        "\tSUB\t1,R3\n"
332
        "\tSTO\tR3,(SP)\n"
333
        "\tBGT\tmem_loop_test\n"
334
        "\tCMP\t5,R2\n"
335
        "\tOR.NZ\t8,R1\n"
336
        "\tADD\t1,SP\n"
337
//
338
        "\tJMP\tR0\n");
339
 
340
// Test whether or not LSL, LSR, and ASR instructions work, together with their
341
// carry flags
342
void    shift_test(void);
343
asm("\t.global\tshift_test\n"
344
        "\t.type\tshift_test,@function\n"
345
"shift_test:\n"
346
        "\tLDI\t0,R1\n"
347
        "\tLDI\t0,R3\n"
348
        "\tLDI\t0,R4\n"
349
// Does shifting right by 32 result in a zero?
350
        "\tLDI\t-1,R2\n"
351
        "\tLSR\t32,R2\n"
352
        "\tOR.Z\t1,R3\n"
353
        "\tOR.C\t2,R3\n"
354
        "\tCMP\t0,R2\n"
355
        "\tOR.Z\t4,R3\n"
356
// Does shifting a -1 right arithmetically by 32 result in a -1?
357
        "\tLDI\t-1,R2\n"
358
        "\tASR\t32,R2\n"
359
        "\tOR.LT\t8,R3\n"
360
        "\tOR.C\t16,R3\n"
361
        "\tCMP\t-1,R2\n"
362
        "\tOR.Z\t32,R3\n"
363
// Does shifting a -4 right arithmetically by 2 result in a -1?
364
        "\tLDI\t-4,R2\n"
365
        "\tASR\t2,R2\n"
366
        "\tOR.LT\t64,R3\n"
367
        "\tOR.C\t128,R1\n"
368
        "\tOR\t128,R3\n" // Artificially declare passing, so as not to fail it
369
        "\tCMP\t-1,R2\n"
370
        "\tOR.Z\t256,R3\n"
371
// Does one more set the carry flag as desired?
372
        "\tASR\t1,R2\n"
373
        "\tOR.LT\t512,R3\n"
374
        "\tOR.C\t1024,R3\n"
375
        "\tCMP\t-1,R2\n"
376
        "\tOR.Z\t2048,R3\n"
377
// Does shifting -1 left by 32 result in a zero?
378
        "\tLDI\t-1,R2\n"
379
        "\tLSL\t32,R2\n"
380
        "\tOR.Z\t4096,R3\n"
381
        "\tOR.C\t8192,R3\n"
382
        "\tCMP\t0,R2\n"
383
        "\tOR.Z\t16384,R3\n"
384
// How about shifting by zero?
385
        "\tLDI\t-1,R2\n"
386
        "\tASR\t0,R2\n"
387
        "\tOR.C\t32768,R1\n"
388
        "\tOR\t32768,R3\n"
389
        "\tCMP\t-1,R2\n"
390
        "\tOR.Z\t1,R4\n"
391
// 
392
        "\tLSR\t0,R2\n"
393
        "\tOR.C\t131072,R1\n"
394
        "\tCMP\t-1,R2\n"
395
        "\tOR.Z\t2,R4\n"
396
//
397
        "\tLSL\t0,R2\n"
398
        "\tOR.C\t524288,R1\n"
399
        "\tCMP\t-1,R2\n"
400
        "\tOR.Z\t4,R4\n"
401
// Tally up our results and return
402
        "\tXOR\t7,R4\n"
403
        "\tXOR\t65535,R3\n"
404
        "\tLSL\t16,R4\n"
405
        "\tOR\tR4,R3\n"
406
        "\tOR\tR3,R1\n"
407
        "\tJMP\tR0");
408
 
409
int     sw_brev(int v);
410
asm("\t.global\tsw_brev\n"
411
        "\t.type\tsw_brev,@function\n"
412
"sw_brev:\n"
413
        "\tSUB\t2,SP\n"
414
        "\tSTO\tR2,(SP)\n"
415
        "\tSTO\tR3,1(SP)\n"
416
        "\tLDI\t-1,R2\n"
417
        "\tCLR\tR3\n"
418
"sw_brev_loop:\n"
419
        "\tLSL\t1,R3\n"
420
        "\tLSR\t1,R1\n"
421
        "\tOR.C\t1,R3\n"
422
        "\tLSR\t1,R2\n"
423
        "\tBZ\tsw_brev_endloop\n"
424
        "\tBRA\tsw_brev_loop\n"
425
"sw_brev_endloop:\n"
426
        "\tMOV\tR3,R1\n"
427
        "\tLOD\t(SP),R2\n"
428
        "\tLOD\t1(SP),R3\n"
429
        "\tADD\t2,SP\n"
430
        "\tJMP\tR0");
431
 
432
void    pipeline_stack_test(void);
433
asm("\t.global\tpipeline_stack_test\n"
434
        "\t.type\tpipeline_stack_test,@function\n"
435
"pipeline_stack_test:\n"
436
        "\tSUB\t1,SP\n"
437
        "\tSTO\tR0,(SP)\n"
438
        "\tLDI\t0,R0\n"
439
        "\tMOV\t1(R0),R1\n"
440
        "\tMOV\t1(R1),R2\n"
441
        "\tMOV\t1(R2),R3\n"
442
        "\tMOV\t1(R3),R4\n"
443
        "\tMOV\t1(R4),R5\n"
444
        "\tMOV\t1(R5),R6\n"
445
        "\tMOV\t1(R6),R7\n"
446
        "\tMOV\t1(R7),R8\n"
447
        "\tMOV\t1(R8),R9\n"
448
        "\tMOV\t1(R9),R10\n"
449
        "\tMOV\t1(R10),R11\n"
450
        "\tMOV\t1(R11),R12\n"
451
        "\tMOV\tpipeline_stack_test_component_return(PC),R0\n"
452
        // "\tLJMP\tpipeline_stack_test_component\n"
453
        "\tBRA\tpipeline_stack_test_component\n"
454
"pipeline_stack_test_component_return:\n"
455
        "\tCMP\t1,R1\n"
456
        "\tLDI.Z\t0,R1\n"
457
        "\tCMP\t2,R2\n"
458
        "\tCMP.Z\t3,R3\n"
459
        "\tCMP.Z\t4,R4\n"
460
        "\tCMP.Z\t5,R5\n"
461
        "\tCMP.Z\t6,R6\n"
462
        "\tCMP.Z\t7,R7\n"
463
        "\tCMP.Z\t8,R8\n"
464
        "\tCMP.Z\t9,R9\n"
465
        "\tCMP.Z\t10,R10\n"
466
        "\tCMP.Z\t11,R11\n"
467
        "\tCMP.Z\t12,R12\n"
468
        "\tBREV.NZ\t-1,R1\n"
469
        "\tLOD\t(SP),R0\n"
470
        "\tADD\t1,SP\n"
471
        "\tJMP\tR0\n"
472
        );
473
 
474
void    pipeline_stack_test_component(void);
475
asm("\t.global\tpipeline_stack_test_component\n"
476
        "\t.type\tpipeline_stack_test_component,@function\n"
477
"pipeline_stack_test_component:\n"
478
        "\tSUB\t13,SP\n"
479
        "\tSTO\tR0,(SP)\n"
480
        "\tSTO\tR1,1(SP)\n"
481
        "\tSTO\tR2,2(SP)\n"
482
        "\tSTO\tR3,3(SP)\n"
483
        "\tSTO\tR4,4(SP)\n"
484
        "\tSTO\tR5,5(SP)\n"
485
        "\tSTO\tR6,6(SP)\n"
486
        "\tSTO\tR7,7(SP)\n"
487
        "\tSTO\tR8,8(SP)\n"
488
        "\tSTO\tR9,9(SP)\n"
489
        "\tSTO\tR10,10(SP)\n"
490
        "\tSTO\tR11,11(SP)\n"
491
        "\tSTO\tR12,12(SP)\n"
492
        "\tXOR\t-1,R0\n"
493
        "\tXOR\t-1,R1\n"
494
        "\tXOR\t-1,R2\n"
495
        "\tXOR\t-1,R3\n"
496
        "\tXOR\t-1,R4\n"
497
        "\tXOR\t-1,R5\n"
498
        "\tXOR\t-1,R6\n"
499
        "\tXOR\t-1,R7\n"
500
        "\tXOR\t-1,R8\n"
501
        "\tXOR\t-1,R9\n"
502
        "\tXOR\t-1,R10\n"
503
        "\tXOR\t-1,R11\n"
504
        "\tXOR\t-1,R12\n"
505
        "\tLOD\t(SP),R0\n"
506
        "\tLOD\t1(SP),R1\n"
507
        "\tLOD\t2(SP),R2\n"
508
        "\tLOD\t3(SP),R3\n"
509
        "\tLOD\t4(SP),R4\n"
510
        "\tLOD\t5(SP),R5\n"
511
        "\tLOD\t6(SP),R6\n"
512
        "\tLOD\t7(SP),R7\n"
513
        "\tLOD\t8(SP),R8\n"
514
        "\tLOD\t9(SP),R9\n"
515
        "\tLOD\t10(SP),R10\n"
516
        "\tLOD\t11(SP),R11\n"
517
        "\tLOD\t12(SP),R12\n"
518
        "\tADD\t13,SP\n"
519
        "\tJMP\tR0\n");
520
 
521
//mpy_test
522
void    mpy_test(void);
523
asm("\t.global\tmpy_test\n"
524
        "\t.type\tmpy_test,@function\n"
525
"mpy_test:\n"
526
        "\tCLR\tR1\n"
527
        // First test: let's count multiples of 137
528
        "\tLDI\t137,R2\n"       // What we're doing multiples of
529
        "\tCLR\tR3\n"           // Our accumulator via addition
530
        "\tCLR\tR4\n"           // Our index for multiplication
531
        "mpy_137_test_loop:\n"
532
        "\tMOV\tR2,R5\n"
533
        "\tMPY\tR4,R5\n"
534
        "\tCMP\tR3,R5\n"
535
        "\tBNZ\tend_mpy_137_test_loop_failed\n"
536
        // Let's try negative while we are at it
537
        "\tMOV\tR2,R6\n"
538
        "\tNEG\tR6\n"
539
        "\tMPY\tR4,R6\n"
540
        "\tNEG\tR6\n"
541
        "\tCMP\tR3,R6\n"
542
        "\tBNZ\tend_mpy_137_test_loop_failed\n"
543
        "\tCLR\tR6\n"
544
        "\tTEST\t0xffff0000,R3\n"
545
        "\tBNZ\tend_mpy_137_test_loop\n"
546
        "\tADD\tR2,R3\n"
547
        "\tADD\t1,R4\n"
548
        "\tBRA\tmpy_137_test_loop\n"
549
"end_mpy_137_test_loop_failed:\n"
550
        "\tOR\t1,R1\n"
551
"end_mpy_137_test_loop:\n"
552
        // Second test ... whatever that might be
553
        "\tJMP\tR0\n");
554
 
555
//brev_test
556
//pipeline_test -- used to be called pipeline memory race conditions
557
void    pipeline_test(void);
558
asm("\t.global\tpipeline_test\n"
559
        "\t.type\tpipeline_test,@function\n"
560
"pipeline_test:\n"
561
        "\tSUB\t2,SP\n"
562
        // Test setup
563
        "\tLDI\t275,R2\n"
564
        "\tSTO\tR2,1(SP)\n"
565
        "\tMOV\t1(SP),R2\n"
566
        "\tSTO\tR2,(SP)\n"
567
        "\tCLR\tR2\n"
568
        //
569
        "\tMOV\tSP,R2\n"
570
        "\tLOD\t(R2),R2\n"
571
        "\tLOD\t(R2),R2\n"
572
        "\tCMP\t275,R2\n"
573
        "\tOR.NZ\t1,R1\n"
574
        //
575
        "\tMOV\tSP,R2\n"
576
        // Here's the test sequence
577
        "\tLOD\t(R2),R3\n"
578
        "\tLOD\t1(R2),R4\n"
579
        "\tSTO\tR4,1(R3)\n"
580
        // Make sure we clear the load pipeline
581
        "\tLOD\t(R2),R3\n"
582
        // Load our written value
583
        "\tLOD\t2(R2),R4\n"
584
        "\tCMP\t275,R4\n"
585
        "\tOR.NZ\t2,R1\n"
586
        //
587
        //
588
        // Next (once upon a time) failing sequence:
589
        //      LOD -x(R12),R0
590
        //      LOD y(R0),R0
591
        "\tMOV\tSP,R2\n"
592
        "\tMOV\t1(R2),R3\n"
593
        "\tSTO\tR3,1(R2)\n"
594
        "\tLDI\t3588,R4\n"      // Just some random value
595
        "\tSTO\tR4,2(R2)\n"
596
        "\tMOV\tR2,R3\n"
597
        // Here's the test sequence
598
        "\tLOD\t(R2),R3\n"
599
        "\tLOD\t1(R3),R3\n"
600
        "\tCMP\tR4,R3\n"
601
        "\tOR.NZ\t4,R1\n"
602
        //
603
        "\tADD\t2,SP\n"
604
        "\tJMP\tR0\n");
605
 
606
//mempipe_test
607
void    mempipe_test(void);
608
asm("\t.global\tmempipe_test\n"
609
        "\t.type\tmempipe_test,@function\n"
610
"mempipe_test:\n"
611
        "\tSUB\t4,SP\n"
612
        "\tSTO\tR0,(SP)\n"
613
        "\tLDI\t0x1000,R11\n"
614
        // Test #1 ... Let's start by writing a value to memory
615
        "\tLDI\t-1,R2\n"
616
        "\tCLR\tR3\n"
617
        "\tSTO\tR2,2(SP)\n"
618
        "\tLOD\t2(SP),R3\n"
619
        "\tCMP\tR3,R2\n"
620
        "\tOR.NZ\t1,R1\n"
621
        // Test #2, reading and then writing a value from memory
622
        "\tNOOP\n"
623
        "\tNOOP\n"
624
        "\tCLR\tR2\n"
625
        "\tCLR\tR3\n"
626
        "\tLOD\t2(SP),R2\n"     // This should load back up our -1 value
627
        "\tSTO\tR2,3(SP)\n"
628
        // Insist that the pipeline clear
629
        "\tLOD\t2(SP),R2\n"
630
        // Now let's try loading into R3
631
        "\tNOOP\n"
632
        "\tNOOP\n"
633
        "\tNOOP\n"
634
        "\tNOOP\n"
635
        "\tLOD\t3(SP),R3\n"
636
        "\tCMP\tR3,R2\n"
637
        "\tOR.NZ\t2,R1\n"
638
        //
639
        "\tLOD\t(SP),R0\n"
640
        "\tADD\t4,SP\n"
641
        "\tJMP\tR0\n");
642
 
643
//cexec_test
644
void    cexec_test(void);
645
asm("\t.global\tcexec_test\n"
646
        "\t.type\tcexec_test,@function\n"
647
"cexec_test:\n"
648
        "\tSUB\t1,SP\n"
649
        "\tSTO\tR0,(SP)\n"
650
        //
651
        "\tXOR\tR2,R2\n"
652
        "\tADD.Z\t1,R2\n"
653
        "\tADD.NZ\t1,R1\n"
654
        "\tCMP.Z\t0,R2\n"
655
        "\tOR.Z\t2,R1\n"
656
        //
657
        "\tLOD\t(SP),R0\n"
658
        "\tADD\t1,SP\n"
659
        "\tJMP\tR0\n");
660
 
661
// Pipeline stalls have been hideous problems for me.  The CPU has been modified
662
// with special logic to keep stages from stalling.  For the most part, this
663
// means that ALU and memory results may be accessed either before or as they
664
// are written to the register file.  This set of code is designed to test
665
// whether this bypass logic works.
666
//
667
//nowaitpipe_test
668
void    nowaitpipe_test(void);
669
asm("\t.global\tnowaitpipe_test\n"
670
        "\t.type\tnowaitpipe_test,@function\n"
671
"nowaitpipe_test:\n"
672
        "\tSUB\t2,SP\n"
673
        //
674
        // Let's start with ALU-ALU testing
675
        //      AA: result->input A
676
        "\tLDI\t-1,R2\n"
677
        "\tCLR\tR2\n"
678
        "\tADD\t1,R2\n"
679
        "\tCMP\t1,R2\n"
680
        "\tOR.NZ\t1,R1\n"
681
        //
682
        //      AA: result -> input B
683
        "\tCLR\tR2\n"
684
        "\tCLR\tR3\n"
685
        "\tADD\t1,R2\n"
686
        "\tCMP\tR2,R3\n"
687
        "\tOR.Z\t2,R1\n"
688
        //      AA: result -> input A on condition
689
        "\tXOR\tR2,R2\n"
690
        "\tADD.Z\t5,R2\n"
691
        "\tCMP\t5,R2\n"
692
        "\tOR.NZ\t4,R1\n"
693
        //      AA: result -> input B on condition
694
        "\tCLR\tR2\n"
695
        "\tXOR\tR3,R3\n"
696
        "\tADD.Z\t5,R2\n"
697
        "\tCMP\tR2,R3\n"
698
        "\tOR.Z\t8,R1\n"
699
        //      AA: result->input B plus offset
700
        "\tCLR\tR2\n"
701
        "\tXOR\tR3,R3\n"
702
        "\tADD\t5,R2\n"
703
        "\tCMP\t-5(R2),R3\n"
704
        "\tOR.NZ\t16,R1\n"
705
        //      AA: result->input B plus offset on condition
706
        "\tCLR\tR2\n"
707
        "\tXOR\tR3,R3\n"
708
        "\tADD.Z\t5,R2\n"
709
        "\tCMP\t-5(R2),R3\n"
710
        "\tOR.NZ\t32,R1\n"
711
        //
712
        // Then we need to do the ALU-MEM input testing
713
        //
714
        "\tCLR\tR2\n"
715
        "\tSTO\tR2,1(SP)\n"
716
        "\tLDI\t8352,R2\n"
717
        "\tLOD\t1(SP),R2\n"
718
        "\tTST\t-1,R2\n"
719
        "\tOR.NZ\t64,R1\n"
720
        // Let's try again, this time with something that's not zero
721
        "\tLDI\t937,R2\n"
722
        "\tSTO\tR2,1(SP)\n"
723
        "\tNOOP\n"
724
        "\tLOD\t1(SP),R2\n"
725
        "\tCMP\t938,R2\n"
726
        "\tOR.GE\t128,R1\n"
727
        "\tCMP\t936,R2\n"
728
        "\tOR.LT\t256,R1\n"
729
        // Mem output->ALU input testing
730
        //      Okay, we just did that as part of our last test
731
        // Mem output->mem input testing
732
        "\tLDI\t5328,R2\n"
733
        "\tLOD\t1(SP),R2\n"
734
        "\tSTO\tR2,1(SP)\n"
735
        "\tLOD\t1(SP),R3\n"
736
        "\tCMP\t937,R3\n"
737
        "\tOR.NZ\t512,R1\n"
738
        //
739
        "\tADD\t2,SP\n"
740
        "\tJMP\tR0\n");
741
 
742
//bcmem_test
743
void    bcmem_test(void);
744
asm("\t.global\tbcmem_test\n"
745
        "\t.type\tbcmem_test,@function\n"
746
"bcmem_test:\n"
747
        "\tSUB\t1,SP\n"
748
        "\tCLR\tR1\n"
749
        "\tCLR\tR2\n"
750
        "\tLDI\t-1,R3\n"
751
        "\tLDI\t0x13000,R4\n"
752
        "\tSTO\tR2,(SP)\n"
753
        "\tLOD\t(SP),R3\n"
754
        "\tCMP\tR2,R3\n"
755
        "\tOR.NZ\t1,R1\n"
756
        "\tCMP\t0x13000,R4\n"
757
        "\tBZ\tbcmem_test_cmploc_1\n"
758
        "\tSTO\tR4,(SP)\n"
759
"bcmem_test_cmploc_1:\n"
760
        "\tLOD\t(SP),R2\n"
761
        "\tCMP\tR2,R4\n"
762
        "\tOR.Z\t2,R1\n"
763
        "\tCLR\tR2\n"
764
        "\tCMP\tR2,R4\n"
765
        "\tBZ\tbcmem_test_cmploc_2\n"
766
        "\tSTO.NZ\tR4,(SP)\n"
767
"bcmem_test_cmploc_2:\n"
768
        "\tLOD\t(SP),R2\n"
769
        "\tCMP\tR2,R4\n"
770
        "\tOR.NZ\t4,R1\n"
771
//
772
        "\tADD\t1,SP\n"
773
        "\tJMP\tR0\n");
774
 
775
//
776
// The CC register has some ... unique requirements associated with it.
777
// Particularly, flags are unavailable until after an ALU operation completes,
778
// and they can't really be bypassed for the CC register.  After writeback,
779
// the "new" CC register isn't really available for another clock.  Trying to
780
// bypass this extra clock can have problems, since ... some bits are fixed,
781
// some bits can only be changed by the supervisor, and others can/will change
782
// and even have effects--like sending the CPU to supervisor mode or
783
// alternatively to sleep.
784
//
785
// Here, let's see if our pipeline can successfully navigate any of these
786
// issues.
787
//
788
void    ccreg_test(void);
789
asm("\t.global\tccreg_test\n"
790
        "\t.type\tccreg_test,@function\n"
791
"ccreg_test:\n"
792
        // First test: If we try to change the fixed bits, will they change
793
        // because the pipeline tries to bypass the write-back stage
794
        "\tCLR\tR1\n"   // We'll start with an "answer" of success
795
        "\tMOV\tCC,R2\n"
796
        "\tMOV\tR2,R4\n"        // Keep a copy
797
        "\tBREV\t0x0ff,R3\n"    // Attempt to change the top fixed bits
798
        "\tXOR\tR3,R2\n"        // Arrange for the changes
799
        "\tMOV\tR2,CC\n"        // Set the changes (they won't take)
800
        "\tMOV\tCC,R5\n"        // See if the pipeline makes them take
801
        "\tXOR\tR4,R5\n"        // Let's look for anything that has changed
802
        "\tOR.NZ\t1,R1\n"       // If anything has changed, then we fail the tst
803
        // 
804
        // Test #2: Can we set the flags?
805
        "\tMOV\tCC,R6\n"
806
        "\tOR\t15,R6\n"
807
        "\tMOV\tR6,CC\n"
808
        "\tMOV\tCC,R7\n"
809
        "\tAND\t15,R7\n"
810
        "\tCMP\t15,R7\n"
811
        "\tOR.NZ\t2,R1\n"
812
        //
813
        // Test #3: How about setting specific flags, and immediately acting
814
        // on them?
815
        "\tXOR\t1+R8,R8\n"      // Turn off the Z bit
816
        "\tOR\t1,CC\n"          // Turn on the Z bit
817
        "\tOR.NZ\t4,R1\n"
818
        //
819
        // Test #4: Can we load the CC plus a value into a register?
820
        //      I don't think so ...
821
        "\tJMP\tR0\n");
822
 
823
__attribute__((noinline))
824
void    wait(unsigned int msk) {
825
        *PIC = 0x7fff0000|msk;
826
        asm("MOV\tidle_task(PC),uPC\n");
827
        *PIC = 0x80000000|(msk<<16);
828
        asm("WAIT\n");
829
        *PIC = 0; // Turn interrupts back off, lest they confuse the test
830
}
831
 
832
asm("\nidle_task:\n\tWAIT\n\tBRA\tidle_task\n");
833
 
834
__attribute__((noinline))
835
void    txchr(char v) {
836
        wait(INT_UARTTX);
837
        *UARTTX = v;
838
}
839
 
840
__attribute__((noinline))
841
void    txstr(const char *str) {
842
        const char *ptr = str;
843
        while(*ptr)
844
                txchr(*ptr++);
845
}
846
 
847
__attribute__((noinline))
848
void    txhex(int num) {
849
        for(int ds=28; ds>=0; ds-=4) {
850
                int     ch;
851
                ch = (num >> ds)&0x0f;
852
                if (ch >= 10)
853
                        ch = 'A'+ch-10;
854
                else
855
                        ch += '0';
856
                txchr(ch);
857
        }
858
}
859
 
860
__attribute__((noinline))
861
void    txreg(const char *name, int val) {
862
        txstr(name);    // 4 characters
863
        txstr("0x");    // 2 characters
864
        txhex(val);     // 8 characters
865
        txstr("    ");  // 4 characters
866
}
867
 
868
__attribute__((noinline))
869
void    save_context(int *context) {
870
        zip_save_context(context);
871
}
872
 
873
__attribute__((noinline))
874
void    test_fails(int start_time, int *listno) {
875
        int     context[16], stop_time;
876
 
877
        // Trigger the scope, if it hasn't already triggered.  Otherwise,
878
        // if it has triggered, don't clear it.
879
#ifdef  HAVE_SCOPE
880
        *SCOPE = 0x8f000004;
881
#endif
882
 
883
        MARKSTOP;
884
        save_context(context);
885
        *listno++ = context[1];
886
        *listno++ = context[14];
887
        *listno++ = context[15];
888
#ifdef  HAVE_COUNTER
889
        *listno   = stop_time;
890
#endif
891
 
892
        txstr("FAIL!\r\n\r\n");
893
        txstr("Between 0x"); txhex(start_time);
894
                txstr(" and 0x"); txhex(stop_time); txstr("\r\n\r\n");
895
        txstr("Core-dump:\r\n");
896
        txreg("uR0 : ", context[0]);
897
        txreg("uR1 : ", context[1]);
898
        txreg("uR2 : ", context[2]);
899
        txreg("uR3 : ", context[3]);
900
        txstr("\r\n");
901
 
902
        txreg("uR4 : ", context[4]);
903
        txreg("uR5 : ", context[5]);
904
        txreg("uR6 : ", context[6]);
905
        txreg("uR7 : ", context[7]);
906
        txstr("\r\n");
907
 
908
        txreg("uR8 : ", context[8]);
909
        txreg("uR9 : ", context[9]);
910
        txreg("uR10: ", context[10]);
911
        txreg("uR11: ", context[11]);
912
        txstr("\r\n");
913
 
914
        txreg("uR12: ", context[12]);
915
        txreg("uSP : ", context[13]);
916
        txreg("uCC : ", context[14]);
917
        txreg("uPC : ", context[15]);
918
        txstr("\r\n\r\n");
919
 
920
        asm("\tBUSY");
921
}
922
 
923
void    testid(const char *str) {
924
        const int       WIDTH=32;
925
        txstr(str);
926
        const char *ptr = str;
927
        int     i = 0;
928
        while(0 != *ptr++)
929
                i++;
930
        i = WIDTH-i;
931
        while(i-- > 0)
932
                txchr(' ');
933
}
934
 
935
int     testlist[32];
936
 
937
void entry(void) {
938
        int     context[16];
939
        int     user_stack[256], *user_stack_ptr = &user_stack[256];
940
        int     start_time, i;
941
 
942
        for(i=0; i<32; i++)
943
                testlist[i] = -1;
944
 
945
#ifdef  HAVE_TIMER
946
        *TIMER = 0x7fffffff;
947
#endif
948
#ifdef  HAVE_COUNTER
949
        *COUNTER = 0;
950
#endif
951
 
952
#define STACKTEST       asm("CMP\t16108,SP\n\tHALT.NZ\n")
953
        STACKTEST;
954
 
955
        // *UART_CTRL = 8333; // 9600 Baud, 8-bit chars, no parity, one stop bit
956
        *UART_CTRL = 25; // 9600 Baud, 8-bit chars, no parity, one stop bit
957
        //
958
        STACKTEST;
959
 
960
        txstr("\r\n");
961
        txstr("Running CPU self-test\n");
962
        txstr("-----------------------------------\r\n");
963
 
964
        int     tnum = 0;
965
        STACKTEST;
966
 
967
        // Test break instruction in user mode
968
        // Make sure the break works as designed
969
        testid("Break test #1"); MARKSTART;
970
        STACKTEST;
971
 
972
        if ((run_test(break_one, user_stack_ptr))||(zip_ucc()&0x1f50))
973
                test_fails(start_time, &testlist[tnum]);
974
        STACKTEST;
975
 
976
        save_context(context);
977
        if (context[15] != (int)break_one+1)
978
                test_fails(start_time, &testlist[tnum]);
979
        if (0==(zip_ucc()&0x80))
980
                test_fails(start_time, &testlist[tnum]);
981
        txstr("Pass\r\n"); testlist[tnum++] = 0; // 0
982
 
983
        STACKTEST;
984
 
985
        // Test break instruction in user mode
986
        // Make sure that a decision on the clock prior won't still cause a 
987
        // break condition
988
        testid("Break test #2"); MARKSTART;
989
        if ((run_test(break_two, user_stack_ptr))||(zip_ucc()&0x1f10))
990
                test_fails(start_time, &testlist[tnum]);
991
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #1
992
 
993
        // LJMP test ... not (yet) written
994
 
995
        // Test the early branching capability
996
        //      Does it successfully clear whatever else is in the pipeline?
997
        testid("Early Branch test"); MARKSTART;
998
        if ((run_test(early_branch_test, user_stack_ptr))||(zip_ucc()&0x01d90))
999
                test_fails(start_time, &testlist[tnum]);
1000
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #2
1001
 
1002
        // TRAP test
1003
        testid("Trap test/AND"); MARKSTART;
1004
        if ((run_test(trap_test_and, user_stack_ptr))||(zip_ucc()&0x01d90))
1005
                test_fails(start_time, &testlist[tnum]);
1006
        if ((zip_ucc() & 0x0200)==0)
1007
                test_fails(start_time, &testlist[tnum]);
1008
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #3
1009
 
1010
        testid("Trap test/CLR"); MARKSTART;
1011
        if ((run_test(trap_test_clr, user_stack_ptr))||(zip_ucc()&0x01d90))
1012
                test_fails(start_time, &testlist[tnum]);
1013
        if ((zip_ucc() & 0x0200)==0)
1014
                test_fails(start_time, &testlist[tnum]);
1015
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #4
1016
 
1017
        // Overflow test
1018
        testid("Overflow test"); MARKSTART;
1019
        if ((run_test(overflow_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1020
                test_fails(start_time, &testlist[tnum]);
1021
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #5
1022
 
1023
        // Carry test
1024
        testid("Carry test"); MARKSTART;
1025
        if ((run_test(carry_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1026
                test_fails(start_time, &testlist[tnum]);
1027
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #6
1028
 
1029
        // LOOP_TEST
1030
        testid("Loop test"); MARKSTART;
1031
        if ((run_test(loop_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1032
                test_fails(start_time, &testlist[tnum]);
1033
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #7 -- FAILS
1034
 
1035
        // SHIFT_TEST
1036
        testid("Shift test"); MARKSTART;
1037
        if ((run_test(shift_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1038
                test_fails(start_time, &testlist[tnum]);
1039
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #8
1040
 
1041
        // MPY_TEST
1042
        testid("Multiply test"); MARKSTART;
1043
        if ((run_test(mpy_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1044
                test_fails(start_time, &testlist[tnum]);
1045
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #9
1046
 
1047
        // BREV_TEST
1048
        //testid("BREV/stack test"); MARKSTART;
1049
        //if ((run_test(brev_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1050
                //test_fails(start_time);
1051
        //txstr("Pass\r\n");
1052
 
1053
        // PIPELINE_TEST
1054
        testid("Pipeline test"); MARKSTART;
1055
        if ((run_test(pipeline_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1056
                test_fails(start_time, &testlist[tnum]);
1057
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #10
1058
 
1059
        // MEM_PIPELINE_STACK_TEST
1060
        testid("Mem-Pipeline test"); MARKSTART;
1061
        if ((run_test(mempipe_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1062
                test_fails(start_time, &testlist[tnum]);
1063
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #11
1064
 
1065
        // CONDITIONAL EXECUTION test
1066
        testid("Conditional Execution test"); MARKSTART;
1067
        if ((run_test(cexec_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1068
                test_fails(start_time, &testlist[tnum]);
1069
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #12 -- FAILS
1070
 
1071
        // NOWAIT pipeline test
1072
        testid("No-waiting pipeline test"); MARKSTART;
1073
        if ((run_test(nowaitpipe_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1074
                test_fails(start_time, &testlist[tnum]);
1075
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #13
1076
 
1077
        // BCMEM test
1078
        testid("Conditional Branching test"); MARKSTART;
1079
        if ((run_test(bcmem_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1080
                test_fails(start_time, &testlist[tnum]);
1081
        txstr("Pass\r\n"); testlist[tnum++] = 0; // #14
1082
 
1083
        // Illegal Instruction test
1084
        testid("Illegal Instruction test"); MARKSTART;
1085
        if ((run_test(NULL, user_stack_ptr))||((zip_ucc()^0x100)&0x01d90))
1086
                test_fails(start_time, &testlist[tnum]);
1087
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1088
 
1089
        // Pipeline memory race condition test
1090
        // DIVIDE test
1091
 
1092
        // CC Register test
1093
        testid("CC Register test"); MARKSTART;
1094
        if ((run_test(ccreg_test, user_stack_ptr))||(zip_ucc()&0x01d90))
1095
                test_fails(start_time, &testlist[tnum]);
1096
        txstr("Pass\r\n"); testlist[tnum++] = 0;
1097
 
1098
        txstr("\r\n");
1099
        txstr("-----------------------------------\r\n");
1100
        txstr("All tests passed.  Halting CPU.\n");
1101
        zip_halt();
1102
}
1103
 
1104
// To build this:
1105
//      zip-gcc -O3 -Wall -Wextra -nostdlib -fno-builtin -T xula.ld -Wl,-Map,cputest.map cputest.cpp -o cputest
1106
//      zip-objdump -D cputest > cputest.txt
1107
//

powered by: WebSVN 2.1.0

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