aboutsummaryrefslogtreecommitdiff
path: root/sw/test-adder/test-adder.c
blob: 70415d8bfb83312ec644080a7c75cc093e7555d4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
//------------------------------------------------------------------------------
// 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
//------------------------------------------------------------------------------