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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [example/] [floating_point_test/] [main.c] - Blame information for rev 55

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

Line No. Rev Author Line
1 55 zero_gravi
// #################################################################################################
2
// # << NEORV32 - RISC-V Single-Precision Floating-Point 'Zfinx' Extension Verification Program >> #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6
// # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
7
// #                                                                                               #
8
// # Redistribution and use in source and binary forms, with or without modification, are          #
9
// # permitted provided that the following conditions are met:                                     #
10
// #                                                                                               #
11
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
// #    conditions and the following disclaimer.                                                   #
13
// #                                                                                               #
14
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
// #    conditions and the following disclaimer in the documentation and/or other materials        #
16
// #    provided with the distribution.                                                            #
17
// #                                                                                               #
18
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
// #    endorse or promote products derived from this software without specific prior written      #
20
// #    permission.                                                                                #
21
// #                                                                                               #
22
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
// # ********************************************************************************************* #
32
// # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
33
// #################################################################################################
34
 
35
 
36
/**********************************************************************//**
37
 * @file floating_point_test/main.c
38
 * @author Stephan Nolting
39
 * @brief Verification program for the NEORV32 'Zfinx' extension (floating-point in x registers) using pseudo-random data as input; compares results from hardware against pure-sw reference functions.
40
 **************************************************************************/
41
 
42
#include <neorv32.h>
43
#include <float.h>
44
#include <math.h>
45
#include "neorv32_zfinx_extension_intrinsics.h"
46
 
47
#ifdef NAN
48
/* NAN is supported */
49
#else
50
#warning NAN macro not supported!
51
#endif
52
#ifdef INFINITY
53
/* INFINITY is supported */
54
#else
55
#warning INFINITY macro not supported!
56
#endif
57
 
58
 
59
/**********************************************************************//**
60
 * @name User configuration
61
 **************************************************************************/
62
/**@{*/
63
/** UART BAUD rate */
64
#define BAUD_RATE          (19200)
65
//** Number of test cases for each instruction */
66
#define NUM_TEST_CASES     (1000000)
67
//** Silent mode (only show actual errors when != 0) */
68
#define SILENT_MODE        (1)
69
//** Run conversion tests when != 0 */
70
#define RUN_CONV_TESTS     (1)
71
//** Run add/sub tests when != 0 */
72
#define RUN_ADDSUB_TESTS   (1)
73
//** Run multiplication tests when != 0 */
74
#define RUN_MUL_TESTS      (1)
75
//** Run min/max tests when != 0 */
76
#define RUN_MINMAX_TESTS   (1)
77
//** Run comparison tests when != 0 */
78
#define RUN_COMPARE_TESTS  (1)
79
//** Run sign-injection tests when != 0 */
80
#define RUN_SGNINJ_TESTS   (1)
81
//** Run classify tests when != 0 */
82
#define RUN_CLASSIFY_TESTS (1)
83
//** Run unsupported instructions tests when != 0 */
84
#define RUN_UNAVAIL_TESTS  (1)
85
/**@}*/
86
 
87
 
88
// Prototypes
89
uint32_t get_test_vector(void);
90
uint32_t xorshift32(void);
91
uint32_t verify_result(uint32_t num, uint32_t opa, uint32_t opb, uint32_t ref, uint32_t res);
92
void print_report(uint32_t num_err);
93
 
94
 
95
/**********************************************************************//**
96
 * Main function; test all available operations of the NEORV32 'Zfinx' extensions using bit floating-point hardware intrinsics and software-only reference functions (emulation).
97
 *
98
 * @note This program requires the Zfinx CPU extension.
99
 *
100
 * @return Irrelevant.
101
 **************************************************************************/
