//------------------------------------------------------------------------------
// setup-eim.c
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include "novena-eim.h"
//------------------------------------------------------------------------------
// Demo Adder
//------------------------------------------------------------------------------
#define DEMO_ADDER_BASE_ADDR (0x3210)
#define DEMO_ADDER_REG_X (EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (0<<2))
#define DEMO_ADDER_REG_Y (EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (1<<2))
#define DEMO_ADDER_REG_Z (EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (2<<2))
#define DEMO_ADDER_REG_SC (EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (3<<2))
//------------------------------------------------------------------------------
// Prototypes
//------------------------------------------------------------------------------
unsigned int demo_adder_test_round (unsigned int, unsigned int);
unsigned int lfsr_next_x (unsigned int);
unsigned int lfsr_next_y (unsigned int);
//------------------------------------------------------------------------------
// Testing Parameters
//------------------------------------------------------------------------------
const int NUM_TEST_ROUNDS = 10000;
const int PRINT_XYZ_VALUES = 1;
//------------------------------------------------------------------------------
int main()
//------------------------------------------------------------------------------
{
// try to setup eim (return value should be 1)
printf("Configuring EIM .. ");
int ok = eim_setup();
if (ok < 1)
{ printf("ERROR\n");
return EXIT_FAILURE;
}
else printf("OK\n");
// run test
int i;
unsigned int x = 0x12341234, y = 0xABCDABCD, zyx;
printf("Testing started.\n");
for (i=0; i<NUM_TEST_ROUNDS; i++)
{
// run another round
unsigned int z = demo_adder_test_round(x, y);
// calculate correct answer
zyx = x + y;
// check result
if (z != zyx)
{ printf("ERROR: round %10d of %10d: x == 0x%08X, y == 0x%08X, z == 0x%08X [z should be 0x%08X]\n", i+1, NUM_TEST_ROUNDS, x, y, z, zyx);
exit(EXIT_FAILURE);
}
else if (PRINT_XYZ_VALUES) printf("OK: round %10d of %10d: x == 0x%08X, y == 0x%08X, z == 0x%08X\n", i+1, NUM_TEST_ROUNDS, x, y, z);
// update input values
x = lfsr_next_x(x);
y = lfsr_next_x(y);
}
// ok
printf("Testing completed successfully.\n");
// done
return EXIT_SUCCESS;
}
//------------------------------------------------------------------------------
unsigned int demo_adder_test_round(unsigned int x, unsigned int y)
//------------------------------------------------------------------------------
{
// write x
eim_write_32(DEMO_ADDER_REG_X, &x);
// write y
eim_write_32(DEMO_ADDER_REG_Y, &y);
/* To make adder calculate something we need to change its control register,
* so we read it, increment and write back. Control register is in the lower 16 bits.
*/
unsigned int ctl;
eim_read_32(DEMO_ADDER_REG_SC, &ctl);
ctl += 1;
ctl &= 0x0000FFFF;
eim_write_32(DEMO_ADDER_REG_SC, &ctl);
/* When adder is done, it will write new control value into its status register. Adder has 1-cycle latency
* which is very small, we don't even need to poll, just check that status was updated. Status register is
* in the upper 16 bits.
*/
unsigned int sts;
eim_read_32(DEMO_ADDER_REG_SC, &sts);
sts >>= 16;
if (sts != ctl)
{ printf("ERROR: Adder timeout!\n");
exit(EXIT_FAILURE);
}
// read z
unsigned int z;
eim_read_32(DEMO_ADDER_REG_Z, &z);
// uncomment to trigger an error
/**
z++;
**/
// done
return z;
}
//------------------------------------------------------------------------------
unsigned int lfsr_next_x(unsigned int value)
//------------------------------------------------------------------------------
{
//
// [32, 31, 29, 28, 27, 25, 24, 23, 21, 19, 17, 14, 10, 6, 4, 2]
// 0 1 3 4 5 7 8 9 11 13 15 18 22 24 28 30
//
unsigned int carry = 0;
carry ^= (value >> 0);
carry ^= (value >> 1);
carry ^= (value >> 3);
carry ^= (value >> 4);
carry ^= (value >> 5);
carry ^= (value >> 7);
carry ^= (value >> 8);
carry ^= (value >> 9);
carry ^= (value >> 11);
carry ^= (value >> 13);
carry ^= (value >> 15);
carry ^= (value >> 18);
carry ^= (value >> 22);
carry ^= (value >> 24);
carry ^= (value >> 28);
carry ^= (value >> 30);
value >>= 1, value |= (carry << 31);
return value;
}
//------------------------------------------------------------------------------
unsigned int lfsr_next_y(unsigned int value)
//------------------------------------------------------------------------------
{
//
// [32, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 1]
// 0 15 16 17 18 19 20 21 22 23 24 25 26 27 28 31
//
unsigned int carry = 0;
carry ^= (value >> 0);
carry ^= (value >> 15);
carry ^= (value >> 16);
carry ^= (value >> 17);
carry ^= (value >> 18);
carry ^= (value >> 19);
carry ^= (value >> 20);
carry ^= (value >> 21);
carry ^= (value >> 22);
carry ^= (value >> 23);
carry ^= (value >> 24);
carry ^= (value >> 25);
carry ^= (value >> 26);
carry ^= (value >> 27);
carry ^= (value >> 28);
carry ^= (value >> 31);
value >>= 1, value |= (carry << 31);
return value;
}
//------------------------------------------------------------------------------
// End-of-File
//------------------------------------------------------------------------------