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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [example/] [coremark/] [core_matrix.c] - Blame information for rev 69

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

Line No. Rev Author Line
1 2 zero_gravi
/*
2
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
3
 
4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7
 
8
    http://www.apache.org/licenses/LICENSE-2.0
9
 
10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
 
16
Original Author: Shay Gal-on
17
*/
18
 
19
#include "coremark.h"
20
/*
21
Topic: Description
22 38 zero_gravi
        Matrix manipulation benchmark
23 2 zero_gravi
 
24 38 zero_gravi
        This very simple algorithm forms the basis of many more complex
25
algorithms.
26
 
27
        The tight inner loop is the focus of many optimizations (compiler as
28
well as hardware based) and is thus relevant for embedded processing.
29
 
30
        The total available data space will be divided to 3 parts:
31
        NxN Matrix A - initialized with small values (upper 3/4 of the bits all
32
zero). NxN Matrix B - initialized with medium values (upper half of the bits all
33
zero). NxN Matrix C - used for the result.
34
 
35
        The actual values for A and B must be derived based on input that is not
36
available at compile time.
37 2 zero_gravi
*/
38
ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val);
39
ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval);
40 38 zero_gravi
void   matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val);
41
void   matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
42
void   matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
43
void   matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
44
void   matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val);
45 2 zero_gravi
 
46 38 zero_gravi
#define matrix_test_next(x)      (x + 1)
47
#define matrix_clip(x, y)        ((y) ? (x)&0x0ff : (x)&0x0ffff)
48
#define matrix_big(x)            (0xf000 | (x))
49
#define bit_extract(x, from, to) (((x) >> (from)) & (~(0xffffffff << (to))))
50 2 zero_gravi
 
51
#if CORE_DEBUG
52 38 zero_gravi
void
53
printmat(MATDAT *A, ee_u32 N, char *name)
54
{
55
    ee_u32 i, j;
56
    ee_printf("Matrix %s [%dx%d]:\n", name, N, N);
57
    for (i = 0; i < N; i++)
58
    {
59
        for (j = 0; j < N; j++)
60
        {
61
            if (j != 0)
62
                ee_printf(",");
63
            ee_printf("%d", A[i * N + j]);
64
        }
65
        ee_printf("\n");
66
    }
67 2 zero_gravi
}
68 38 zero_gravi
void
69
printmatC(MATRES *C, ee_u32 N, char *name)
70
{
71
    ee_u32 i, j;
72
    ee_printf("Matrix %s [%dx%d]:\n", name, N, N);
73
    for (i = 0; i < N; i++)
74
    {
75
        for (j = 0; j < N; j++)
76
        {
77
            if (j != 0)
78
                ee_printf(",");
79
            ee_printf("%d", C[i * N + j]);
80
        }
81
        ee_printf("\n");
82
    }
83 2 zero_gravi
}
84
#endif
85
/* Function: core_bench_matrix
86 38 zero_gravi
        Benchmark function
87 2 zero_gravi
 
88 38 zero_gravi
        Iterate <matrix_test> N times,
89
        changing the matrix values slightly by a constant amount each time.
90 2 zero_gravi
*/
91 38 zero_gravi
ee_u16
92
core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc)
93
{
94
    ee_u32  N   = p->N;
95
    MATRES *C   = p->C;
96
    MATDAT *A   = p->A;
97
    MATDAT *B   = p->B;
98
    MATDAT  val = (MATDAT)seed;
99 2 zero_gravi
 
100 38 zero_gravi
    crc = crc16(matrix_test(N, C, A, B, val), crc);
101 2 zero_gravi
 
102 38 zero_gravi
    return crc;
103 2 zero_gravi
}
104
 