102
int main() {
103
 
104
  uint32_t err_cnt = 0;
105
  uint32_t err_cnt_total = 0;
106
  uint32_t test_cnt = 0;
107
  uint32_t i = 0;
108
  float_conv_t opa;
109
  float_conv_t opb;
110
  float_conv_t res_hw;
111
  float_conv_t res_sw;
112
 
113
 
114
  // init primary UART
115
  neorv32_uart_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
116
 
117
  // capture all exceptions and give debug info via UART
118
  neorv32_rte_setup();
119
 
120
  // check available hardware extensions and compare with compiler flags
121
  neorv32_rte_check_isa(0); // silent = 0 -> show message if isa mismatch
122
 
123
  // check if Zfinx extension is implemented at all
124
  if (neorv32_check_zextension(CSR_MZEXT_ZFINX) == 0) {
125
    neorv32_uart_print("Error! <Zfinx> extension not synthesized!\n");
126
    return 0;
127
  }
128
 
129
 
130
// Disable compilation by default
131
#ifndef RUN_TEST
132
  #warning Program HAS NOT BEEN COMPILED! Use >>make USER_FLAGS+=-DRUN_TEST clean_all exe<< to compile it.
133
 
134
  // inform the user if you are actually executing this
135
  neorv32_uart_printf("ERROR! Program has not been compiled. Use >>make USER_FLAGS+=-DRUN_TEST clean_all exe<< to compile it.\n");
136
 
137
  return 0;
138
#endif
139
 
140
 
141
  // intro
142
  neorv32_uart_printf("<<< Zfinx extension test >>>\n");
143
#if (SILENT_MODE != 0)
144
  neorv32_uart_printf("SILENT_MODE enabled (only showing actual errors)\n");
145
#endif
146
  neorv32_uart_printf("Test cases per instruction: %u\n\n", (uint32_t)NUM_TEST_CASES);
147
 
148
 
149
  // clear exception status word
150
  neorv32_cpu_csr_write(CSR_FFLAGS, 0);; // real hardware
151
  feclearexcept(FE_ALL_EXCEPT); // software runtime (GCC floating-point emulation)
152
 
153
 
154
// ----------------------------------------------------------------------------
155
// Conversion Tests
156
// ----------------------------------------------------------------------------
157
 
158
#if (RUN_CONV_TESTS != 0)
159
  neorv32_uart_printf("\n#%u: FCVT.S.WU (unsigned integer to float)...\n", test_cnt);
160
  err_cnt = 0;
161
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
162
    opa.binary_value = get_test_vector();
163
    res_hw.float_value = riscv_intrinsic_fcvt_swu(opa.binary_value);
164
    res_sw.float_value = riscv_emulate_fcvt_swu(opa.binary_value);
165
    err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
166
  }
167
  print_report(err_cnt);
168
  err_cnt_total += err_cnt;
169
  test_cnt++;
170
 
171
  neorv32_uart_printf("\n#%u: FCVT.S.W (signed integer to float)...\n", test_cnt);
172
  err_cnt = 0;
173
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
174
    opa.binary_value = get_test_vector();
175
    res_hw.float_value = riscv_intrinsic_fcvt_sw((int32_t)opa.binary_value);
176
    res_sw.float_value = riscv_emulate_fcvt_sw((int32_t)opa.binary_value);
177
    err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
178
  }
179
  print_report(err_cnt);
180
  err_cnt_total += err_cnt;
181
  test_cnt++;
182
 
183
  neorv32_uart_printf("\n#%u: FCVT.WU.S (float to unsigned integer)...\n", test_cnt);
184
  err_cnt = 0;
185
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
186
    opa.binary_value = get_test_vector();
187
    res_hw.binary_value = riscv_intrinsic_fcvt_wus(opa.float_value);
188
    res_sw.binary_value = riscv_emulate_fcvt_wus(opa.float_value);
189
    err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
190
  }
191
  print_report(err_cnt);
192
  err_cnt_total += err_cnt;
193
  test_cnt++;
194
 
195
  neorv32_uart_printf("\n#%u: FCVT.W.S (float to signed integer)...\n", test_cnt);
196
  err_cnt = 0;
197
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
198
    opa.binary_value = get_test_vector();
199
    res_hw.binary_value = (uint32_t)riscv_intrinsic_fcvt_ws(opa.float_value);
200
    res_sw.binary_value = (uint32_t)riscv_emulate_fcvt_ws(opa.float_value);
201
    err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
202
  }
203
  print_report(err_cnt);
