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

Subversion Repositories systemc_cordic

[/] [systemc_cordic/] [trunk/] [cordic_ip/] [testbench.cpp.fullpipe] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 wwcheng
// testbench.cpp: source file
2
/********************************************************************
3
//
4
// Module:
5
//   Testbench feeding instructions into Cordic core
6
//
7
// Implementation:
8
//   This module tests the Rotate, Magnitude-Phase, Sin-Cos and
9
//   Sinh-Cosh CORDIC engines.
10
//
11
//
12
// Authors:     Winnie Cheng,
13
//              Peter Wu
14
//
15
 *********************************************************************/
16
 
17
#include "testbench.h"
18
#include "opcode.h"
19
#include "convert.h"
20
#include 
21
 
22
#define ROTATE_NUM_TEST         1
23
#define MAGPHASE_NUM_TEST       1
24
#define SINCOS_NUM_TEST         1
25
#define SINHCOSH_NUM_TEST       1
26
 
27
#ifdef MODULE_NAME
28
#undef MODULE_NAME
29
#endif
30
 
31
#define MODULE_NAME     "[testbench]"
32
 
33
#define DEBUG           1
34
#ifdef DEBUG
35
#define dprintf         printf
36
#else
37
#define dprintf
38
#endif
39
 
40
#define PROGFILE        "userprog.dat"
41
#define LOGFILE         "testpipe.log"
42
#define MAX_PROGSIZE    24
43
#define MAX_STR_LEN     128
44
 
45
void testbench::readfifo_process()
46
{
47
    fifo_read_request.write(true);
48
    wait();
49
 
50
    // monitor fifo output
51
    while(1) {
52
        wait();
53
        if(fifo_valid.read()) {
54
            printf("%s opcode %x, result1 %f, result2 %f\n", MODULE_NAME,(short) fifo_opcode.read(), tofp(fifo_result1.read()), tofp(fifo_result2.read()));
55
        } else {
56
            dprintf("%s no data read from fifo\n", MODULE_NAME);
57
        }
58
    }
59
}
60
 
