/*
|
/*
|
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC)
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
limitations under the License.
|
limitations under the License.
|
|
|
Original Author: Shay Gal-on
|
Original Author: Shay Gal-on
|
*/
|
*/
|
|
|
#include "coremark.h"
|
#include "coremark.h"
|
/*
|
/*
|
Topic: Description
|
Topic: Description
|
Matrix manipulation benchmark
|
Matrix manipulation benchmark
|
|
|
This very simple algorithm forms the basis of many more complex algorithms.
|
This very simple algorithm forms the basis of many more complex
|
|
algorithms.
|
|
|
The tight inner loop is the focus of many optimizations (compiler as well as hardware based)
|
The tight inner loop is the focus of many optimizations (compiler as
|
and is thus relevant for embedded processing.
|
well as hardware based) and is thus relevant for embedded processing.
|
|
|
The total available data space will be divided to 3 parts:
|
The total available data space will be divided to 3 parts:
|
NxN Matrix A - initialized with small values (upper 3/4 of the bits all zero).
|
NxN Matrix A - initialized with small values (upper 3/4 of the bits all
|
NxN Matrix B - initialized with medium values (upper half of the bits all zero).
|
zero). NxN Matrix B - initialized with medium values (upper half of the bits all
|
NxN Matrix C - used for the result.
|
zero). NxN Matrix C - used for the result.
|
|
|
The actual values for A and B must be derived based on input that is not available at compile time.
|
The actual values for A and B must be derived based on input that is not
|
|
available at compile time.
|
*/
|
*/
|
ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val);
|
ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val);
|
ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval);
|
ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval);
|
void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val);
|
void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val);
|
void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
|
void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
|
void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
|
void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
|
void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
|
void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B);
|
void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val);
|
void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val);
|
|
|
#define matrix_test_next(x) (x+1)
|
#define matrix_test_next(x) (x + 1)
|
#define matrix_clip(x,y) ((y) ? (x) & 0x0ff : (x) & 0x0ffff)
|
#define matrix_clip(x, y) ((y) ? (x)&0x0ff : (x)&0x0ffff)
|
#define matrix_big(x) (0xf000 | (x))
|
#define matrix_big(x) (0xf000 | (x))
|
#define bit_extract(x,from,to) (((x)>>(from)) & (~(0xffffffff << (to))))
|
#define bit_extract(x, from, to) (((x) >> (from)) & (~(0xffffffff << (to))))
|
|
|
#if CORE_DEBUG
|
#if CORE_DEBUG
|
void printmat(MATDAT *A, ee_u32 N, char *name) {
|
void
|
|
printmat(MATDAT *A, ee_u32 N, char *name)
|
|
{
|
ee_u32 i,j;
|
ee_u32 i,j;
|
ee_printf("Matrix %s [%dx%d]:\n",name,N,N);
|
ee_printf("Matrix %s [%dx%d]:\n",name,N,N);
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
for (j=0; j<N; j++) {
|
{
|
|
for (j = 0; j < N; j++)
|
|
{
|
if (j!=0)
|
if (j!=0)
|
ee_printf(",");
|
ee_printf(",");
|
ee_printf("%d",A[i*N+j]);
|
ee_printf("%d", A[i * N + j]);
|
}
|
}
|
ee_printf("\n");
|
ee_printf("\n");
|
}
|
}
|
}
|
}
|
void printmatC(MATRES *C, ee_u32 N, char *name) {
|
void
|
|
printmatC(MATRES *C, ee_u32 N, char *name)
|
|
{
|
ee_u32 i,j;
|
ee_u32 i,j;
|
ee_printf("Matrix %s [%dx%d]:\n",name,N,N);
|
ee_printf("Matrix %s [%dx%d]:\n",name,N,N);
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
for (j=0; j<N; j++) {
|
{
|
|
for (j = 0; j < N; j++)
|
|
{
|
if (j!=0)
|
if (j!=0)
|
ee_printf(",");
|
ee_printf(",");
|
ee_printf("%d",C[i*N+j]);
|
ee_printf("%d", C[i * N + j]);
|
}
|
}
|
ee_printf("\n");
|
ee_printf("\n");
|
}
|
}
|
}
|
}
|
#endif
|
#endif
|
/* Function: core_bench_matrix
|
/* Function: core_bench_matrix
|
Benchmark function
|
Benchmark function
|
|
|
Iterate <matrix_test> N times,
|
Iterate <matrix_test> N times,
|
changing the matrix values slightly by a constant amount each time.
|
changing the matrix values slightly by a constant amount each time.
|
*/
|
*/
|
ee_u16 core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc) {
|
ee_u16
|
|
core_bench_matrix(mat_params *p, ee_s16 seed, ee_u16 crc)
|
|
{
|
ee_u32 N=p->N;
|
ee_u32 N=p->N;
|
MATRES *C=p->C;
|
MATRES *C = p->C;
|
MATDAT *A=p->A;
|
MATDAT *A = p->A;
|
MATDAT *B=p->B;
|
MATDAT *B = p->B;
|
MATDAT val=(MATDAT)seed;
|
MATDAT val = (MATDAT)seed;
|
|
|
crc=crc16(matrix_test(N,C,A,B,val),crc);
|
crc = crc16(matrix_test(N, C, A, B, val), crc);
|
|
|
return crc;
|
return crc;
|
}
|
}
|
|
|
/* Function: matrix_test
|
/* Function: matrix_test
|
Perform matrix manipulation.
|
Perform matrix manipulation.
|
|
|
Parameters:
|
Parameters:
|
N - Dimensions of the matrix.
|
N - Dimensions of the matrix.
|
C - memory for result matrix.
|
C - memory for result matrix.
|
A - input matrix
|
A - input matrix
|
B - operator matrix (not changed during operations)
|
B - operator matrix (not changed during operations)
|
|
|
Returns:
|
Returns:
|
A CRC value that captures all results calculated in the function.
|
A CRC value that captures all results calculated in the function.
|
In particular, crc of the value calculated on the result matrix
|
In particular, crc of the value calculated on the result matrix
|
after each step by <matrix_sum>.
|
after each step by <matrix_sum>.
|
|
|
Operation:
|
Operation:
|
|
|
1 - Add a constant value to all elements of a matrix.
|
1 - Add a constant value to all elements of a matrix.
|
2 - Multiply a matrix by a constant.
|
2 - Multiply a matrix by a constant.
|
3 - Multiply a matrix by a vector.
|
3 - Multiply a matrix by a vector.
|
4 - Multiply a matrix by a matrix.
|
4 - Multiply a matrix by a matrix.
|
5 - Add a constant value to all elements of a matrix.
|
5 - Add a constant value to all elements of a matrix.
|
|
|
After the last step, matrix A is back to original contents.
|
After the last step, matrix A is back to original contents.
|
*/
|
*/
|
ee_s16 matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val) {
|
ee_s16
|
|
matrix_test(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B, MATDAT val)
|
|
{
|
ee_u16 crc=0;
|
ee_u16 crc=0;
|
MATDAT clipval=matrix_big(val);
|
MATDAT clipval = matrix_big(val);
|
|
|
matrix_add_const(N,A,val); /* make sure data changes */
|
matrix_add_const(N, A, val); /* make sure data changes */
|
#if CORE_DEBUG
|
#if CORE_DEBUG
|
printmat(A,N,"matrix_add_const");
|
printmat(A, N, "matrix_add_const");
|
#endif
|
#endif
|
matrix_mul_const(N,C,A,val);
|
matrix_mul_const(N, C, A, val);
|
crc=crc16(matrix_sum(N,C,clipval),crc);
|
crc = crc16(matrix_sum(N, C, clipval), crc);
|
#if CORE_DEBUG
|
#if CORE_DEBUG
|
printmatC(C,N,"matrix_mul_const");
|
printmatC(C, N, "matrix_mul_const");
|
#endif
|
#endif
|
matrix_mul_vect(N,C,A,B);
|
matrix_mul_vect(N, C, A, B);
|
crc=crc16(matrix_sum(N,C,clipval),crc);
|
crc = crc16(matrix_sum(N, C, clipval), crc);
|
#if CORE_DEBUG
|
#if CORE_DEBUG
|
printmatC(C,N,"matrix_mul_vect");
|
printmatC(C, N, "matrix_mul_vect");
|
#endif
|
#endif
|
matrix_mul_matrix(N,C,A,B);
|
matrix_mul_matrix(N, C, A, B);
|
crc=crc16(matrix_sum(N,C,clipval),crc);
|
crc = crc16(matrix_sum(N, C, clipval), crc);
|
#if CORE_DEBUG
|
#if CORE_DEBUG
|
printmatC(C,N,"matrix_mul_matrix");
|
printmatC(C, N, "matrix_mul_matrix");
|
#endif
|
#endif
|
matrix_mul_matrix_bitextract(N,C,A,B);
|
matrix_mul_matrix_bitextract(N, C, A, B);
|
crc=crc16(matrix_sum(N,C,clipval),crc);
|
crc = crc16(matrix_sum(N, C, clipval), crc);
|
#if CORE_DEBUG
|
#if CORE_DEBUG
|
printmatC(C,N,"matrix_mul_matrix_bitextract");
|
printmatC(C, N, "matrix_mul_matrix_bitextract");
|
#endif
|
#endif
|
|
|
matrix_add_const(N,A,-val); /* return matrix to initial value */
|
matrix_add_const(N, A, -val); /* return matrix to initial value */
|
return crc;
|
return crc;
|
}
|
}
|
|
|
/* Function : matrix_init
|
/* Function : matrix_init
|
Initialize the memory block for matrix benchmarking.
|
Initialize the memory block for matrix benchmarking.
|
|
|
Parameters:
|
Parameters:
|
blksize - Size of memory to be initialized.
|
blksize - Size of memory to be initialized.
|
memblk - Pointer to memory block.
|
memblk - Pointer to memory block.
|
seed - Actual values chosen depend on the seed parameter.
|
seed - Actual values chosen depend on the seed parameter.
|
p - pointers to <mat_params> containing initialized matrixes.
|
p - pointers to <mat_params> containing initialized matrixes.
|
|
|
Returns:
|
Returns:
|
Matrix dimensions.
|
Matrix dimensions.
|
|
|
Note:
|
Note:
|
The seed parameter MUST be supplied from a source that cannot be determined at compile time
|
The seed parameter MUST be supplied from a source that cannot be
|
|
determined at compile time
|
*/
|
*/
|
ee_u32 core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p) {
|
ee_u32
|
|
core_init_matrix(ee_u32 blksize, void *memblk, ee_s32 seed, mat_params *p)
|
|
{
|
ee_u32 N=0;
|
ee_u32 N=0;
|
MATDAT *A;
|
MATDAT *A;
|
MATDAT *B;
|
MATDAT *B;
|
ee_s32 order=1;
|
ee_s32 order = 1;
|
MATDAT val;
|
MATDAT val;
|
ee_u32 i=0,j=0;
|
ee_u32 i = 0, j = 0;
|
if (seed==0)
|
if (seed == 0)
|
seed=1;
|
seed=1;
|
while (j<blksize) {
|
while (j < blksize)
|
|
{
|
i++;
|
i++;
|
j=i*i*2*4;
|
j = i * i * 2 * 4;
|
}
|
}
|
N=i-1;
|
N = i - 1;
|
A=(MATDAT *)align_mem(memblk);
|
A = (MATDAT *)align_mem(memblk);
|
B=A+N*N;
|
B = A + N * N;
|
|
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
for (j=0; j<N; j++) {
|
{
|
|
for (j = 0; j < N; j++)
|
|
{
|
seed = ( ( order * seed ) % 65536 );
|
seed = ( ( order * seed ) % 65536 );
|
val = (seed + order);
|
val = (seed + order);
|
val=matrix_clip(val,0);
|
val = matrix_clip(val, 0);
|
B[i*N+j] = val;
|
B[i * N + j] = val;
|
val = (val + order);
|
val = (val + order);
|
val=matrix_clip(val,1);
|
val = matrix_clip(val, 1);
|
A[i*N+j] = val;
|
A[i * N + j] = val;
|
order++;
|
order++;
|
}
|
}
|
}
|
}
|
|
|
p->A=A;
|
p->A = A;
|
p->B=B;
|
p->B = B;
|
p->C=(MATRES *)align_mem(B+N*N);
|
p->C = (MATRES *)align_mem(B + N * N);
|
p->N=N;
|
p->N = N;
|
#if CORE_DEBUG
|
#if CORE_DEBUG
|
printmat(A,N,"A");
|
printmat(A, N, "A");
|
printmat(B,N,"B");
|
printmat(B, N, "B");
|
#endif
|
#endif
|
return N;
|
return N;
|
}
|
}
|
|
|
/* Function: matrix_sum
|
/* Function: matrix_sum
|
Calculate a function that depends on the values of elements in the matrix.
|
Calculate a function that depends on the values of elements in the
|
|
matrix.
|
|
|
For each element, accumulate into a temporary variable.
|
For each element, accumulate into a temporary variable.
|
|
|
As long as this value is under the parameter clipval,
|
As long as this value is under the parameter clipval,
|
add 1 to the result if the element is bigger then the previous.
|
add 1 to the result if the element is bigger then the previous.
|
|
|
Otherwise, reset the accumulator and add 10 to the result.
|
Otherwise, reset the accumulator and add 10 to the result.
|
*/
|
*/
|
ee_s16 matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval) {
|
ee_s16
|
|
matrix_sum(ee_u32 N, MATRES *C, MATDAT clipval)
|
|
{
|
MATRES tmp=0,prev=0,cur=0;
|
MATRES tmp=0,prev=0,cur=0;
|
ee_s16 ret=0;
|
ee_s16 ret = 0;
|
ee_u32 i,j;
|
ee_u32 i,j;
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
for (j=0; j<N; j++) {
|
{
|
|
for (j = 0; j < N; j++)
|
|
{
|
cur=C[i*N+j];
|
cur=C[i*N+j];
|
tmp+=cur;
|
tmp+=cur;
|
if (tmp>clipval) {
|
if (tmp > clipval)
|
|
{
|
ret+=10;
|
ret+=10;
|
tmp=0;
|
tmp=0;
|
} else {
|
}
|
|
else
|
|
{
|
ret += (cur>prev) ? 1 : 0;
|
ret += (cur>prev) ? 1 : 0;
|
}
|
}
|
prev=cur;
|
prev = cur;
|
}
|
}
|
}
|
}
|
return ret;
|
return ret;
|
}
|
}
|
|
|
/* Function: matrix_mul_const
|
/* Function: matrix_mul_const
|
Multiply a matrix by a constant.
|
Multiply a matrix by a constant.
|
This could be used as a scaler for instance.
|
This could be used as a scaler for instance.
|
*/
|
*/
|
void matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val) {
|
void
|
|
matrix_mul_const(ee_u32 N, MATRES *C, MATDAT *A, MATDAT val)
|
|
{
|
ee_u32 i,j;
|
ee_u32 i,j;
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
for (j=0; j<N; j++) {
|
{
|
|
for (j = 0; j < N; j++)
|
|
{
|
C[i*N+j]=(MATRES)A[i*N+j] * (MATRES)val;
|
C[i*N+j]=(MATRES)A[i*N+j] * (MATRES)val;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Function: matrix_add_const
|
/* Function: matrix_add_const
|
Add a constant value to all elements of a matrix.
|
Add a constant value to all elements of a matrix.
|
*/
|
*/
|
void matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val) {
|
void
|
|
matrix_add_const(ee_u32 N, MATDAT *A, MATDAT val)
|
|
{
|
ee_u32 i,j;
|
ee_u32 i,j;
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
for (j=0; j<N; j++) {
|
{
|
|
for (j = 0; j < N; j++)
|
|
{
|
A[i*N+j] += val;
|
A[i*N+j] += val;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Function: matrix_mul_vect
|
/* Function: matrix_mul_vect
|
Multiply a matrix by a vector.
|
Multiply a matrix by a vector.
|
This is common in many simple filters (e.g. fir where a vector of coefficients is applied to the matrix.)
|
This is common in many simple filters (e.g. fir where a vector of
|
|
coefficients is applied to the matrix.)
|
*/
|
*/
|
void matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) {
|
void
|
|
matrix_mul_vect(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
|
|
{
|
ee_u32 i,j;
|
ee_u32 i,j;
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
|
{
|
C[i]=0;
|
C[i]=0;
|
for (j=0; j<N; j++) {
|
for (j = 0; j < N; j++)
|
|
{
|
C[i]+=(MATRES)A[i*N+j] * (MATRES)B[j];
|
C[i]+=(MATRES)A[i*N+j] * (MATRES)B[j];
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Function: matrix_mul_matrix
|
/* Function: matrix_mul_matrix
|
Multiply a matrix by a matrix.
|
Multiply a matrix by a matrix.
|
Basic code is used in many algorithms, mostly with minor changes such as scaling.
|
Basic code is used in many algorithms, mostly with minor changes such as
|
|
scaling.
|
*/
|
*/
|
void matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) {
|
void
|
|
matrix_mul_matrix(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
|
|
{
|
ee_u32 i,j,k;
|
ee_u32 i,j,k;
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
for (j=0; j<N; j++) {
|
{
|
|
for (j = 0; j < N; j++)
|
|
{
|
C[i*N+j]=0;
|
C[i*N+j]=0;
|
for(k=0;k<N;k++)
|
for (k = 0; k < N; k++)
|
{
|
{
|
C[i*N+j]+=(MATRES)A[i*N+k] * (MATRES)B[k*N+j];
|
C[i * N + j] += (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/* Function: matrix_mul_matrix_bitextract
|
/* Function: matrix_mul_matrix_bitextract
|
Multiply a matrix by a matrix, and extract some bits from the result.
|
Multiply a matrix by a matrix, and extract some bits from the result.
|
Basic code is used in many algorithms, mostly with minor changes such as scaling.
|
Basic code is used in many algorithms, mostly with minor changes such as
|
|
scaling.
|
*/
|
*/
|
void matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B) {
|
void
|
|
matrix_mul_matrix_bitextract(ee_u32 N, MATRES *C, MATDAT *A, MATDAT *B)
|
|
{
|
ee_u32 i,j,k;
|
ee_u32 i,j,k;
|
for (i=0; i<N; i++) {
|
for (i = 0; i < N; i++)
|
for (j=0; j<N; j++) {
|
{
|
|
for (j = 0; j < N; j++)
|
|
{
|
C[i*N+j]=0;
|
C[i*N+j]=0;
|
for(k=0;k<N;k++)
|
for (k = 0; k < N; k++)
|
{
|
{
|
MATRES tmp=(MATRES)A[i*N+k] * (MATRES)B[k*N+j];
|
MATRES tmp = (MATRES)A[i * N + k] * (MATRES)B[k * N + j];
|
C[i*N+j]+=bit_extract(tmp,2,4)*bit_extract(tmp,5,7);
|
C[i * N + j] += bit_extract(tmp, 2, 4) * bit_extract(tmp, 5, 7);
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|