204
  err_cnt_total += err_cnt;
205
  test_cnt++;
206
#endif
207
 
208
 
209
// ----------------------------------------------------------------------------
210
// Add/Sub Tests
211
// ----------------------------------------------------------------------------
212
 
213
#if (RUN_ADDSUB_TESTS != 0)
214
  neorv32_uart_printf("\n#%u: FADD.S (addition)...\n", test_cnt);
215
  err_cnt = 0;
216
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
217
    opa.binary_value = get_test_vector();
218
    opb.binary_value = get_test_vector();
219
    res_hw.float_value = riscv_intrinsic_fadds(opa.float_value, opb.float_value);
220
    res_sw.float_value = riscv_emulate_fadds(opa.float_value, opb.float_value);
221
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
222
  }
223
  print_report(err_cnt);
224
  err_cnt_total += err_cnt;
225
  test_cnt++;
226
 
227
  neorv32_uart_printf("\n#%u: FSUB.S (subtraction)...\n", test_cnt);
228
  err_cnt = 0;
229
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
230
    opa.binary_value = get_test_vector();
231
    opb.binary_value = get_test_vector();
232
    res_hw.float_value = riscv_intrinsic_fsubs(opa.float_value, opb.float_value);
233
    res_sw.float_value = riscv_emulate_fsubs(opa.float_value, opb.float_value);
234
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
235
  }
236
  print_report(err_cnt);
237
  err_cnt_total += err_cnt;
238
  test_cnt++;
239
#endif
240
 
241
 
242
// ----------------------------------------------------------------------------
243
// Multiplication Tests
244
// ----------------------------------------------------------------------------
245
 
246
#if (RUN_MUL_TESTS != 0)
247
  neorv32_uart_printf("\n#%u: FMUL.S (multiplication)...\n", test_cnt);
248
  err_cnt = 0;
249
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
250
    opa.binary_value = get_test_vector();
251
    opb.binary_value = get_test_vector();
252
    res_hw.float_value = riscv_intrinsic_fmuls(opa.float_value, opb.float_value);
253
    res_sw.float_value = riscv_emulate_fmuls(opa.float_value, opb.float_value);
254
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
255
  }
256
  print_report(err_cnt);
257
  err_cnt_total += err_cnt;
258
  test_cnt++;
259
#endif
260
 
261
 
262
// ----------------------------------------------------------------------------
263
// Min/Max Tests
264
// ----------------------------------------------------------------------------
265
 
266
#if (RUN_MINMAX_TESTS != 0)
267
  neorv32_uart_printf("\n#%u: FMIN.S (select minimum)...\n", test_cnt);
268
  err_cnt = 0;
269
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
270
    opa.binary_value = get_test_vector();
271
    opb.binary_value = get_test_vector();
272
    res_hw.float_value = riscv_intrinsic_fmins(opa.float_value, opb.float_value);
273
    res_sw.float_value = riscv_emulate_fmins(opa.float_value, opb.float_value);
274
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
275
  }
276
  print_report(err_cnt);
277
  err_cnt_total += err_cnt;
278
  test_cnt++;
279
 
280
  neorv32_uart_printf("\n#%u: FMAX.S (select maximum)...\n", test_cnt);
281
  err_cnt = 0;
282
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
283
    opa.binary_value = get_test_vector();
284
    opb.binary_value = get_test_vector();
285
    res_hw.float_value = riscv_intrinsic_fmaxs(opa.float_value, opb.float_value);
286
    res_sw.float_value = riscv_emulate_fmaxs(opa.float_value, opb.float_value);
287
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
288
  }
289
  print_report(err_cnt);
290
  err_cnt_total += err_cnt;
291
  test_cnt++;
292
#endif
293
 
294
 
295
// ----------------------------------------------------------------------------
296
// Comparison Tests
297
// ----------------------------------------------------------------------------
298
 
299
#if (RUN_COMPARE_TESTS != 0)
300
  neorv32_uart_printf("\n#%u: FEQ.S (compare if equal)...\n", test_cnt);
301
  err_cnt = 0;