105
/* Function: matrix_test
106 38 zero_gravi
        Perform matrix manipulation.
107 2 zero_gravi
 
108 38 zero_gravi
        Parameters:
109
        N - Dimensions of the matrix.
110
        C - memory for result matrix.
111
        A - input matrix
112
        B - operator matrix (not changed during operations)
113 2 zero_gravi
 
114 38 zero_gravi
        Returns:
115
        A CRC value that captures all results calculated in the function.
116
        In particular, crc of the value calculated on the result matrix
117
        after each step by <matrix_sum>.
118 2 zero_gravi
 
119 38 zero_gravi
        Operation:
120 2 zero_gravi
 
121 38 zero_gravi
        1 - Add a constant value to all elements of a matrix.
122
        2 - Multiply a matrix by a constant.
123
        3 - Multiply a matrix by a vector.
124
        4 - Multiply a matrix by a matrix.
125
        5 - Add a constant value to all elements of a matrix.
126
 
127
        After the last step, matrix A is back to original contents.
128 2 zero_gravi
*/
129 38 zero_gravi
ee_s16
130
matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val)
131
{
132
    ee_u16 crc     = 0;
133
    MATDAT clipval = matrix_big(val);
134 2 zero_gravi
 
135 38 zero_gravi
    matrix_add_const(N, A, val); /* make sure data changes  */
136 2 zero_gravi
#if CORE_DEBUG
137 38 zero_gravi
    printmat(A, N, "matrix_add_const");
138 2 zero_gravi
#endif
139 38 zero_gravi
    matrix_mul_const(N, C, A, val);
140
    crc = crc16(matrix_sum(N, C, clipval), crc);
141 2 zero_gravi
#if CORE_DEBUG
142 38 zero_gravi
    printmatC(C, N, "matrix_mul_const");
143 2 zero_gravi
#endif
144 38 zero_gravi
    matrix_mul_vect(N, C, A, B);
145
    crc = crc16(matrix_sum(N, C, clipval), crc);
146 2 zero_gravi
#if CORE_DEBUG
147 38 zero_gravi
    printmatC(C, N, "matrix_mul_vect");
148 2 zero_gravi
#endif
149 38 zero_gravi
    matrix_mul_matrix(N, C, A, B);
150
    crc = crc16(matrix_sum(N, C, clipval), crc);
151 2 zero_gravi
#if CORE_DEBUG
152 38 zero_gravi
    printmatC(C, N, "matrix_mul_matrix");
153 2 zero_gravi
#endif
154 38 zero_gravi
    matrix_mul_matrix_bitextract(N, C, A, B);
155
    crc = crc16(matrix_sum(N, C, clipval), crc);
156 2 zero_gravi
#if CORE_DEBUG
157 38 zero_gravi
    printmatC(C, N, "matrix_mul_matrix_bitextract");
158 2 zero_gravi
#endif
159 38 zero_gravi
 
160
    matrix_add_const(N, A, -val); /* return matrix to initial value */
161
    return crc;
162 2 zero_gravi
}
163
 
164
/* Function : matrix_init
165 38 zero_gravi
        Initialize the memory block for matrix benchmarking.
166 2 zero_gravi
 
167 38 zero_gravi
        Parameters:
168
        blksize - Size of memory to be initialized.
169
        memblk - Pointer to memory block.
170
        seed - Actual values chosen depend on the seed parameter.
171
        p - pointers to <mat_params> containing initialized matrixes.
172 2 zero_gravi
 
173 38 zero_gravi
        Returns:
174
        Matrix dimensions.
175
 
176
        Note:
177
        The seed parameter MUST be supplied from a source that cannot be
178
   determined at compile time
179 2 zero_gravi
*/
180 38 zero_gravi
ee_u32
181
core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p)
182
{
183
    ee_u32  N = 0;
184
    MATDAT *A;
185
    MATDAT *B;
186
    ee_s32  order = 1;
187
    MATDAT  val;
188
    ee_u32  i = 0, j = 0;
189
    if (seed == 0)
190
        seed = 1;
191
    while (j < blksize)
192
    {
193
        i++;
194
        j = i * i * 2 * 4;
195
    }
196
    N = i - 1;
197
    A = (MATDAT *)align_mem(memblk);
198
    B = A + N * N;
199 2 zero_gravi
 
200 38 zero_gravi
    for (i = 0; i < N; i++)
201
    {
202
        for (j = 0; j < N; j++)
203
        {
204
            seed         = ((order * seed) % 65536);
205
            val          = (seed + order);
206
            val          = matrix_clip(val, 0);
207
            B[i * N + j] = val;
208
            val          = (val + order);
209
            val          = matrix_clip(val, 1);
210
            A[i * N + j] = val;
211
            order++;
212
        }
213
    }
214 2 zero_gravi
 
215 38 zero_gravi
    p->A = A;
216
    p->B = B;
217
    p->C = (MATRES *)align_mem(B + N * N);
218
    p->N = N;
219 2 zero_gravi
#if CORE_DEBUG
220 38 zero_gravi
    printmat(A, N, "A");
221
    printmat(B, N, "B");
222 2 zero_gravi
#endif
223 38 zero_gravi
    return N;
224 2 zero_gravi
}
225
 
