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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [sw/] [tests/] [or1200/] [board/] [or1200-div.c] - Blame information for rev 439

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 439 julius
/*
2
   Test integer division
3
 
4
   Use a software division algorithm to perform division and compare against
5
   the hardware calculated results
6
 
7
   TODO: Check the signed division software calculation stuff is 100% correct!
8
 
9
   Julius Baxter, julius@opencores.org
10
 
11
*/
12
 
13
#include "cpu-utils.h"
14
#include "uart.h"
15
#include "printf.h"
16
#include "board.h"
17
 
18
static int sdiv_errors, udiv_errors;
19
 
20
#define VERBOSE_TESTS 0
21
 
22
// Make this bigger when running on FPGA target. For simulation it's enough.
23
#define NUM_TESTS 2000000
24
 
25
int
26
or1k_div(int dividend, int divisor)
27
{
28
  int result;
29
  asm ("l.div\t%0,%1,%2" : "=r" (result) : "r" (dividend), "r" (divisor));
30
  return result;
31
}
32
 
33
unsigned int
34
or1k_divu(unsigned int dividend, unsigned int divisor)
35
{
36
  int result;
37
  asm ("l.divu\t%0,%1,%2" : "=r" (result) : "r" (dividend), "r" (divisor));
38
  return result;
39
}
40
 
41
 
42
void
43
check_div(int dividend, int divisor, int expected_result)
44
{
45
#if VERBOSE_TESTS
46
  printf("l.div  0x%.8x / 0x%.8x = (SW) 0x%.8x : ", dividend, divisor,
47
         expected_result);
48
#endif
49
  int result =  or1k_div(dividend, divisor);
50
  report(result);
51
  if ( result != expected_result)
52
    {
53
      printf("l.div 0x%.8x / 0x%.8x = (SW) 0x%.8x : ", dividend, divisor,
54
             expected_result);
55
 
56
      printf("(HW) 0x%.8x - MISMATCH\n",result);
57
      sdiv_errors++;
58
    }
59
#if VERBOSE_TESTS
60
  else
61
    printf("OK\n");
62
#endif
63
 
64
}
65
 
66
void
67
check_divu(unsigned int dividend, unsigned int divisor,
68
           unsigned int expected_result)
69
{
70
#if VERBOSE_TESTS
71
  printf("l.divu 0x%.8x / 0x%.8x = (SW) 0x%.8x : ", dividend, divisor,
72
         expected_result);
73
#endif
74
 
75
  unsigned int result =  or1k_divu(dividend, divisor);
76
  report(result);
77
  if ( result != expected_result)
78
    {
79
      printf("l.divu 0x%.8x / 0x%.8x = (SW) 0x%.8x : ", dividend, divisor,
80
             expected_result);
81
 
82
      printf("(HW) 0x%.8x - MISMATCH\n",result);
83
      udiv_errors++;
84
    }
85
#if VERBOSE_TESTS
86
  else
87
    printf("OK\n");
88
#endif
89
}
90
 
91
 
92
// Software implementation of division
93
unsigned int
94
div_soft(unsigned int n, unsigned int d)
95
{
96
 
97
  // unsigned 32-bit restoring divide algo:
98
  unsigned long long p, dd;
99
  long long p_signed;
100
  unsigned int q = 0;
101
 
102
  p = (unsigned long long) n;
103
  dd = (unsigned long long) d << 32;
104
 
105
  int i;
106
  for(i=31; i>-1; i--){
107
    p_signed = (2*p) - dd;
108
    if (p_signed>=0)
109
      {
110
        p = (2*p) - dd;
111
        q |= 1 << i;
112
      }
113
    else
114
      {
115
        p = p_signed + dd;
116
      }
117
  }
118
 
119
  return q;
120
 
121
}
122
 
123
int
124
main(void)
125
{
126
#ifdef _UART_H_
127
  uart_init(DEFAULT_UART);
128
#endif
129
 
130
  unsigned int seconds = 0;
131
  cpu_reset_timer_ticks();
132
  cpu_enable_timer();
133
 
134
  printf("\n\n\tOR1200 Division Instruction Tests\n");
135
  printf("\tRunning %d tests\n", NUM_TESTS);
136
#if VERBOSE_TESTS==0
137
  printf("\tElapsed time: 000");
138
#endif
139
 
140
  udiv_errors = 0;
141
  sdiv_errors = 0;
142
 
143
  int i;
144
 
145
  unsigned long n, d;
146
  unsigned long expected_result;
147
  i=0;
148
  while(i < NUM_TESTS)
149
    {
150
      n = rand();
151
      d = rand();
152
 
153
      report(0x10101010);
154
 
155
      while ( d >= n )
156
        d >>= (rand() & 0xff);
157
 
158
      if (n&0x80000000) // numerator is negative
159
        {
160
          // Calculate a value that's really smaller than the numerator
161
          while ( d >= ~(n-1) )
162
            d >>= (rand() & 0xff);
163
 
164
          if (!d) d = 1;
165
          // Processor thinks it's in 2's complement already, so we'll convert
166
          // from the interpreted 2's complement to unsigned for our calculation
167
          expected_result = div_soft(~(n-1), d);
168
          // Answer will be an unsigned +ve value, but of course it has to be
169
          // negative so convert back to 2's complment negative
170
          expected_result = ~expected_result + 1; // 2's complement
171
        }
172
      else
173
        expected_result = div_soft(n, d);
174
 
175
      /* Report things */
176
      report(n);
177
      report(d);
178
      report(expected_result);
179
 
180
      /* Signed divide */
181
      check_div(n, d, expected_result);
182
 
183
 
184
      /* Unsigned divide test */
185
      /* Ensure numerator's bit 31 is clear */
186
      n >>= 1;
187
 
188
      /* If divisor is > numerator, shift it by a random amount */
189
      while ( d >= n )
190
        d >>= (rand() & 0xff);
191
      if (!d) d = 1;
192
 
193
      expected_result = div_soft(n, d);
194
 
195
      /* Report things */
196
      report(n);
197
      report(d);
198
      report(expected_result);
199
 
200
      /* Unsigned divide */
201
      check_divu(n, d, expected_result);
202
 
203
      i++;
204
#if VERBOSE_TESTS==0
205
      if (cpu_get_timer_ticks() >= TICKS_PER_SEC)
206
        {
207
          cpu_reset_timer_ticks();
208
          seconds++;
209
          printf("\b\b\b%.3d",seconds);
210
        }
211
#endif
212
    }
213
 
214
  printf("\n");
215
 
216
  printf("Division check complete\n");
217
  printf("Unsigned:\t%d tests\t %d errors\n",
218
         NUM_TESTS, udiv_errors);
219
  printf("Signed:\t\t%d tests\t %d errors\n",
220
         NUM_TESTS, sdiv_errors);
221
 
222
  if ((udiv_errors > 0) || (sdiv_errors > 0))
223
    report(0xbaaaaaad);
224
  else
225
    report(0x8000000d);
226
 
227
  return 0;
228
 
229
}

powered by: WebSVN 2.1.0

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