302
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
303
    opa.binary_value = get_test_vector();
304
    opb.binary_value = get_test_vector();
305
    res_hw.binary_value = riscv_intrinsic_feqs(opa.float_value, opb.float_value);
306
    res_sw.binary_value = riscv_emulate_feqs(opa.float_value, opb.float_value);
307
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
308
  }
309
  print_report(err_cnt);
310
  err_cnt_total += err_cnt;
311
  test_cnt++;
312
 
313
  neorv32_uart_printf("\n#%u: FLT.S (compare if less-than)...\n", test_cnt);
314
  err_cnt = 0;
315
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
316
    opa.binary_value = get_test_vector();
317
    opb.binary_value = get_test_vector();
318
    res_hw.binary_value = riscv_intrinsic_flts(opa.float_value, opb.float_value);
319
    res_sw.binary_value = riscv_emulate_flts(opa.float_value, opb.float_value);
320
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
321
  }
322
  print_report(err_cnt);
323
  err_cnt_total += err_cnt;
324
  test_cnt++;
325
 
326
  neorv32_uart_printf("\n#%u: FLE.S (compare if less-than-or-equal)...\n", test_cnt);
327
  err_cnt = 0;
328
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
329
    opa.binary_value = get_test_vector();
330
    opb.binary_value = get_test_vector();
331
    res_hw.binary_value = riscv_intrinsic_fles(opa.float_value, opb.float_value);
332
    res_sw.binary_value = riscv_emulate_fles(opa.float_value, opb.float_value);
333
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
334
  }
335
  print_report(err_cnt);
336
  err_cnt_total += err_cnt;
337
  test_cnt++;
338
#endif
339
 
340
 
341
// ----------------------------------------------------------------------------
342
// Sign-Injection Tests
343
// ----------------------------------------------------------------------------
344
 
345
#if (RUN_SGNINJ_TESTS != 0)
346
  neorv32_uart_printf("\n#%u: FSGNJ.S (sign-injection)...\n", test_cnt);
347
  err_cnt = 0;
348
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
349
    opa.binary_value = get_test_vector();
350
    opb.binary_value = get_test_vector();
351
    res_hw.float_value = riscv_intrinsic_fsgnjs(opa.float_value, opb.float_value);
352
    res_sw.float_value = riscv_emulate_fsgnjs(opa.float_value, opb.float_value);
353
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
354
  }
355
  print_report(err_cnt);
356
  err_cnt_total += err_cnt;
357
  test_cnt++;
358
 
359
  neorv32_uart_printf("\n#%u: FSGNJN.S (sign-injection NOT)...\n", test_cnt);
360
  err_cnt = 0;
361
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
362
    opa.binary_value = get_test_vector();
363
    opb.binary_value = get_test_vector();
364
    res_hw.float_value = riscv_intrinsic_fsgnjns(opa.float_value, opb.float_value);
365
    res_sw.float_value = riscv_emulate_fsgnjns(opa.float_value, opb.float_value);
366
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
367
  }
368
  print_report(err_cnt);
369
  err_cnt_total += err_cnt;
370
  test_cnt++;
371
 
372
  neorv32_uart_printf("\n#%u: FSGNJX.S (sign-injection XOR)...\n", test_cnt);
373
  err_cnt = 0;
374
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
375
    opa.binary_value = get_test_vector();
376
    opb.binary_value = get_test_vector();
377
    res_hw.float_value = riscv_intrinsic_fsgnjxs(opa.float_value, opb.float_value);
378
    res_sw.float_value = riscv_emulate_fsgnjxs(opa.float_value, opb.float_value);
379
    err_cnt += verify_result(i, opa.binary_value, opb.binary_value, res_sw.binary_value, res_hw.binary_value);
380
  }
381
  print_report(err_cnt);
382
  err_cnt_total += err_cnt;
383
  test_cnt++;
384
#endif
385
 
386
 
387
// ----------------------------------------------------------------------------
388
// Classify Tests
389
// ----------------------------------------------------------------------------
390
 
391
#if (RUN_CLASSIFY_TESTS != 0)
392
  neorv32_uart_printf("\n#%u: FCLASS.S (classify)...\n", test_cnt);
