aboutsummaryrefslogtreecommitdiffstats
path: root/test/kvx/mmult
diff options
context:
space:
mode:
authorDavid Monniaux <david.monniaux@univ-grenoble-alpes.fr>2020-05-26 22:11:32 +0200
committerDavid Monniaux <david.monniaux@univ-grenoble-alpes.fr>2020-05-26 22:11:32 +0200
commitbc1e43ea95b9455cdccee442db77bc5fafd3dcc6 (patch)
tree4e82b5f50870603f42ec46d57e543c3e10fb1f4f /test/kvx/mmult
parentb4a08d0815342b6238d307864f0823d0f07bb691 (diff)
downloadcompcert-kvx-bc1e43ea95b9455cdccee442db77bc5fafd3dcc6.tar.gz
compcert-kvx-bc1e43ea95b9455cdccee442db77bc5fafd3dcc6.zip
tests for kvx
Diffstat (limited to 'test/kvx/mmult')
-rw-r--r--test/kvx/mmult/.gitignore4
-rw-r--r--test/kvx/mmult/Makefile67
-rw-r--r--test/kvx/mmult/README.md17
-rw-r--r--test/kvx/mmult/mmult.c146
-rw-r--r--test/kvx/mmult/mmult.h10
5 files changed, 244 insertions, 0 deletions
diff --git a/test/kvx/mmult/.gitignore b/test/kvx/mmult/.gitignore
new file mode 100644
index 00000000..b43ccc5f
--- /dev/null
+++ b/test/kvx/mmult/.gitignore
@@ -0,0 +1,4 @@
+mmult-test-ccomp-kvx
+mmult-test-gcc-kvx
+mmult-test-gcc-x86
+.zero
diff --git a/test/kvx/mmult/Makefile b/test/kvx/mmult/Makefile
new file mode 100644
index 00000000..e7cd890e
--- /dev/null
+++ b/test/kvx/mmult/Makefile
@@ -0,0 +1,67 @@
+KVXC ?= k1-cos-gcc
+CC ?= gcc
+CCOMP ?= ccomp
+CFLAGS ?= -O2
+SIMU ?= k1-mppa
+TIMEOUT ?= 10s
+
+KVXCPATH=$(shell which $(KVXC))
+CCPATH=$(shell which $(CC))
+CCOMPPATH=$(shell which $(CCOMP))
+SIMUPATH=$(shell which $(SIMU))
+
+PRNG=../prng/prng.c
+
+ALL= mmult-test-gcc-x86 mmult-test-gcc-kvx mmult-test-ccomp-kvx
+CCOMP_OUT= mmult-test-ccomp-kvx.out
+GCC_OUT= mmult-test-gcc-kvx.out
+X86_GCC_OUT= mmult-test-gcc-x86.out
+STUB_OUT=.zero
+
+all: $(ALL)
+
+mmult-test-gcc-x86: mmult.c $(PRNG) $(CCPATH)
+ $(CC) $(CFLAGS) $(filter-out $(CCPATH),$^) -o $@
+
+mmult-test-gcc-kvx: mmult.c $(PRNG) $(KVXCPATH)
+ $(KVXC) $(CFLAGS) $(filter-out $(KVXCPATH),$^) -o $@
+
+mmult-test-ccomp-kvx: mmult.c $(PRNG) $(CCOMPPATH)
+ $(CCOMP) $(CFLAGS) $(filter-out $(CCOMPPATH),$^) -o $@
+
+.SECONDARY:
+%kvx.out: %kvx $(SIMUPATH)
+ ret=0; timeout $(TIMEOUT) $(SIMU) -- $< > $@ || { ret=$$?; }; echo $$ret >> $@
+
+%x86.out: %x86
+ ret=0; timeout $(TIMEOUT) ./$< > $@ || { ret=$$?; }; echo $$ret >> $@
+
+.zero:
+ @echo "0" > $@
+
+.PHONY:
+test: test-x86 test-kvx
+
+.PHONY:
+test-x86: $(X86_GCC_OUT) $(STUB_OUT)
+ @if ! diff $< $(STUB_OUT); then\
+ >&2 echo "ERROR x86: $< failed";\
+ else\
+ echo "GOOD x86: $< succeeded";\
+ fi
+
+.PHONY:
+test-kvx: $(GCC_OUT) $(STUB_OUT)
+ @if ! diff $< $(STUB_OUT); then\
+ >&2 echo "ERROR kvx: $< failed";\
+ else\
+ echo "GOOD kvx: $< succeeded";\
+ fi
+
+.PHONY:
+check: $(CCOMP_OUT) $(STUB_OUT)
+ @if ! diff $< $(STUB_OUT); then\
+ >&2 echo "ERROR kvx: $< failed";\
+ else\
+ echo "GOOD kvx: $< succeeded";\
+ fi
diff --git a/test/kvx/mmult/README.md b/test/kvx/mmult/README.md
new file mode 100644
index 00000000..780603f6
--- /dev/null
+++ b/test/kvx/mmult/README.md
@@ -0,0 +1,17 @@
+MMULT
+=====
+
+Examples of matrix multiplication using different methods.
+
+We compute matrix multiplication using column-based matrix multiplication, then row-based, and finally block based.
+
+The test verifies that the result is the same on the three methods. If it is the same, 0 will be returned.
+
+The following commands can be run inside the folder:
+
+- `make`: produces the unitary test binaries
+ - `mmult-test-gcc-x86` : binary from gcc on x86
+ - `mmult-test-kvx-x86` : binary from gcc on kvx
+ - `mmult-test-ccomp-x86` : binary from ccomp on kvx
+- `make test`: tests the return value of the binaries produced by gcc.
+- `make check`: tests the return value of the binary produced by CompCert.
diff --git a/test/kvx/mmult/mmult.c b/test/kvx/mmult/mmult.c
new file mode 100644
index 00000000..aeb91d48
--- /dev/null
+++ b/test/kvx/mmult/mmult.c
@@ -0,0 +1,146 @@
+#include "../prng/types.h"
+#include "../prng/prng.h"
+
+#define __UNIT_TEST_MMULT__
+
+#ifdef __UNIT_TEST_MMULT__
+#define SIZE 10
+#else
+#include "test.h"
+#endif
+
+void mmult_row(uint64_t C[][SIZE], uint64_t A[][SIZE], uint64_t B[][SIZE]){
+ int i, j, k;
+
+ for (i = 0 ; i < SIZE ; i++)
+ for (j = 0 ; j < SIZE ; j++)
+ C[i][j] = 0;
+
+ for (i = 0 ; i < SIZE ; i++)
+ for (j = 0 ; j < SIZE ; j++)
+ for (k = 0 ; k < SIZE ; k++)
+ C[i][j] += A[i][k] * B[k][j];
+}
+
+void mmult_col(uint64_t C[][SIZE], uint64_t A[][SIZE], uint64_t B[][SIZE]){
+ int i, j, k;
+
+ for (i = 0 ; i < SIZE ; i++)
+ for (j = 0 ; j < SIZE ; j++)
+ C[i][j] = 0;
+
+ for (k = 0 ; k < SIZE ; k++)
+ for (i = 0 ; i < SIZE ; i++)
+ for (j = 0 ; j < SIZE ; j++)
+ C[i][j] += A[i][k] * B[k][j];
+}
+
+typedef struct mblock {
+ int imin, imax, jmin, jmax;
+ uint64_t *mat;
+} mblock;
+
+#define MAT_XY(mat, x, y) (mat)[(x)*SIZE + (y)]
+#define MAT_IJ(block, i, j) MAT_XY((block)->mat, (block)->imin + (i), block->jmin + (j))
+
+void divac_mul(mblock *C, const mblock *A, const mblock *B){
+ const int size = C->imax - C->imin;
+ int i, j, k;
+
+ for (i = 0 ; i < size ; i++)
+ for (j = 0 ; j < size ; j++)
+ for (k = 0 ; k < size ; k++)
+ MAT_IJ(C, i, j) += MAT_IJ(A, i, k) * MAT_IJ(B, k, j);
+}
+
+#define BLOCK_X_MID(block) ((block)->imin + (block)->imax) / 2
+#define BLOCK_Y_MID(block) ((block)->jmin + (block)->jmax) / 2
+
+#define MAKE_MBLOCK(newb, block, I, J) \
+ mblock newb = {.mat=(block)->mat};\
+ if ((I) == 0){\
+ newb.imin = (block)->imin;\
+ newb.imax = BLOCK_X_MID((block));\
+ } else {\
+ newb.imin = BLOCK_X_MID((block));\
+ newb.imax = (block)->imax;\
+ } if ((J) == 0){\
+ newb.jmin = (block)->jmin;\
+ newb.jmax = BLOCK_Y_MID((block));\
+ } else {\
+ newb.jmin = BLOCK_Y_MID((block));\
+ newb.jmax = (block)->jmax;\
+ }
+
+void divac_part(mblock *C, const mblock *A, const mblock *B);
+
+void divac_wrap(mblock *C , char IC, char JC,
+ const mblock *A, char IA, char JA,
+ const mblock *B, char IB, char JB){
+ MAKE_MBLOCK(Cb, C, IC, JC);
+ MAKE_MBLOCK(Ab, A, IA, JA);
+ MAKE_MBLOCK(Bb, B, IB, JB);
+
+ divac_part(&Cb, &Ab, &Bb);
+}
+
+
+void divac_part(mblock *C, const mblock *A, const mblock *B){
+ const int size = C->imax - C->imin;
+
+ if (size % 2 == 1)
+ divac_mul(C, A, B);
+ else{
+ /* C_00 = A_00 B_00 + A_01 B_10 */
+ divac_wrap(C, 0, 0, A, 0, 0, B, 0, 0);
+ divac_wrap(C, 0, 0, A, 0, 1, B, 1, 0);
+
+ /* C_10 = A_10 B_00 + A_11 B_10 */
+ divac_wrap(C, 1, 0, A, 1, 0, B, 0, 0);
+ divac_wrap(C, 1, 0, A, 1, 1, B, 1, 0);
+
+ /* C_01 = A_00 B_01 + A_01 B_11 */
+ divac_wrap(C, 0, 1, A, 0, 0, B, 0, 1);
+ divac_wrap(C, 0, 1, A, 0, 1, B, 1, 1);
+
+ /* C_11 = A_10 B_01 + A_11 B_11 */
+ divac_wrap(C, 1, 1, A, 1, 0, B, 0, 1);
+ divac_wrap(C, 1, 1, A, 1, 1, B, 1, 1);
+ }
+
+}
+
+void mmult_divac(uint64_t C[][SIZE], uint64_t A[][SIZE], uint64_t B[][SIZE]){
+ mblock Cb = {.mat = (uint64_t *) C, .imin = 0, .imax = SIZE, .jmin = 0, .jmax = SIZE};
+ mblock Ab = {.mat = (uint64_t *) A , .imin = 0, .imax = SIZE, .jmin = 0, .jmax = SIZE};
+ mblock Bb = {.mat = (uint64_t *) B , .imin = 0, .imax = SIZE, .jmin = 0, .jmax = SIZE};
+
+ divac_part(&Cb, &Ab, &Bb);
+}
+
+#ifdef __UNIT_TEST_MMULT__
+static uint64_t C1[SIZE][SIZE], C2[SIZE][SIZE], C3[SIZE][SIZE];
+static uint64_t A[SIZE][SIZE], B[SIZE][SIZE];
+
+int main(void){
+ srand(42);
+ int i, j;
+
+ for (i = 0 ; i < SIZE ; i++)
+ for (j = 0 ; j < SIZE ; j++){
+ A[i][j] = randlong();
+ B[i][j] = randlong();
+ }
+
+ mmult_row(C1, A, B);
+ mmult_col(C2, A, B);
+ mmult_divac(C3, A, B);
+
+ for (i = 0 ; i < SIZE ; i++)
+ for (j = 0 ; j < SIZE ; j++)
+ if (!(C1[i][j] == C2[i][j] && C1[i][j] == C3[i][j]))
+ return -1;
+
+ return 0;
+}
+#endif /* __UNIT_TEST_MMULT__ */
diff --git a/test/kvx/mmult/mmult.h b/test/kvx/mmult/mmult.h
new file mode 100644
index 00000000..3721784a
--- /dev/null
+++ b/test/kvx/mmult/mmult.h
@@ -0,0 +1,10 @@
+#ifndef __MMULT_H__
+#define __MMULT_H__
+
+#include "../lib/types.h"
+
+void mmult_row(uint64_t *A, const uint64_t *B, const uint64_t *C);
+void mmult_column(uint64_t *A, const uint64_t *B, const uint64_t *C);
+void mmult_strassen(uint64_t *A, const uint64_t *B, const uint64_t *C);
+
+#endif /* __MMULT_H__ */