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

Subversion Repositories openrisc_me

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

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

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

powered by: WebSVN 2.1.0

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