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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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