393
  err_cnt = 0;
394
  for (i=0;i<(uint32_t)NUM_TEST_CASES; i++) {
395
    opa.binary_value = get_test_vector();
396
    res_hw.binary_value = riscv_intrinsic_fclasss(opa.float_value);
397
    res_sw.binary_value = riscv_emulate_fclasss(opa.float_value);
398
    err_cnt += verify_result(i, opa.binary_value, 0, res_sw.binary_value, res_hw.binary_value);
399
  }
400
  print_report(err_cnt);
401
  err_cnt_total += err_cnt;
402
  test_cnt++;
403
#endif
404
 
405
 
406
// ----------------------------------------------------------------------------
407
// UNSUPPORTED Instructions Tests - Execution should raise illegal instruction exception
408
// ----------------------------------------------------------------------------
409
 
410
#if (RUN_UNAVAIL_TESTS != 0)
411
  neorv32_uart_printf("\n# unsupported FDIV.S (division) [illegal instruction]...\n");
412
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
413
  opa.binary_value = get_test_vector();
414
  opb.binary_value = get_test_vector();
415
  riscv_intrinsic_fdivs(opa.float_value, opb.float_value);
416
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
417
    neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
418
    err_cnt_total++;
419
  }
420
  else {
421
    neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
422
  }
423
 
424
  neorv32_uart_printf("\n# unsupported FSQRT.S (square root) [illegal instruction]...\n");
425
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
426
  opa.binary_value = get_test_vector();
427
  opb.binary_value = get_test_vector();
428
  riscv_intrinsic_fsqrts(opa.float_value);
429
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
430
    neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
431
    err_cnt_total++;
432
  }
433
  else {
434
    neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
435
  }
436
 
437
  neorv32_uart_printf("\n# unsupported FMADD.S (fused multiply-add) [illegal instruction]...\n");
438
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
439
  opa.binary_value = get_test_vector();
440
  opb.binary_value = get_test_vector();
441
  riscv_intrinsic_fmadds(opa.float_value, opb.float_value, -opa.float_value);
442
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
443
    neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
444
    err_cnt_total++;
445
  }
446
  else {
447
    neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
448
  }
449
 
450
  neorv32_uart_printf("\n# unsupported FMSUB.S (fused multiply-sub) [illegal instruction]...\n");
451
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
452
  opa.binary_value = get_test_vector();
453
  opb.binary_value = get_test_vector();
454
  riscv_intrinsic_fmsubs(opa.float_value, opb.float_value, -opa.float_value);
455
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
456
    neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
457
    err_cnt_total++;
458
  }
459
  else {
460
    neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
461
  }
462
 
463
  neorv32_uart_printf("\n# unsupported FNMSUB.S (fused negated multiply-sub) [illegal instruction]...\n");
464
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
465
  opa.binary_value = get_test_vector();
466
  opb.binary_value = get_test_vector();
467
  riscv_intrinsic_fnmadds(opa.float_value, opb.float_value, -opa.float_value);
468
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
469
    neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
470
    err_cnt_total++;
471
  }
472
  else {
473
    neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
474
  }
475
 
476
  neorv32_uart_printf("\n# unsupported FNMADD.S (fused negated multiply-add) [illegal instruction]...\n");
477
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
478
  opa.binary_value = get_test_vector();
479
  opb.binary_value = get_test_vector();
480
  riscv_intrinsic_fnmadds(opa.float_value, opb.float_value, -opa.float_value);
481
  if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
482
    neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
483
    err_cnt_total++;
484
  }
485
  else {
486
    neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
487
  }
488
#endif
489
 
490
 
491
  // final report
492
  if (err_cnt_total != 0) {
493
    neorv32_uart_printf("\n%c[1m[ZFINX EXTENSION VERIFICATION FAILED!]%c[0m\n", 27, 27);
494
    neorv32_uart_printf("%u errors in %u test cases\n", err_cnt_total, test_cnt*(uint32_t)NUM_TEST_CASES);
495
  }