61
void testbench::testbench_process()
62
{
63
    short i;
64
    double x, y, a;
65
    double rad, correct_x, correct_y;
66
    double computed_v1, computed_v2;
67
    int fixed1, fixed2;
68
    bool success, skip;
69
    int retval;
70
    char ir[MAX_STR_LEN];
71
    char op[3][MAX_STR_LEN];
72
    int file_opcode;
73
    int num_instr;
74
    FILE *logfile;
75
 
76
    // Opens user program file for reading
77
    FILE *infile = fopen(PROGFILE, "r");
78
 
79
    if(!infile) {
80
        cout << MODULE_NAME << "File does not exist: " << PROGFILE << endl;
81
        exit(-1);
82
    }
83
 
84
    // Initialize output
85
 
86
    done.write(false);
87
    instructions_valid.write(false);
88
    start_monitor.write(false);
89
    wait();
90
 
91
    wait_until(start.delayed()==true);
92
    printf("%s Testbench for CORDIC engines\n", MODULE_NAME);
93
    success = true;
94
 
95
    // Test Rotate Engine
96
    for(i = 0; i < ROTATE_NUM_TEST; i++) {
97
        wait();
98
 
99
        // Generate random input
100
        a = 1.0*((rand()>>2)%360)-180.0;
101
        x = 1.0*((rand()>>2)%100);
102
        y = 1.0*((rand()>>2)%100);
103
        cout << MODULE_NAME << "Rotate(" << x << ", " << y << ", " << a << ")" << endl;
104
 
105
        // activate the rotate engine
106
        engine_select.write(I_ROTATE);
107
        operand1.write(toint(x));       // orgX
108
        operand2.write(toint(y));       // orgY
109
        operand3.write(toint(a));       // angle
110
        instructions_valid.write(true);
111
        wait();
112
 
113
        // pulse instructions valid
114
        instructions_valid.write(false);
115
        wait_until(compute_done.delayed()==true);
116
 
117
        // Read Computed Results
118
        computed_v1 = tofp(result1.read());
119
        computed_v2 = tofp(result2.read());
120
 
121
        // Check Result
122
        rad=(3.1415926*a)/180.0;
123
        correct_x=x*cos(rad)-y*sin(rad); /* Perform "perfect" rotation by  */
124
        correct_y=y*cos(rad)+x*sin(rad); /* using f.p. and transcendentals */
125
 
126
        if ((fabs(computed_v1-correct_x)>0.15) ||
127
            (fabs(computed_v2-correct_y)>0.15)) {
128
            cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
129
            cout << computed_v2 << " expected=" << correct_x << ",";
130
            cout << correct_y << endl;
131
            success = false;
132
        } else {
133
            cout << MODULE_NAME << "CORRECT" << endl;
134
        }
135
 
136
        wait();
137
 
138
    } // end Test Rotate Engine
139
 
140
    // Test MagPhase Engine
141
    for(i = 0; i < MAGPHASE_NUM_TEST; i++) {
142
        wait();
143
        x = 2.0*((rand()>>2)%100) - 100;
144
        y = 2.0*((rand()>>2)%100) - 100;
145
        cout << MODULE_NAME << "Mag and Phase(" << x << ", " << y << ") " << endl;
146
 
147
        // activate the rotate engine
148
        engine_select.write(I_MAGPHASE);
149
        operand1.write(toint(x));       // orgX
150
        operand2.write(toint(y));       // orgY
151
        instructions_valid.write(true);
152
        wait();
153
 
154
        // pulse instructions valid
155
        instructions_valid.write(false);
156
        wait_until(compute_done.delayed()==true);
157
 
158
        // Read Computed Results
159
        computed_v1 = tofp(result1.read());
160
        computed_v2 = tofp(result2.read());
161
 
162
        // Check Result
163
        correct_x=sqrt(x*x+y*y); /* Perform "perfect" magnitude */
164
        correct_y=atan(y/x)*180/3.1415926;
165
 
166
        if (x<0 && y>0)
167
           correct_y = 180 + correct_y;
168
        if (x<0 && y<=0)
169
           correct_y = -180 + correct_y;
170
 
171
        if ((fabs(computed_v1-correct_x)>0.15) ||
172
            (fabs(computed_v2-correct_y)>0.15)) {
173
            cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
174
            cout << computed_v2 << " expected=" << correct_x << ",";
175
            cout << correct_y << endl;
176
            success = false;
177
        } else {
178
            cout << MODULE_NAME << "CORRECT" << endl;
179
        }
180
 
181
        wait();
182
 
183
    } // end Test Magnitude and Phase Engine
184
 
185
    // Test Sine Cosine Engine
186
    for(i = 0; i < SINCOS_NUM_TEST; i++) {
187
        wait();
188
        a = 1.0*((rand()>>2)%360)-180.0;
189
        cout << MODULE_NAME << "Sine and Cosine(" << a << ") " << endl;
190
 
191
        // activate the rotate engine
192
        engine_select.write(I_SINCOS);
193
        operand1.write(toint(a));       // orgX
194
        instructions_valid.write(true);
195
        wait();
196
 
197
        // pulse instructions valid
198
        instructions_valid.write(false);
199
        wait_until(compute_done.delayed()==true);
200
 
201
        // Read Computed Results
202
        computed_v1 = tofp(result1.read());
203
        computed_v2 = tofp(result2.read());
204
 
205
        // Check Result
206
        rad=(3.1415926*a)/180.0;
207
        correct_x=sin(rad); /* Perform "perfect" Cosine */
208
        correct_y=cos(rad);
209
        if ((fabs(computed_v1-correct_x)>0.06) ||
210
            (fabs(computed_v2-correct_y)>0.06)) {
211
            cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
212
            cout << computed_v2 << " expected=" << correct_x << ",";
213
            cout << correct_y << endl;
214
            success = false;
215
        } else {
216
            cout << MODULE_NAME << "CORRECT" << endl;
217
        }
218
 
219
        wait();
220
 
221
    } // end Test Sine and Cosine Engine
222
 
223
    // Test Sinh Cosh Engine
224
    for(i = 0; i < SINHCOSH_NUM_TEST; i++) {
225
        wait();
226
        a = 1.0*((rand()>>2)%90)-45.0;
227
        if(a < 0 && a > -3) a = -3;       // adjust for algorithm inaccuracies
228
        cout << MODULE_NAME << "Sinh and Cosh(" << a << ") " << endl;
229
        // activate the rotate engine
230
        engine_select.write(I_SINHCOSH);
231
        operand1.write(toint(a));       // orgX
232
        instructions_valid.write(true);
233
        wait();
234
 
235
        // pulse instructions valid
236
        instructions_valid.write(false);
237
        wait_until(compute_done.delayed()==true);
238
 
239
        // Read Computed Results
240
        computed_v1 = tofp(result1.read());
241
        computed_v2 = tofp(result2.read());
242
 
243
        // Check Result
244
        rad=(3.1415926*a)/180.0;
245
        correct_x=sinh(rad); /* Perform "perfect" Cosine */
246
        correct_y=cosh(rad);
247
 
248
        if ((fabs(computed_v1-correct_x)>0.06) ||
249
            (fabs(computed_v2-correct_y)>0.06)) {
250
            cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
251
            cout << computed_v2 << " expected=" << correct_x << ",";
252
            cout << correct_y << endl;
253
            success = false;
254
        } else {
255
            cout << MODULE_NAME << "CORRECT" << endl;
256
        }
257
 
258
        wait();
259
 
260
    } // end Test Sinh and Cosh Engine
261
 
262
    // Testing Pipeline
263
    wait();
264
    cout << MODULE_NAME << "Testing Pipeline Mode" << endl;
265
    start_monitor.write(true);
266
    wait();
267
 
268
    // Translates user program
269
    i = 0;
270
 
271
    while(i < MAX_PROGSIZE) {
272
      wait();
273
 
274
      retval = fscanf(infile, "%s", ir);
275
      if(retval==EOF) break;
276
      if(!strcmp(ir, "rot")) {
277
          // Rotate type functions
278
          printf("%s Opcode ROTATE[%s]: ", MODULE_NAME, ir);
279
          // get operands
280
          if((retval=fscanf(infile, "%s %s %s\n", op[0], op[1], op[2]))!= 3) {
281
            printf("Parse Error\n");
282
            break;
283
          } else {
284
            printf("[%s], [%s], [%s]\n", op[0], op[1], op[2]);
285
 
286
            engine_select.write(I_ROTATE);
287
            operand1.write(toint(atof(op[0])));
288
            operand2.write(toint(atof(op[1])));
289
            operand3.write(toint(atof(op[2])));
290
            instructions_valid.write(true);
291
          }
292
      } else if(!strcmp(ir, MAG_OPNAME)){
293
          // Magnitude-Phase type functions
294
          printf("%s Opcode MAG-PHASE[%s]: ", MODULE_NAME, ir);
295
          // get operands
296
          if((retval=fscanf(infile, "%s %s\n", op[0], op[1]))!= 2) {
297
            printf("Parse Error\n");
298
            break;
299
          } else {
300
            printf("%s, %s\n", op[0], op[1]);
301
            engine_select.write(I_MAGPHASE);
302
            operand1.write(toint(atof(op[0])));
303
            operand2.write(toint(atof(op[1])));
304
            instructions_valid.write(true);
305
          }
306
      } else if(!strcmp(ir, SIN_OPNAME) || !strcmp(ir, COS_OPNAME)) {
307
          // Trig type functions
308
          printf("%s Opcode SIN-COS[%s]: ", MODULE_NAME, ir);
309
          // get operands
310
          if((retval=fscanf(infile, "%s\n", op[0]))!= 1) {
311
            printf("Parse Error\n");
312
            break;
313
          } else {
314
            printf("%s\n", op[0]);
315
            engine_select.write(I_SINCOS);
316
            operand1.write(toint(atof(op[0])));
317
            instructions_valid.write(true);
318
          }
319
      } else if(!strcmp(ir, SINH_OPNAME) || !strcmp(ir, COSH_OPNAME)) {
320
          // Trig Hyperbolic type functions
321
          printf("%s Opcode SINH-COSH[%s]: ", MODULE_NAME, ir);
322
          // get operands
323
          if((retval=fscanf(infile, "%s\n", op[0]))!= 1) {
324
            printf("Parse Error\n");
325
            break;
326
          } else {
327
            printf("%s\n", op[0]);
328
            engine_select.write(I_SINHCOSH);
329
            operand1.write(toint(atof(op[0])));
330
            instructions_valid.write(true);
331
          }
332
      } else if (!strcmp(ir, NOP_OPNAME)) {
333
          // NOP function
334
          printf("%s Opcode NOP[%s]\n", MODULE_NAME, ir);
335
          engine_select.write(I_NOP);
336
          instructions_valid.write(true);
337
      } else {
338
          printf("Unknown Opcode %s\n", ir);
339
          engine_select.write(I_NOP);
340
          instructions_valid.write(false);
341
          break;
342
      }
343
      i++;
344
    }
345
 
346
    if(i == MAX_PROGSIZE) wait();
347
 
348
    instructions_valid.write(false);
349
    fclose(infile);
350
    cout << MODULE_NAME << "Interpreted " << i << " instructions\n";
351
    num_instr = i;
352
 
353
    wait_until(monitor_idle.delayed()==true);
354
    start_monitor.write(false);
355
    wait();
356
 
357
    // Check results
358
    cout << MODULE_NAME << "Checking Pipeline Mode results" << endl;
359
    infile = fopen(PROGFILE, "r");
360
    logfile = fopen(LOGFILE, "r");
361
    if(!infile) {
362
        cout << MODULE_NAME << "Prog file cannot be opened: " << PROGFILE << endl;
363
        exit(-1);
364
    }
365
    if(!logfile) {
366
        cout << MODULE_NAME << "Log file cannot be opened: " << LOGFILE << endl;
367
        exit(-1);
368
    }
369
 
370
    i = 0;
371
    skip = false;
372
 
373
    while(i < MAX_PROGSIZE) {
374
      wait();
375
 
376
      retval = fscanf(infile, "%s", ir);
377
      if(retval==EOF) break;
378
      if(skip==false) {
379
          retval = fscanf(logfile, "%d %x %x\n", &file_opcode, &fixed1, &fixed2);
380
          if(retval!=3) {
381
              cout << MODULE_NAME << "ERROR mismatch num_arg in " << LOGFILE << " found " << retval << endl;
382
              break;
383
          }
384
          computed_v1 = tofp((short)fixed1);
385
          computed_v2 = tofp((short)fixed2);
386
      }
387
      skip = false;
388
      if(!strcmp(ir, "rot")) {
389
          // Rotate type functions
390
          printf("%s Opcode ROTATE[%s]: ", MODULE_NAME, ir);
391
          // get operands
392
          if((retval=fscanf(infile, "%s %s %s\n", op[0], op[1], op[2]))!= 3) {
393
            printf("Parse Error\n");
394
            break;
395
          } else {
396
            printf("[%s], [%s], [%s]\n", op[0], op[1], op[2]);
397
            // Check
398
            rad=(3.1415926*atof(op[2]))/180.0;
399
            correct_x=atof(op[0])*cos(rad)-atof(op[1])*sin(rad);
400
            correct_y=atof(op[1])*cos(rad)+atof(op[0])*sin(rad);
401
 
402
            if ((fabs(computed_v1-correct_x)>0.15) ||
403
                (fabs(computed_v2-correct_y)>0.15)) {
404
                cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
405
                cout << computed_v2 << " expected=" << correct_x << ",";
406
                cout << correct_y << endl;
407
                success = false;
408
            } else {
409
                cout << MODULE_NAME << "CORRECT" << endl;
410
            }
411
          }
412
      } else if(!strcmp(ir, MAG_OPNAME)){
413
          // Magnitude-Phase type functions
414
          printf("%s Opcode MAG-PHASE[%s]: ", MODULE_NAME, ir);
415
          // get operands
416
          if((retval=fscanf(infile, "%s %s\n", op[0], op[1]))!= 2) {
417
            printf("Parse Error\n");
418
            break;
419
          } else {
420
            printf("%s, %s\n", op[0], op[1]);
421
            // Check
422
            x = atof(op[0]);
423
            y = atof(op[1]);
424
            correct_x=sqrt(x*x+y*y);
425
            correct_y=atan(y/x)*180/3.1415926;
426
 
427
            if (x<0 && y>0)
428
                correct_y = 180 + correct_y;
429
            if (x<0 && y<=0)
430
                correct_y = -180 + correct_y;
431
 
432
            if ((fabs(computed_v1-correct_x)>0.15) ||
433
                (fabs(computed_v2-correct_y)>0.15)) {
434
                cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
435
                cout << computed_v2 << " expected=" << correct_x << ",";
436
                cout << correct_y << endl;
437
                success = false;
438
            } else {
439
                cout << MODULE_NAME << "CORRECT" << endl;
440
            }
441
          }
442
      } else if(!strcmp(ir, SIN_OPNAME) || !strcmp(ir, COS_OPNAME)) {
443
          // Trig type functions
444
          printf("%s Opcode SIN-COS[%s]: ", MODULE_NAME, ir);
445
          // get operands
446
          if((retval=fscanf(infile, "%s\n", op[0]))!= 1) {
447
            printf("Parse Error\n");
448
            break;
449
          } else {
450
            printf("%s\n", op[0]);
451
            // Check
452
            rad=(3.1415926*atof(op[0]))/180.0;
453
            correct_x=sin(rad); /* Perform "perfect" Cosine */
454
            correct_y=cos(rad);
455
            if ((fabs(computed_v1-correct_x)>0.06) ||
456
                (fabs(computed_v2-correct_y)>0.06)) {
457
                cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
458
                cout << computed_v2 << " expected=" << correct_x << ",";
459
                cout << correct_y << endl;
460
                success = false;
461
            } else {
462
                cout << MODULE_NAME << "CORRECT" << endl;
463
            }
464
          }
465
      } else if(!strcmp(ir, SINH_OPNAME) || !strcmp(ir, COSH_OPNAME)) {
466
          // Trig Hyperbolic type functions
467
          printf("%s Opcode SINH-COSH[%s]: ", MODULE_NAME, ir);
468
          // get operands
469
          if((retval=fscanf(infile, "%s\n", op[0]))!= 1) {
470
              printf("Parse Error\n");
471
              break;
472
          } else {
473
             printf("%s\n", op[0]);
474
             // Check
475
             rad=(3.1415926*atof(op[0]))/180.0;
476
             correct_x=sinh(rad); /* Perform "perfect" Cosine */
477
             correct_y=cosh(rad);
478
 
479
             if ((fabs(computed_v1-correct_x)>0.06) ||
480
                (fabs(computed_v2-correct_y)>0.06)) {
481
                 cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
482
                 cout << computed_v2 << " expected=" << correct_x << ",";
483
                 cout << correct_y << endl;
484
                 success = false;
485
             } else {
486
                 cout << MODULE_NAME << "CORRECT" << endl;
487
             }
488
          }
489
      } else if (!strcmp(ir, NOP_OPNAME)) {
490
          // NOP function
491
          printf("%s Opcode NOP[%s]\n", MODULE_NAME, ir);
492
          skip = true;
493
      } else {
494
          printf("Unknown Opcode %s\n", ir);
495
          break;
496
      }
497
      i++;
498
    }
499
    if(i != num_instr) {
500
        cout << MODULE_NAME << "ERROR num of instruction mismatched " ;
501
        cout << i << " vs " << num_instr << endl;
502
        success = false;
503
    } else {
504
        cout << MODULE_NAME << "Pipeline processed " << i << " instructions" <
505
    }
506
    fclose(infile);
507
    fclose(logfile);
508
 
509
    cout << MODULE_NAME << "Testbench completed - ";
510
    if(success) {
511
        cout << "SUCCESS" << endl;
512
    } else {
513
        cout << "FAILED" << endl;
514
    }
515
    done.write(true);
516
    // end of test vectors
517
}

powered by: WebSVN 2.1.0

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