226
/* Function: matrix_sum
227 38 zero_gravi
        Calculate a function that depends on the values of elements in the
228
   matrix.
229 2 zero_gravi
 
230 38 zero_gravi
        For each element, accumulate into a temporary variable.
231
 
232
        As long as this value is under the parameter clipval,
233
        add 1 to the result if the element is bigger then the previous.
234
 
235
        Otherwise, reset the accumulator and add 10 to the result.
236 2 zero_gravi
*/
237 38 zero_gravi
ee_s16
238
matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval)
239
{
240
    MATRES tmp = 0, prev = 0, cur = 0;
241
    ee_s16 ret = 0;
242
    ee_u32 i, j;
243
    for (i = 0; i < N; i++)
244
    {
245
        for (j = 0; j < N; j++)
246
        {
247
            cur = C[i * N + j];
248
            tmp += cur;
249
            if (tmp > clipval)
250
            {
251
                ret += 10;
252
                tmp = 0;
253
            }
254
            else
255
            {
256
                ret += (cur > prev) ? 1 : 0;
257
            }
258
            prev = cur;
259
        }
260
    }
261
    return ret;
262 2 zero_gravi
}
263
 
264
/* Function: matrix_mul_const
265 38 zero_gravi
        Multiply a matrix by a constant.
266
        This could be used as a scaler for instance.
267 2 zero_gravi
*/
268 38 zero_gravi
void
269
matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val)
270
{
271
    ee_u32 i, j;
272
    for (i = 0; i < N; i++)
273
    {
274
        for (j = 0; j < N; j++)
275
        {
276
            C[i * N + j] = (MATRES)A[i * N + j] * (MATRES)val;
277
        }
278
    }
279 2 zero_gravi
}
280
 
281
/* Function: matrix_add_const
282 38 zero_gravi
        Add a constant value to all elements of a matrix.
283 2 zero_gravi
*/
284 38 zero_gravi
void
285
matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val)
286
{
287
    ee_u32 i, j;
288
    for (i = 0; i < N; i++)
289
    {
290
        for (j = 0; j < N; j++)
291
        {
292
            A[i * N + j] += val;
293
        }
294
    }
295 2 zero_gravi
}
296
 
297
/* Function: matrix_mul_vect
298 38 zero_gravi
        Multiply a matrix by a vector.
299
        This is common in many simple filters (e.g. fir where a vector of
300
   coefficients is applied to the matrix.)
301 2 zero_gravi
*/
302 38 zero_gravi
void
303
matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
304
{
305
    ee_u32 i, j;
306
    for (i = 0; i < N; i++)
307
    {
308
        C[i] = 0;
309
        for (j = 0; j < N; j++)
310
        {
311
            C[i] += (MATRES)A[i * N + j] * (MATRES)B[j];
312
        }
313
    }
314 2 zero_gravi
}
315
 
316
/* Function: matrix_mul_matrix
317 38 zero_gravi
        Multiply a matrix by a matrix.
318
        Basic code is used in many algorithms, mostly with minor changes such as
319
   scaling.
320 2 zero_gravi
*/
321 38 zero_gravi
void
322
matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
323
{
324
    ee_u32 i, j, k;
325
    for (i = 0; i < N; i++)
326
    {
327
        for (j = 0; j < N; j++)
328
        {
329
            C[i * N + j] = 0;
330
            for (k = 0; k < N; k++)
331
            {
332
                C[i * N + j] += (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
333
            }
334
        }
335
    }
336 2 zero_gravi
}
337
 
338
/* Function: matrix_mul_matrix_bitextract
339 38 zero_gravi
        Multiply a matrix by a matrix, and extract some bits from the result.
340
        Basic code is used in many algorithms, mostly with minor changes such as
341
   scaling.
342 2 zero_gravi
*/
343 38 zero_gravi
void
344
matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
345
{
346
    ee_u32 i, j, k;
347
    for (i = 0; i < N; i++)
348
    {
349
        for (j = 0; j < N; j++)
350
        {
351
            C[i * N + j] = 0;
352
            for (k = 0; k < N; k++)
353
            {
354
                MATRES tmp = (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
355
                C[i * N + j] += bit_extract(tmp, 2, 4) * bit_extract(tmp, 5, 7);
356
            }
357
        }
358
    }
359 2 zero_gravi
}

powered by: WebSVN 2.1.0

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