496
  else {
497
    neorv32_uart_printf("\n%c[1m[Zfinx extension verification successful!]%c[0m\n", 27, 27);
498
  }
499
 
500
  return 0;
501
}
502
 
503
 
504
/**********************************************************************//**
505
 * Generate 32-bit test data (including special values like INFINITY every now and then).
506
 *
507
 * @return Test data (32-bit).
508
 **************************************************************************/
509
uint32_t get_test_vector(void) {
510
 
511
  float_conv_t tmp;
512
 
513
  // generate special value "every" ~256th time this function is called
514
  if ((xorshift32() & 0xff) == 0xff) {
515
 
516
    switch((xorshift32() >> 10) & 0x3) { // random decision which special value we are taking
517
      case  0: tmp.float_value  = +INFINITY; break;
518
      case  1: tmp.float_value  = -INFINITY; break;
519
      case  2: tmp.float_value  = +0.0f; break;
520
      case  3: tmp.float_value  = -0.0f; break;
521
      case  4: tmp.binary_value = 0x7fffffff; break;
522
      case  5: tmp.binary_value = 0xffffffff; break;
523
      case  6: tmp.float_value  = NAN; break;
524
      case  7: tmp.float_value  = NAN; break; // FIXME signaling_NAN?
525
      default: tmp.float_value  = NAN; break;
526
    }
527
  }
528
  else {
529
    tmp.binary_value = xorshift32();
530
  }
531
 
532
  // subnormal numbers are not supported yet!
533
  // flush them to zero
534
//tmp.float_value = subnormal_flush(tmp.float_value);
535
 
536
  return tmp.binary_value;
537
}
538
 
539
 
540
/**********************************************************************//**
541
 * PSEUDO-RANDOM number generator.
542
 *
543
 * @return Random data (32-bit).
544
 **************************************************************************/
545
uint32_t xorshift32(void) {
546
 
547
  static uint32_t x32 = 314159265;
548
 
549
  x32 ^= x32 << 13;
550
  x32 ^= x32 >> 17;
551
  x32 ^= x32 << 5;
552
 
553
  return x32;
554
}
555
 
556
 
557
/**********************************************************************//**
558
 * Verify results (software reference vs. actual hardware).
559
 *
560
 * @param[in] num Test case number
561
 * @param[in] opa Operand 1
562
 * @param[in] opb Operand 2
563
 * @param[in] ref Software reference
564
 * @param[in] res Actual results from hardware
565
 * @return zero if results are equal.
566
 **************************************************************************/
567
uint32_t verify_result(uint32_t num, uint32_t opa, uint32_t opb, uint32_t ref, uint32_t res) {
568
 
569
#if (SILENT_MODE == 0)
570
  neorv32_uart_printf("%u: opa = 0x%x, opb = 0x%x : ref[SW] = 0x%x vs. res[HW] = 0x%x ", num, opa, opb, ref, res);
571
#endif
572
 
573
  if (ref != res) {
574
#if (SILENT_MODE != 0)
575
    neorv32_uart_printf("%u: opa = 0x%x, opb = 0x%x : ref[SW] = 0x%x vs. res[HW] = 0x%x ", num, opa, opb, ref, res);
576
#endif
577
    neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
578
    return 1;
579
  }
580
  else {
581
#if (SILENT_MODE == 0)
582
    neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
583
#endif
584
    return 0;
585
  }
586
}
587
 
588
 
589
/**********************************************************************//**
590
 * Print test report.
591
 *
592
 * @param[in] num_err Number or errors in this test.
593
 **************************************************************************/
594
void print_report(uint32_t num_err) {
595
 
596
  neorv32_uart_printf("Errors: %u/%u ", num_err, (uint32_t)NUM_TEST_CASES);
597
 
598
  if (num_err == 0) {
599
    neorv32_uart_printf("%c[1m[ok]%c[0m\n", 27, 27);
600
  }
601
  else {
602
    neorv32_uart_printf("%c[1m[FAILED]%c[0m\n", 27, 27);
603
  }
604
}

powered by: WebSVN 2.1.0

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