Line 9... |
Line 9... |
Julius Baxter, julius@opencores.org
|
Julius Baxter, julius@opencores.org
|
|
|
*/
|
*/
|
|
|
#include "cpu-utils.h"
|
#include "cpu-utils.h"
|
#include "uart.h"
|
|
#include "printf.h"
|
#include "printf.h"
|
|
|
static int sdiv_errors, udiv_errors;
|
static int sdiv_errors, udiv_errors;
|
|
|
#define VERBOSE_TESTS 0
|
#define VERBOSE_TESTS 0
|
|
|
// Make this bigger when running on FPGA target. For simulation it's enough.
|
// Make this bigger when running on FPGA target. For simulation it's enough.
|
#define NUM_TESTS 200
|
#define NUM_TESTS 2000
|
|
|
int
|
int
|
or1k_div(int dividend, int divisor)
|
or1k_div(int dividend, int divisor)
|
{
|
{
|
int result;
|
int result;
|
Line 40... |
Line 39... |
|
|
void
|
void
|
check_div(int dividend, int divisor, int expected_result)
|
check_div(int dividend, int divisor, int expected_result)
|
{
|
{
|
#if VERBOSE_TESTS
|
#if VERBOSE_TESTS
|
printf("l.div 0x%.8x / 0x%.8x = 0x%.8x : ", dividend, divisor,
|
printf("l.div 0x%.8x / 0x%.8x = (SW) 0x%.8x : ", dividend, divisor,
|
expected_result);
|
expected_result);
|
#endif
|
#endif
|
int result = or1k_div(dividend, divisor);
|
int result = or1k_div(dividend, divisor);
|
|
report(result);
|
if ( result != expected_result)
|
if ( result != expected_result)
|
{
|
{
|
printf("l.div 0x%.8x / 0x%.8x = 0x%.8x : ", dividend, divisor,
|
printf("l.div 0x%.8x / 0x%.8x = (SW) 0x%.8x : ", dividend, divisor,
|
expected_result);
|
expected_result);
|
|
|
printf("FAIL - 0x%.8x\n",result);
|
printf("(HW) 0x%.8x - MISMATCH\n",result);
|
sdiv_errors++;
|
sdiv_errors++;
|
}
|
}
|
#if VERBOSE_TESTS
|
#if VERBOSE_TESTS
|
else
|
else
|
printf("OK\n");
|
printf("OK\n");
|
Line 64... |
Line 64... |
void
|
void
|
check_divu(unsigned int dividend, unsigned int divisor,
|
check_divu(unsigned int dividend, unsigned int divisor,
|
unsigned int expected_result)
|
unsigned int expected_result)
|
{
|
{
|
#if VERBOSE_TESTS
|
#if VERBOSE_TESTS
|
printf("l.divu 0x%.8x / 0x%.8x = 0x%.8x : ", dividend, divisor,
|
printf("l.divu 0x%.8x / 0x%.8x = (SW) 0x%.8x : ", dividend, divisor,
|
expected_result);
|
expected_result);
|
#endif
|
#endif
|
|
|
unsigned int result = or1k_div(dividend, divisor);
|
unsigned int result = or1k_divu(dividend, divisor);
|
|
report(result);
|
if ( result != expected_result)
|
if ( result != expected_result)
|
{
|
{
|
printf("l.divu 0x%.8x / 0x%.8x = 0x%.8x : ", dividend, divisor,
|
printf("l.divu 0x%.8x / 0x%.8x = (SW) 0x%.8x : ", dividend, divisor,
|
expected_result);
|
expected_result);
|
|
|
printf("FAIL - 0x%.8x\n",result);
|
printf("(HW) 0x%.8x - MISMATCH\n",result);
|
udiv_errors++;
|
udiv_errors++;
|
}
|
}
|
#if VERBOSE_TESTS
|
#if VERBOSE_TESTS
|
else
|
else
|
printf("OK\n");
|
printf("OK\n");
|
Line 135... |
Line 136... |
while(i < NUM_TESTS)
|
while(i < NUM_TESTS)
|
{
|
{
|
n = rand();
|
n = rand();
|
d = rand();
|
d = rand();
|
|
|
|
report(0x10101010);
|
|
|
while ( d >= n )
|
while ( d >= n )
|
d >>= (rand() & 0xff);
|
d >>= (rand() & 0xff);
|
|
|
if (n&0x80000000) // numerator is negative
|
if (n&0x80000000) // numerator is negative
|
{
|
{
|
// Calculate a value that's really smaller than the numerator
|
// Calculate a value that's really smaller than the numerator
|
while ( d >= ~(n-1) )
|
while ( d >= ~(n-1) )
|
d >>= (rand() & 0xff);
|
d >>= (rand() & 0xff);
|
|
|
|
if (!d) d = 1;
|
// Processor thinks it's in 2's complement already, so we'll convert
|
// Processor thinks it's in 2's complement already, so we'll convert
|
// from the interpreted 2's complement to unsigned for our calculation
|
// from the interpreted 2's complement to unsigned for our calculation
|
expected_result = div_soft(~(n-1), d);
|
expected_result = div_soft(~(n-1), d);
|
// Answer will be an unsigned +ve value, but of course it has to be
|
// Answer will be an unsigned +ve value, but of course it has to be
|
// negative so convert back to 2's complment negative
|
// negative so convert back to 2's complment negative
|
expected_result = ~expected_result + 1; // 2's complement
|
expected_result = ~expected_result + 1; // 2's complement
|
}
|
}
|
else
|
else
|
expected_result = div_soft(n, d);
|
expected_result = div_soft(n, d);
|
|
|
|
/* Report things */
|
|
report(n);
|
|
report(d);
|
|
report(expected_result);
|
|
|
|
/* Signed divide */
|
check_div(n, d, expected_result);
|
check_div(n, d, expected_result);
|
|
|
|
|
|
/* Unsigned divide test */
|
|
/* Ensure numerator's bit 31 is clear */
|
n >>= 1;
|
n >>= 1;
|
|
|
|
/* If divisor is > numerator, shift it by a random amount */
|
while ( d >= n )
|
while ( d >= n )
|
d >>= (rand() & 0xff);
|
d >>= (rand() & 0xff);
|
|
if (!d) d = 1;
|
|
|
expected_result = div_soft(n, d);
|
expected_result = div_soft(n, d);
|
|
|
|
/* Report things */
|
|
report(n);
|
|
report(d);
|
|
report(expected_result);
|
|
|
|
/* Unsigned divide */
|
check_divu(n, d, expected_result);
|
check_divu(n, d, expected_result);
|
|
|
i++;
|
i++;
|
//printf("%d\n",i);
|
|
|
|
}
|
}
|
|
|
|
|
printf("Division check complete\n");
|
printf("Division check complete\n");
|