[Cbe-oss-dev] [PATCH 2/3] libspe2: Add test framework
Kazunori Asayama
asayama at sm.sony.co.jp
Wed Mar 26 19:28:42 EST 2008
This patch adds test framework as following:
- modify Makefile to make it easy to add and run tests
- add common test utilities
- modify existing tests to use the framework
Signed-off-by: Kazunori Asayama <asayama at sm.sony.co.jp>
---
Makefile | 8 +
make.defines | 1
tests/Makefile | 256 ++++++++++++++++++++++++++++++++++++--------
tests/README | 193 +++++++++++++++++++++++++++++++++
tests/common_libspe2_test.h | 61 ++++++++++
tests/ppu_file.c | 119 ++++++++++++++++++++
tests/ppu_libspe2_test.h | 168 ++++++++++++++++++++++++++++
tests/ppu_main.c | 105 ++++++++++++++++++
tests/ppu_misc.c | 60 ++++++++++
tests/ppu_result.c | 213 ++++++++++++++++++++++++++++++++++++
tests/ppu_thread.c | 141 ++++++++++++++++++++++++
tests/spu_libspe2_test.h | 81 +++++++++++++
tests/testevent1.c | 2
tests/testevent2.c | 2
tests/testinfo.c | 2
tests/testlibspe2.c | 2
tests/testmap1.c | 2
tests/testmbox.c | 2
tests/testpthread.c | 2
tests/testpthreadmini.c | 4
tests/testsingle.c | 2
tests/testsinglemini.c | 4
22 files changed, 1374 insertions(+), 56 deletions(-)
Index: b/Makefile
===================================================================
--- a/Makefile 2008-03-26 15:32:18.000000000 +0900
+++ b/Makefile 2008-03-26 15:32:32.000000000 +0900
@@ -92,7 +92,7 @@ elfspe-install:
libspe12-install:
$(MAKE) -C libspe12 install
-tests: tests/Makefile
+tests: all
make -C tests
ada : ada/Makefile
@@ -229,7 +229,11 @@ tests-clean:
$(MAKE) -C tests clean
distclean: clean
+ $(MAKE) -C tests distclean
rm -rf latex
rm -rf html
-.PHONY: all clean tests tags
+check: tests
+ $(MAKE) -C tests -s check
+
+.PHONY: all clean check tests tags
Index: b/make.defines
===================================================================
--- a/make.defines 2008-03-26 15:32:18.000000000 +0900
+++ b/make.defines 2008-03-26 15:32:32.000000000 +0900
@@ -118,6 +118,7 @@ libspe2_SONAME := libspe2.so.${MAJOR_VER
CC := ${CROSS}gcc
+EMBEDSPU := $(CROSS)embedspu
CTAGS := ctags
CFLAGS := -O2 -Wall -I. -fPIC -I$(TOP)/include -fexceptions -std=gnu99 \
Index: b/tests/Makefile
===================================================================
--- a/tests/Makefile 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/Makefile 2008-03-26 15:32:32.000000000 +0900
@@ -1,56 +1,222 @@
-#*
-#* libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
-#* Copyright (C) 2005 IBM Corp.
-#*
-#* This library is free software; you can redistribute it and/or modify it
-#* under the terms of the GNU Lesser General Public License as published by
-#* the Free Software Foundation; either version 2.1 of the License,
-#* or (at your option) any later version.
-#*
-#* This library is distributed in the hope that it will be useful, but
-#* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-#* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-#* License for more details.
-#*
-#* You should have received a copy of the GNU Lesser General Public License
-#* along with this library; if not, write to the Free Software Foundation,
-#* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#*
+#
+# libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+#
+# Copyright (C) 2008 Sony Computer Entertainment Inc.
+# Copyright 2007,2008 Sony Corp.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+#
-TOP=..
+TOP = ..
include $(TOP)/make.defines
-CFLAGS += -I$(TOP)/spebase
-CFLAGS += -I$(TOP) -g
-CFLAGS += $(TEST_CFLAGS)
-
-LDFLAGS := $(CFLAGS) $(TEST_LDFLAGS)
-LDLIBS := -L$(TOP) -lspe2 -lpthread
-
-ALL := testsingle testsinglemini hello hellointr\
- testmap1 \
- testpthread testpthreadmini \
- testlibspe2 testlibspe2hello \
- testinfo testhandler \
- testevent1 testevent2 \
- testmbox readmbox
-
-all: $(ALL)
-
-hello: helloworld.c
- $(SPU_CC) $(SPU_CFLAGS) -o hello helloworld.c
+# libspe2 directories
+LIBSPE2_INCLUDE = $(TOP)
+LIBSPE2_LIB = $(TOP)
-hellointr: hellointr.c
- $(SPU_CC) $(SPU_CFLAGS) -o hellointr hellointr.c
+# PPU toolchain
+CFLAGS += -g -I$(LIBSPE2_INCLUDE) -I$(LIBSPE2_INCLUDE)/spebase $(TEST_CFLAGS)
+LDFLAGS = $(CFLAGS) -L$(LIBSPE2_LIB) $(TEST_LDFLAGS) -lspe2 -lpthread
-readmbox: readmbox.c
- $(SPU_CC) $(SPU_CFLAGS) -o readmbox readmbox.c
+# SPU toolchain
+SPU_CFLAGS = -g -Wall -fno-builtin -Wno-format-zero-length
+SPU_LDFLAGS =
-testlibspe2hello: testlibspe2hello.c
- $(SPU_CC) $(SPU_CFLAGS) -o testlibspe2hello testlibspe2hello.c
+# test paramegers
+TEST_ITERATION = 1
+TEST_VERBOSE = 0
+TEST_SPES = 4
+# list of test sets
+test_sets = regular basic extra
+
+
+# Main PPE programs (test cases)
+regular_main_progs = \
+ $(basic_main_progs)
+
+basic_main_progs = \
+ testsingle.elf \
+ testsinglemini.elf \
+ testpthread.elf \
+ testpthreadmini.elf \
+ testlibspe2.elf \
+ testinfo.elf \
+ testhandler.elf \
+ testevent1.elf \
+ testevent2.elf \
+ testmbox.elf
+
+extra_main_progs = \
+ testmap1.elf
+
+# Additional PPE programs
+ppu_progs =
+
+# External SPE programs
+basic_spu_progs = \
+ helloworld.spu.elf \
+ hellointr.spu.elf \
+ testlibspe2hello.spu.elf \
+ readmbox.spu.elf
+
+# Additional SPE programs
+spu_progs =
+
+
+# utility routines
+ppu_utils = ppu_main.o ppu_file.o ppu_misc.o ppu_result.o ppu_thread.o
+
+# all test cases
+all_main_progs = $(regular_main_progs) $(extra_main_progs)
+
+# add extra programs for each test case to the test set.
+$(foreach case,$(all_main_progs),$(eval ppu_progs += $($(case)_ppu_progs)))
+$(foreach case,$(all_main_progs),$(eval spu_progs += $($(case)_spu_progs)))
+
+# list of all programs
+$(foreach set,$(test_sets),$(eval ppu_progs += $($(set)_main_progs) $($(set)_ppu_progs)))
+$(foreach set,$(test_sets),$(eval spu_progs += $($(set)_spu_progs)))
+
+
+# list of ELFs
+ppu_elfs = $(filter %.elf,$(ppu_progs))
+spu_elfs = $(filter %.elf,$(spu_progs))
+
+
+# 'all' test set
+test_sets := all $(test_sets)
+
+
+# lists of test items corresponding to test sets.
+# (automatically generated from lists of programs above)
+$(foreach set,$(test_sets), \
+ $(eval $(set)_tests = $(patsubst %,check-%,$($(set)_main_progs))))
+
+all_checks = $(patsubst %,check-%,$(test_sets))
+
+
+# rules
+%.spu.elf: %.spu.o
+ $(SPU_CC) $(filter %.spu.o,$^) -o $@ $(SPU_LDFLAGS)
+
+%.spu.o: %.c
+ $(SPU_CC) $(SPU_CFLAGS) -c $< -o $@
+
+%.elf: %.o
+ $(CC) $(filter %.o,$^) -o $@ $(LDFLAGS)
+
+%.embed.o: %.spu.elf
+ $(EMBEDSPU) $(ARCH_CFLAGS) $(subst .,_,$(subst -,_,$*)) $< $@
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+
+.PHONY: all check clean distclean help
+.PHONY: $(all_checks) $(all_tests)
+
+all: $(ppu_progs) $(spu_progs)
+
+check: check-regular
+
+$(all_checks):
+ @failed=""; \
+ for p in $($(subst -,_,$(patsubst check-%,%,$@))_tests); \
+ do \
+ $(MAKE) -s $$p || failed="$$failed $$p"; \
+ done; \
+ echo >&2; \
+ if [ -n "$$failed" ]; then \
+ echo "FAIL: $$failed" >&2; exit 1; \
+ else \
+ echo "PASS" >&2; \
+ fi
+
+$(all_tests): check-%: %
+ @[ -n "$(LIBSPE2_LIB)" ] && export LD_LIBRARY_PATH='$(LIBSPE2_LIB)'; \
+ prog=./$(patsubst check-%,%,$@); \
+ opts=" -n $(TEST_ITERATION) -s $(TEST_SPES)"; \
+ [ "$(TEST_VERBOSE)" != 0 ] && opts="$$opts -v"; \
+ echo "$$prog: RUNNING"; \
+ $$prog $$opts || failed="1"; \
+ if [ "$$failed" = 1 ]; then \
+ echo "$$prog: FAIL" >&2; exit 1; \
+ else \
+ echo "$$prog: PASS" >&2; \
+ fi
+
+# additional dependencies
+$(foreach set, $(test_sets), \
+ $(eval $($(set)_tests): $($(set)_ppu_progs) $($(set)_spu_progs)))
+$(foreach case,$(all_main_progs), \
+ $(eval $(case): $($(case)_ppu_progs) $($(case)_spu_progs)))
clean:
- rm -f $(ALL)
+ -$(RM) *.elf *.o *.tmp
+
+distclean: clean
+ -$(RM) *~
+
+help:
+ @echo; \
+ echo "Syntax:"; \
+ echo " $$ $(MAKE) [<TEST-PARAMETERS>] [<TEST-CASE-OR-TEST-SET>]"; \
+ echo; \
+ echo "Examples:"; \
+ echo " $$ $(MAKE) check"; \
+ echo " $$ $(MAKE) ARCH=ppc64 check"; \
+ echo; \
+ echo "Test parameters:"; \
+ echo " CROSS=<ppu-toolchain> Prefix of PPU toolchain. (default: $(CROSS))"; \
+ echo " SPU_CROSS=<spu-toolchain> Prefix of SPU toolchain. (default: $(SPU_CROSS))"; \
+ echo " ARCH=<ppc-or-ppc64> Whether libspe2 is 32-bit or 64-bit. (default: $(ARCH))"; \
+ echo " LIBSPE2_INCLUDE=<dir> Use header files in the directory <dir>. (default: $(LIBSPE2_INCLUDE))"; \
+ echo " LIBSPE2_LIB=<dir> Use library files in the directory <dir>. (default: $(LIBSPE2_LIB))"; \
+ echo " TEST_STATIC=1 Use static libraries instead of shared libraries."; \
+ echo " TEST_SPES=<n> Number of SPEs to be used. (default: $(TEST_SPES))"; \
+ echo " Some tests may ignore this parameter."; \
+ echo " TEST_ITERATION=<n> Run each test <n> times repeatedly (default: $(TEST_ITERATION))."; \
+ echo " Some tests may ignore this parameter."; \
+ echo " TEST_VERBOSE=1 Display many information while testing."; \
+ echo; \
+ echo "Test sets:"; \
+ echo " check Same as 'check-regular'."; \
+ for t in $(test_sets); \
+ do \
+ echo " check-$$t"; \
+ done; \
+ echo; \
+ echo "Individual test cases (included in the regular test set)"; \
+ for t in $(regular_tests); \
+ do \
+ echo " $$t"; \
+ done; \
+ echo; \
+ echo "Individual test cases (not included in the regular test set)"; \
+ for t in $(extra_tests); \
+ do \
+ echo " $$t"; \
+ done
+
+
+# dependencies between PPU code
+$(ppu_elfs:.elf=.o) $(ppu_utils): ppu_libspe2_test.h common_libspe2_test.h
+
+$(ppu_elfs): $(ppu_utils)
+# dependencies between SPU code
+$(spu_elfs:.spu.elf=.spu.o) $(spu_elfs): spu_libspe2_test.h common_libspe2_test.h
Index: b/tests/common_libspe2_test.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/common_libspe2_test.h 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,61 @@
+/*
+ * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ * Copyright (C) 2008 Sony Computer Entertainment Inc.
+ * Copyright 2007,2008 Sony Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This file provides common definitions and declarations shared
+ * between PPE and SPEs.
+ */
+
+#ifndef __COMMON_LIBSPE2_TEST_H
+#define __COMMON_LIBSPE2_TEST_H
+
+#include <assert.h>
+
+/*** configurations ***/
+
+
+/*** test parameters ***/
+#define MAX_SPES 64
+#define DEFAULT_NUM_SPES 4
+
+
+/*** limits ***/
+#define MAX_DUMMY_FDS 10000
+
+
+/*** utilities ***/
+#define ASSERT(e) assert(e)
+
+
+/*** structure to be used to record information about error in SPE
+ * test code. In the C99 handler's test cases, we can't use SPE's
+ * 'printf' function to report errors because a part of the function
+ * is implemented in the C99 handler itself. :-) So we report errors
+ * via LS by using this structure in such cases.
+ ***/
+typedef struct spe_error_info
+{
+ unsigned int code;
+ unsigned int file;
+ unsigned int line;
+ unsigned int err; /* errno */
+} spe_error_info_t;
+
+#endif /* __COMMON_LIBSPE2_TEST_H */
Index: b/tests/ppu_file.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_file.c 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,119 @@
+/*
+ * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ * Copyright (C) 2008 Sony Computer Entertainment Inc.
+ * Copyright 2008 Sony Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "ppu_libspe2_test.h"
+
+
+/*** SPUFS direct access ***/
+int spufs_open(const spe_context_ptr_t spe, const char *name, int mode)
+{
+ char node[256];
+
+ sprintf(node, "/spu/spethread-%lu-%lu/%s",
+ (unsigned long)getpid(), (unsigned long)spe, name);
+ return open(node, mode);
+}
+
+/*** consuming FDs ***/
+#define DUMMY_FD_FILE "/dev/null"
+static int g_num_dummy_fd = 0;
+static int g_dummy_fd[MAX_DUMMY_FDS];
+
+int dummy_file_open(int num)
+{
+ if (num > MAX_DUMMY_FDS) {
+ eprintf("No more room for dummy FDs.\n");
+ return -1;
+ }
+
+ /* open specified number of FDs. */
+ while (g_num_dummy_fd < num) {
+ int fd;
+ fd = open(DUMMY_FD_FILE, O_RDONLY);
+ if (fd == -1) {
+ perror("open(" DUMMY_FD_FILE ")");
+ return -1;
+ }
+ g_dummy_fd[g_num_dummy_fd++] = fd;
+ }
+
+ return 0;
+}
+
+int dummy_file_open_r(int num)
+{
+ /* open files as many as possible */
+ while (1) {
+ int fd;
+ fd = open(DUMMY_FD_FILE, O_RDONLY);
+ if (fd == -1) {
+ if (errno == EMFILE) {
+ break;
+ }
+ else {
+ perror("open(" DUMMY_FD_FILE ")");
+ return -1;
+ }
+ }
+ if (g_num_dummy_fd >= MAX_DUMMY_FDS) {
+ close(fd);
+ eprintf("No more room for dummy FDs.\n");
+ return -1;
+ }
+ g_dummy_fd[g_num_dummy_fd++] = fd;
+ }
+
+ /* close specified number of FDs. */
+ while (num-- > 0) {
+ g_num_dummy_fd--;
+
+ close(g_dummy_fd[g_num_dummy_fd]);
+ }
+
+ return 0;
+}
+
+/* close all dummy files */
+void dummy_file_close(void)
+{
+ int i;
+ for (i = 0; i < g_num_dummy_fd; i++) {
+ close(g_dummy_fd[i]);
+ }
+ g_num_dummy_fd = 0;
+}
+
+int tmpfile_open(char *name, const char *base)
+{
+ static int serial = 0;
+ static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+ pthread_mutex_lock(&lock);
+ sprintf(name, "%s-%lu.%u.tmp", base, (unsigned long)getpid(), serial++);
+ pthread_mutex_unlock(&lock);
+
+ return open(name, O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+}
Index: b/tests/ppu_libspe2_test.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_libspe2_test.h 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,168 @@
+/*
+ * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ * Copyright (C) 2008 Sony Computer Entertainment Inc.
+ * Copyright 2007,2008 Sony Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This file provides definitions and declarations used by PPE. */
+
+#ifndef __PPU_LIBSPE2_TEST_H
+#define __PPU_LIBSPE2_TEST_H
+
+#include "common_libspe2_test.h"
+
+#include <libspe2.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*** main routine of the test ***/
+extern int ppu_main(int argc, char **argv, int (*test_proc)(int targc, char **targv));
+
+
+/*** parameters ***/
+/* # of SPEs to be used (some tests ignore this value) */
+extern int NUM_SPES;
+
+
+/*** error handling and messages ***/
+/* counter to manage number of errors */
+extern int g_failed;
+/* increment the # of errors */
+#define failed() (++g_failed, eprintf("Error.\n"))
+/* report error and exit immediately */
+#define fatal() do { failed(); check_failed(); } while (0)
+/* check whether any errors have occured and exit immediately if any. */
+#define check_failed() do { if (g_failed) { exit(1); } } while (0)
+
+/* check if the content of spe_stop_info_t structure has an expected
+ value */
+#define check_stop_info(stop_info, expected) \
+ check_stop_info_helper(__FILE__, __LINE__, stop_info, expected)
+extern int check_stop_info_helper(const char *filename, int line,
+ const spe_stop_info_t *stop_info,
+ const spe_stop_info_t *expected);
+/* check if the stop reason is SPE_EXIT and the exit code is an
+ expected value. */
+#define check_exit_code(stop_info, expected) \
+ check_exit_code_helper(__FILE__, __LINE__, stop_info, expected)
+extern int check_exit_code_helper(const char *filename, int line,
+ const spe_stop_info_t *stop_info,
+ int expected);
+
+/*
+ * Translating the beginning of the LS as spe_error_info_t structure,
+ * and displays the contents of the structure. This function is
+ * intended to be used in order to print errors on SPE when SPE's
+ * printf is unavailable or unreliable, e.g. while testing printf.
+ */
+extern void print_spe_error_info(spe_context_ptr_t spe);
+
+/* print messages */
+extern int g_verbose_p;
+#define lmessage(f, n, ...) (fprintf(stderr, "%s:%d: ", f, n), fprintf(stderr, __VA_ARGS__))
+#define message(...) lmessage(__FILE__, __LINE__, __VA_ARGS__)
+#define leprintf(...) lmessage(__VA_ARGS__)
+#define eprintf(...) message(__VA_ARGS__)
+#define ltprintf(...) ((void)(g_verbose_p && lmessage(__VA_ARGS__)))
+#define tprintf(...) ((void)(g_verbose_p && message(__VA_ARGS__)))
+
+/* convert enum values into human readable strings */
+extern const char *mbox_behavior_symbol(unsigned int behavior);
+extern const char *proxy_dma_behavior_symbol(unsigned int behavior);
+extern const char *stop_reason_symbol(unsigned int reason);
+extern const char *runtime_error_symbol(unsigned int error);
+extern const char *runtime_exception_symbol(unsigned int exception);
+
+
+/*** file operations ***/
+/* waste file descriptor resource */
+extern int dummy_file_open(int num);
+extern int dummy_file_open_r(int num);
+extern void dummy_file_close(void);
+
+/* generate a unique temporary filename and open it. */
+extern int tmpfile_open(char *name /* at leas 256 bytes */, const char *base);
+
+/* SPUFS direct access.
+ This function is provided only for test purpose.
+ It must *NOT* be used by applications.
+ */
+extern int spufs_open(const spe_context_ptr_t spe, const char *name, int mode);
+
+
+/*** test data ***/
+/* returns a 32-bit random data */
+extern unsigned int rand32(void);
+/* fill buffer with test data
+ *
+ * index and size must be a product of 4.
+ */
+extern void generate_data(void *ptr, unsigned int idx, size_t size);
+
+
+/*** time base ***/
+extern unsigned int get_timebase_frequency(void);
+
+
+/*** barrier ***/
+typedef struct barrier
+{
+ int counter;
+ int done;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+} barrier_t;
+
+#define BARRIER_INITIALIZER { \
+ .counter = 0, .done = 0, \
+ .mutex = PTHREAD_MUTEX_INITIALIZER, \
+ .cond = PTHREAD_COND_INITIALIZER, \
+ }
+
+extern void barrier_initialize(barrier_t *counter);
+extern void barrier_finalize(barrier_t *counter);
+extern void barrier_sync(barrier_t *counter, int thread_count);
+
+extern void global_sync(int thread_count);
+
+
+/*** multi-threading helpers ***/
+typedef struct ppe_thread ppe_thread_t;
+typedef struct ppe_thread_group
+{
+ ppe_thread_t *threads;
+ int nr_threads;
+ void *data; /* application data */
+} ppe_thread_group_t;
+struct ppe_thread
+{
+ int index;
+ pthread_t thread;
+ ppe_thread_group_t *group;
+};
+/* non-blocking I/F */
+extern ppe_thread_group_t *
+ppe_thread_group_create(size_t num_threads, void *(*proc)(void *), void *data);
+extern int ppe_thread_group_wait(ppe_thread_group_t *group, void **exit_codes);
+/* blocking I/F */
+extern int ppe_thread_group_run(size_t num_threads, void *(*proc)(void *), void *data,
+ void **exit_codes);
+
+#endif /* __PPU_LIBSPE2_TEST_H */
Index: b/tests/ppu_main.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_main.c 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,105 @@
+/*
+ * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ * Copyright (C) 2008 Sony Computer Entertainment Inc.
+ * Copyright 2007,2008 Sony Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ppu_libspe2_test.h"
+
+#define PROGRESS_STEP 1000
+
+int NUM_SPES = DEFAULT_NUM_SPES;
+int g_verbose_p = 0;
+int g_failed;
+
+static void usage(const char *prog)
+{
+ eprintf("Usage: %s [<options>] [--] [<arguments>]\n"
+ "Options:\n"
+ " -h print this message\n"
+ " -n <iteration> repeat test <iteration> times\n"
+ " -s <SPEs> # of SPEs\n"
+ " -v verbose mode\n"
+ " -q quiet mode\n"
+ , prog);
+}
+
+int ppu_main(int argc, char **argv, int (*test_proc)(int targc, char **targv))
+{
+ long long i, iteration = 1;
+ char *str;
+ int c;
+
+ /* parse command line options */
+ while ((c = getopt(argc, argv, "hn:vqs:")) != -1) {
+ switch (c) {
+ case 'h':
+ usage(argv[0]);
+ return 0;
+ case 'n':
+ iteration = strtoll(optarg, &str, 0);
+ if (*str) {
+ usage(argv[0]);
+ return 1;
+ }
+ break;
+ case 's':
+ NUM_SPES = strtol(optarg, &str, 0);
+ if (*str) {
+ usage(argv[0]);
+ return 1;
+ }
+ if (NUM_SPES > MAX_SPES) {
+ eprintf("Too many SPEs\n");
+ return 1;
+ }
+ break;
+ case 'v':
+ g_verbose_p = 1;
+ break;
+ case 'q':
+ g_verbose_p = 0;
+ break;
+ default:
+ usage(argv[0]);
+ return 1;
+ }
+ }
+
+ argv[optind - 1] = argv[0]; /* pass argv[0] as the first parameter of test() */
+
+ /* run main test routine in 'iteration' times */
+ for (i = 0; iteration < 0 || i != iteration; i++) {
+ if (i % PROGRESS_STEP == 0) {
+ tprintf("[%lld/%lld]\n", i, iteration);
+ }
+ if ((*test_proc)(argc - optind + 1, argv + optind - 1)) {
+ return 1;
+ }
+ check_failed();
+ }
+
+ tprintf("done\n");
+
+ return 0;
+}
Index: b/tests/ppu_misc.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_misc.c 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,60 @@
+/*
+ * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ * Copyright (C) 2008 Sony Computer Entertainment Inc.
+ * Copyright 2008 Sony Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "ppu_libspe2_test.h"
+
+void generate_data(void *data, unsigned int idx, size_t size)
+{
+ /* index and size must be a product of 4 */
+ unsigned int *ptr = data;
+ unsigned int *end = data + size;
+ unsigned int value = idx / 4;
+
+ while (ptr < end) {
+ *ptr++ = value++;
+ }
+}
+
+unsigned int rand32(void)
+{
+ return rand() ^ (rand() << 16);
+}
+
+unsigned int get_timebase_frequency(void)
+{
+ const char *filename = "/proc/cpuinfo";
+ char buf[256];
+ FILE *fp;
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ return -1;
+ }
+ while (fgets(buf, sizeof(buf), fp)) {
+ unsigned long long tb;
+ if (sscanf(buf, "timebase%*[ \t]:%llu\n", &tb) == 1) {
+ fclose(fp);
+ return tb;
+ }
+ }
+ fclose(fp);
+ return 0;
+}
Index: b/tests/ppu_result.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_result.c 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,213 @@
+/*
+ * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ * Copyright (C) 2008 Sony Computer Entertainment Inc.
+ * Copyright 2008 Sony Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+
+#include "ppu_libspe2_test.h"
+
+
+/*** checking results and/or printing information ***/
+int check_stop_info_helper(const char *filename, int line,
+ const spe_stop_info_t *stop_info,
+ const spe_stop_info_t *expected)
+{
+ if (stop_info->stop_reason != expected->stop_reason) {
+ leprintf(filename, line,
+ "Unexpected reason: %s (%d)\n",
+ stop_reason_symbol(stop_info->stop_reason), stop_info->stop_reason);
+ return 1;
+ }
+
+ switch (stop_info->stop_reason) {
+ case SPE_EXIT:
+ if (stop_info->result.spe_exit_code != expected->result.spe_exit_code) {
+ leprintf(filename, line,
+ "Unexpected exit code: %u (0x%x)\n",
+ stop_info->result.spe_exit_code, stop_info->result.spe_exit_code);
+ return 1;
+ }
+ break;
+ case SPE_STOP_AND_SIGNAL:
+ if (stop_info->result.spe_signal_code != expected->result.spe_signal_code) {
+ leprintf(filename, line,
+ "Unexpected signal code: 0x%x\n", stop_info->result.spe_signal_code);
+ return 1;
+ }
+ break;
+ case SPE_RUNTIME_ERROR:
+ if (stop_info->result.spe_runtime_error != expected->result.spe_runtime_error) {
+ leprintf(filename, line,
+ "Unexpected runtime error: 0x%x (%s)\n",
+ stop_info->result.spe_runtime_error,
+ runtime_error_symbol(stop_info->result.spe_runtime_error));
+ return 1;
+ }
+ break;
+ case SPE_RUNTIME_FATAL:
+ if (stop_info->result.spe_runtime_fatal != expected->result.spe_runtime_fatal) {
+ leprintf(filename, line,
+ "Unexpected errno: %d (%s)\n",
+ stop_info->result.spe_runtime_fatal,
+ strerror(stop_info->result.spe_runtime_fatal));
+ return 1;
+ }
+ break;
+ case SPE_RUNTIME_EXCEPTION:
+ if (stop_info->result.spe_runtime_exception != expected->result.spe_runtime_exception) {
+ leprintf(filename, line,
+ "Unexpected runtime exception: 0x%x (%s)\n",
+ stop_info->result.spe_runtime_exception,
+ runtime_exception_symbol(stop_info->result.spe_runtime_exception));
+ return 1;
+ }
+ break;
+ case SPE_CALLBACK_ERROR:
+ if (stop_info->result.spe_callback_error != expected->result.spe_callback_error) {
+ leprintf(filename, line,
+ "Unexpected callback error: 0x%x\n", stop_info->result.spe_callback_error);
+ return 1;
+ }
+ break;
+ case SPE_ISOLATION_ERROR:
+ if (stop_info->result.spe_isolation_error != expected->result.spe_isolation_error) {
+ leprintf(filename, line,
+ "Unexpected isolation error: 0x%x\n", stop_info->result.spe_isolation_error);
+ return 1;
+ }
+ break;
+ default:
+ leprintf(filename, line,
+ "Unknown stop reason: %d\n", stop_info->stop_reason);
+ return 1;
+ }
+
+ return 0;
+}
+
+int check_exit_code_helper(const char *filename, int line,
+ const spe_stop_info_t *stop_info, int expected_code)
+{
+ spe_stop_info_t expected;
+
+ expected.stop_reason = SPE_EXIT;
+ expected.result.spe_exit_code = expected_code;
+
+ return check_stop_info_helper(filename, line, stop_info, &expected);
+}
+
+void print_spe_error_info(spe_context_ptr_t spe)
+{
+ const void *ls = spe_ls_area_get(spe);
+ const spe_error_info_t *err = (const spe_error_info_t *)ls;
+ if (!err) {
+ tprintf("Could not get LS address. Ignored.\n");
+ return;
+ }
+ fprintf(stderr, "%s:%d: Error in SPE. exit code == %d, errno == %d.\n",
+ (const char *)ls + err->file, err->line, err->code, err->err);
+}
+
+/*** get human readable strings corresponding to symbols ***/
+const char *mbox_behavior_symbol(unsigned int behavior)
+{
+ switch (behavior) {
+ case SPE_MBOX_ALL_BLOCKING:
+ return "SPE_MBOX_ALL_BLOCKING";
+ case SPE_MBOX_ANY_BLOCKING:
+ return "SPE_MBOX_ANY_BLOCKING";
+ case SPE_MBOX_ANY_NONBLOCKING:
+ return "SPE_MBOX_ANY_NONBLOCKING";
+ default:
+ return "unknown";
+ }
+}
+
+const char *proxy_dma_behavior_symbol(unsigned int behavior)
+{
+ switch (behavior) {
+ case SPE_TAG_ANY:
+ return "SPE_TAG_ANY";
+ case SPE_TAG_ALL:
+ return "SPE_TAG_ALL";
+ case SPE_TAG_IMMEDIATE:
+ return "SPE_TAG_IMMEDIATE";
+ default:
+ return "unknown";
+ }
+}
+
+const char *stop_reason_symbol(unsigned int reason)
+{
+ switch (reason) {
+ case SPE_EXIT:
+ return "SPE_EXIT";
+ case SPE_STOP_AND_SIGNAL:
+ return "SPE_STOP_AND_SIGNAL";
+ case SPE_RUNTIME_ERROR:
+ return "SPE_RUNTIME_ERROR";
+ case SPE_RUNTIME_EXCEPTION:
+ return "SPE_RUNTIME_EXCEPTION";
+ case SPE_RUNTIME_FATAL:
+ return "SPE_RUNTIME_FATAL";
+ case SPE_CALLBACK_ERROR:
+ return "SPE_CALLBACK_ERROR";
+ case SPE_ISOLATION_ERROR:
+ return "SPE_ISOLATION_ERROR";
+ default:
+ return "unknown";
+ }
+}
+
+const char *runtime_error_symbol(unsigned int error)
+{
+ switch (error) {
+ case SPE_SPU_STOPPED_BY_STOP: /* INTERNAL USE ONLY */
+ return "SPE_SPU_STOPPED_BY_STOP";
+ case SPE_SPU_HALT:
+ return "SPE_SPU_HALT";
+ case SPE_SPU_WAITING_ON_CHANNEL: /* INTERNAL USE ONLY */
+ return "SPE_SPU_WAITING_ON_CHANNEL";
+ case SPE_SPU_SINGLE_STEP:
+ return "SPE_SPU_SINGLE_STEP";
+ case SPE_SPU_INVALID_INSTR:
+ return "SPE_SPU_INVALID_INSTR";
+ case SPE_SPU_INVALID_CHANNEL:
+ return "SPE_SPU_INVALID_CHANNEL";
+ default:
+ return "unknown";
+ }
+}
+
+const char *runtime_exception_symbol(unsigned int exception)
+{
+ switch (exception) {
+ case SPE_DMA_ALIGNMENT:
+ return "SPE_DMA_ALIGNMENT";
+ case SPE_DMA_SEGMENTATION:
+ return "SPE_DMA_SEGMENTATION";
+ case SPE_DMA_STORAGE:
+ return "SPE_DMA_STORAGE";
+ case SPE_INVALID_DMA:
+ return "SPE_INVALID_DMA";
+ default:
+ return "unknown";
+ }
+}
Index: b/tests/ppu_thread.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/ppu_thread.c 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,141 @@
+/*
+ * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ * Copyright (C) 2008 Sony Computer Entertainment Inc.
+ * Copyright 2008 Sony Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <string.h>
+
+#include "ppu_libspe2_test.h"
+
+
+/*** barriers ***/
+void barrier_initialize(barrier_t *barrier)
+{
+ barrier->counter = 0;
+ barrier->done = 0;
+ pthread_mutex_init(&barrier->mutex, 0);
+ pthread_cond_init(&barrier->cond, 0);
+}
+
+void barrier_finalize(barrier_t *barrier)
+{
+ pthread_cond_destroy(&barrier->cond);
+ pthread_mutex_destroy(&barrier->mutex);
+}
+
+void barrier_sync(barrier_t *barrier, int thread_count)
+{
+ pthread_mutex_lock(&barrier->mutex);
+
+ /* wait until all threads leave the previous sync point */
+ while (barrier->done) {
+ pthread_cond_wait(&barrier->cond, &barrier->mutex);
+ }
+
+ barrier->counter++;
+ if (barrier->counter == thread_count) {
+ /* this thread is the last one which comes to the sync point */
+ barrier->done = thread_count - 1;
+ barrier->counter = 0;
+ pthread_cond_broadcast(&barrier->cond);
+ }
+ else {
+ /* wait until all threads reach the sync point */
+ while (!barrier->done) {
+ pthread_cond_wait(&barrier->cond, &barrier->mutex);
+ }
+
+ ASSERT(barrier->counter == 0);
+
+ barrier->done--;
+ if (barrier->done == 0) {
+ /* this thread is the last one which leave the sync point */
+ pthread_cond_broadcast(&barrier->cond);
+ }
+ }
+
+ pthread_mutex_unlock(&barrier->mutex);
+}
+
+static barrier_t g_barrier = BARRIER_INITIALIZER;
+
+void global_sync(int thread_count)
+{
+ barrier_sync(&g_barrier, thread_count);
+}
+
+/*** multi-threading helpers ***/
+ppe_thread_group_t *ppe_thread_group_create(size_t num_threads,
+ void *(*proc)(void *), void *data)
+{
+ int i;
+ ppe_thread_group_t *group = malloc(sizeof(ppe_thread_group_t));
+ if (!group) {
+ eprintf("malloc: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ group->threads = calloc(num_threads, sizeof(ppe_thread_t));
+ if (!group->threads) {
+ eprintf("calloc: %s\n", strerror(errno));
+ free(group);
+ return NULL;
+ }
+
+ group->data = data;
+ group->nr_threads = num_threads;
+
+ /* create PPU threads */
+ for (i = 0; i < num_threads; i++) {
+ int ret;
+ group->threads[i].index = i;
+ group->threads[i].group = group;
+ ret = pthread_create(&group->threads[i].thread, NULL, proc, group->threads + i);
+ if (ret) {
+ eprintf("pthread_create: %s\n", strerror(ret));
+ return NULL;
+ }
+ }
+
+ return group;
+}
+
+int ppe_thread_group_wait(ppe_thread_group_t *group, void **exit_codes)
+{
+ int i;
+
+ /* wait for all PPU threads */
+ for (i = 0; i < group->nr_threads; i++) {
+ pthread_join(group->threads[i].thread, exit_codes ? exit_codes + i : NULL);
+ }
+
+ free(group->threads);
+ free(group);
+
+ return 0;
+}
+
+int ppe_thread_group_run(size_t num_threads, void *(*proc)(void *), void *data,
+ void **exit_codes)
+{
+ ppe_thread_group_t *group = ppe_thread_group_create(num_threads, proc, data);
+ if (!group) return -1;
+
+ return ppe_thread_group_wait(group, exit_codes);
+}
Index: b/tests/spu_libspe2_test.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/spu_libspe2_test.h 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,81 @@
+/*
+ * libspe2 - A wrapper library to adapt the JSRE SPU usage model to SPUFS
+ *
+ * Copyright (C) 2008 Sony Computer Entertainment Inc.
+ * Copyright 2007,2008 Sony Corp.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This file provides definitions and declarations used by SPEs. */
+
+#ifndef __SPU_LIBSPE2_TEST_H
+#define __SPU_LIBSPE2_TEST_H
+
+#include "common_libspe2_test.h"
+
+#include <spu_intrinsics.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* Check if data is correct. It's expected that the source data is
+ * created by PPE's 'data_generate' function.
+ *
+ * idx must be a product of 4.
+ * size must be a product of 16.
+ */
+static inline int data_check(unsigned char *p, unsigned int idx, int size)
+{
+ vector unsigned int *pv = (vector unsigned int *)p;
+ vector unsigned int *pv_end = pv + (size >> 4);
+ unsigned int init = idx >> 2;
+ vector unsigned int values = { init, init + 1, init + 2, init + 3, };
+
+ while (pv < pv_end) {
+ if (spu_extract(spu_gather(spu_cmpeq(values, *pv)), 0) != 0xf) {
+ return 0;
+ }
+ values += spu_splats(4U);
+ pv++;
+ }
+ return 1;
+}
+
+/* Spin specified times. */
+static inline void spin(unsigned long long n)
+{
+ volatile unsigned long long i = n;
+ while (i-- > 0) {
+ /* dummy loop */
+ }
+}
+
+/*** To locate the g_spe_error_info at the fixed LS address so that
+ * the PPE code can access it easily, we define the variable in the
+ * ".interrupt" section, which always starts at '0'.
+ ***/
+#define DEFINE_SPE_ERROR_INFO \
+ volatile spe_error_info_t g_spe_error_info __attribute__((section(".interrupt")))
+#define DECLARE_SPE_ERROR_INFO extern volatile spe_error_info_t g_spe_error_info
+
+#define error_info_exit(n) do { \
+ g_spe_error_info.code = (n); \
+ g_spe_error_info.file = (unsigned int)__FILE__; \
+ g_spe_error_info.line = __LINE__; \
+ g_spe_error_info.err = errno; \
+ exit(n); \
+ } while (0)
+
+#endif /* __SPU_LIBSPE2_TEST_H */
Index: b/tests/README
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ b/tests/README 2008-03-26 15:32:32.000000000 +0900
@@ -0,0 +1,193 @@
+ libspe2 test suite
+
+
+1. Introduction
+
+ This is a suite of tests for the SPE runtime management library
+ version 2, aka libspe2. The major purposes of the tests are:
+
+ * function tests of libspe2
+ - checking if the implementation conforms to the spec or not.
+
+ * system tests of libspe2
+ - checking robustness.
+
+ * confirmation of libspe2's usage scenarios
+ - checking if the spec is reasonable or not.
+
+ and in addition to the aboves:
+
+ * system tests of SPUFS
+ - additional tests for SPUFS
+
+
+2. Requirements
+
+ * Hardware
+ - target machine (Cell/B.E. hardware)
+
+ * Runtime environment
+ - Linux kernel with SPUFS
+ - generic userland
+
+ * Software
+ - GNU make
+ - PowerPC or PPU GNU toolchain (gcc or ppu-gcc)
+ - SPU GNU toolchain (spu-gcc)
+ - libspe2 (target of this test suite)
+
+
+3. License
+
+ This test suite is licensed under the terms in the file 'COPYING' in
+ the top directory.
+
+
+4. Running tests
+
+ * To run regular tests, follow the steps below:
+
+ i. Login your target machine.
+
+ (ii. Build the library in the top directory.)
+
+ iii. Run 'make check' in this directory.
+
+ * You can run other tests rather than the regular tests, and also
+ can modify many of test parameters. Type "make help" for details.
+
+
+5. Evaluating results
+
+ * A result of each test is displayed as following:
+
+ <TEST_NAME>: <RESULT>
+
+ If a test passes, the value of <RESULT> is "PASS", otherwise
+ "FAIL".
+
+ * If all (specified) tests pass, a string "PASS" is displayed at
+ the end of output lines and the make command returns zero.
+
+ Otherwise, a string "FAIL" and a list of failed tests are
+ displayed, and the make command returns a non-zero value.
+
+
+6. Adding new test cases
+
+ * Test sets and test cases
+
+ This test suite consists of several test sets, which are groups
+ of test cases. You can add a new test case to the test suite by
+ appending it to one of the existing test sets. You also can
+ define a new test set in the test suite.
+
+ * Adding a new test case to a test set
+
+ To add a new test case to an existing test set, follow the steps
+ below:
+
+ i. Add the file name of the main PPU program of the new test case
+ to the macro '<test-set>_main_progs' in Makefile. The PPU
+ program can be either a script or an ELF executable.
+
+ - The file name is used as the name of the test case.
+
+ e.g.) If the file name is 'test_my_case.elf', the name of
+ the test case will be 'test_may_case.elf'.
+
+ - If the test passes, the main PPU program must return zero
+ to the system, otherwise must retun non-zero value.
+
+ - If your test case is an ELF executable, it must have the
+ suffix '.elf'.
+
+ e.g.) If your new test case is 'test_my_case.elf' and you want
+ to add it to the 'regular' test set, modify the macro
+ regular_main_progs in Makefile as:
+
+ regular_main_progs = \
+ test_my_case.elf \
+ ...
+
+ ii. If the new test case requires other external PPU executables,
+ add the file name of them to the macro
+ '<test-case>_ppu_progs'.
+
+ - The PPU ELF executables must have the suffix '.elf'.
+
+ - You can use '<test-set>_ppu_progs' macro instead of
+ '<test-case>_ppu_progs', if all test case in the test set
+ require the same external PPU executables.
+
+ e.g.) If the test case 'test_my_case.sh' requires an external
+ helper program 'test_my_case_helper.elf', add the following
+ definition to Makefile:
+
+ test_my_case.sh_ppu_progs = test_my_case_helper.elf
+
+ iii. If the new test case requires external SPU ELF executables,
+ i.e. if the test case load the SPU ELF executables by using
+ the spe_image_open API function, add the file name of them to
+ the macro '<test-case>_spu_progs'.
+
+ - The SPU executables must have the suffix '.spu.elf'.
+
+ - You can use '<test-set>_spu_progs' macro instead of
+ '<test-case>_spu_progs', if all test case in the test set
+ require the same external executables.
+
+ - It is unnecessary to add embeded SPU programs to the
+ macro (see the step iv).
+
+ iv. Add extra dependencies of the PPU and/or SPU ELF executables.
+
+ - The PPU object files must have the suffix '.o'.
+
+ - The SPU object files must have the suffix '.spu.o'.
+
+ - It is unnecessary to add the main object files which have
+ the same base name as the ELF executables to the extra
+ dependencies.
+
+ e.g.) If the added program is 'test_my_case.spu.elf',
+ you have no need to add 'test_my_case.spu.o' to the
+ dependency of 'test_my_case.spu.elf'.
+
+ - If you want to embed an SPU program into a PPE ELF
+ executable, all you must do is just adding the name of the
+ CESOF file which contains the SPE program to the dependency
+ of the PPE ELF executable.
+
+ o The CESOF files must have the suffix '.embed.o'.
+
+ o The embeded SPU programs can be accessed as
+ 'spe_program_handle_t <base-name>' by the PPE ELF
+ executable.
+
+ e.g.) If you want to embed an SPU ELF executable
+ 'spu_my_case.spu.elf' into the PPE ELF executable
+ 'test_my_case_embed.elf', the definition of the dependency
+ of test_my_case.elf must be:
+
+ test_my_case.elf: spu_my_case.embed.o
+
+ and the SPU program can be accessed as 'spe_program_handle_t
+ spu_my_case'.
+
+ v. Add sources and/or scripts of the test case to this directory.
+
+ - Sources of ELF executables must be written in C and must
+ have the suffix '.c'.
+
+ * Adding a new test set to the test suite
+
+ You can define a new test set to the test suite as following:
+
+ i. Add the name of the test set to the macro 'test_sets' in
+ Makefile.
+
+ ii. Add test cases to the new test set as above.
+
+---
+EOF
Index: b/tests/testevent1.c
===================================================================
--- a/tests/testevent1.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testevent1.c 2008-03-26 15:32:32.000000000 +0900
@@ -28,7 +28,7 @@ int main()
}
/* load the program. */
- program = spe_image_open("hello");
+ program = spe_image_open("helloworld.spu.elf");
if (!program) {
perror("spe_open_image");
return -1;
Index: b/tests/testevent2.c
===================================================================
--- a/tests/testevent2.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testevent2.c 2008-03-26 15:32:32.000000000 +0900
@@ -27,7 +27,7 @@ __attribute__((noreturn)) void * spe_thr
arg_ptr = (struct thread_args *) arg;
- program = spe_image_open("hellointr");
+ program = spe_image_open("hellointr.spu.elf");
if (!program) {
perror("spe_image_open");
pthread_exit(NULL);
Index: b/tests/testlibspe2.c
===================================================================
--- a/tests/testlibspe2.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testlibspe2.c 2008-03-26 15:32:32.000000000 +0900
@@ -33,7 +33,7 @@ int main(void)
}
printf("Invocation of spe_image_open, context=%p\n", context);
- if ((program = spe_image_open("testlibspe2hello")) == NULL) {
+ if ((program = spe_image_open("testlibspe2hello.spu.elf")) == NULL) {
fprintf(stderr,
"Invocation of spe_image_open FAILED, context=%p, errno=%d\n",
context, errno);
Index: b/tests/testmap1.c
===================================================================
--- a/tests/testmap1.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testmap1.c 2008-03-26 15:32:32.000000000 +0900
@@ -21,4 +21,6 @@ int main(void)
spe_context_destroy(ctx);
printf("%d done\n", status);
printf("%d done\n", MFC_LSA);
+
+ return 0;
}
Index: b/tests/testmbox.c
===================================================================
--- a/tests/testmbox.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testmbox.c 2008-03-26 15:32:32.000000000 +0900
@@ -29,7 +29,7 @@ __attribute__((noreturn)) void * spe_thr
arg_ptr = (struct thread_args *) arg;
- program = spe_image_open("readmbox");
+ program = spe_image_open("readmbox.spu.elf");
if (!program) {
perror("spe_image_open");
pthread_exit(NULL);
Index: b/tests/testpthread.c
===================================================================
--- a/tests/testpthread.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testpthread.c 2008-03-26 15:32:32.000000000 +0900
@@ -23,7 +23,7 @@ __attribute__((noreturn)) void * spe_thr
arg_ptr = (struct thread_args *) arg;
- program = spe_image_open("hello");
+ program = spe_image_open("helloworld.spu.elf");
if (!program) {
perror("spe_image_open");
pthread_exit(NULL);
Index: b/tests/testpthreadmini.c
===================================================================
--- a/tests/testpthreadmini.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testpthreadmini.c 2008-03-26 15:32:32.000000000 +0900
@@ -9,7 +9,7 @@ struct thread_args {
void * envp;
};
-void * spe_thread(void * arg)
+static void * spe_thread(void * arg)
{
int flags = 0;
unsigned int entry = SPE_DEFAULT_ENTRY;
@@ -18,7 +18,7 @@ void * spe_thread(void * arg)
arg_ptr = (struct thread_args *) arg;
- program = spe_image_open("hello");
+ program = spe_image_open("helloworld.spu.elf");
spe_program_load(arg_ptr->ctx, program);
spe_context_run(arg_ptr->ctx, &entry, flags, arg_ptr->argp, arg_ptr->envp, NULL);
pthread_exit(NULL);
Index: b/tests/testsingle.c
===================================================================
--- a/tests/testsingle.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testsingle.c 2008-03-26 15:32:32.000000000 +0900
@@ -14,7 +14,7 @@ int main(void)
spe_stop_info_t stop_info;
int rc;
- program = spe_image_open("hello");
+ program = spe_image_open("helloworld.spu.elf");
if (!program) {
perror("spe_open_image");
return -1;
Index: b/tests/testsinglemini.c
===================================================================
--- a/tests/testsinglemini.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testsinglemini.c 2008-03-26 15:32:32.000000000 +0900
@@ -11,11 +11,13 @@ int main()
void * envp = NULL;
spe_program_handle_t * program;
- program = spe_image_open("hello");
+ program = spe_image_open("helloworld.spu.elf");
ctx = spe_context_create(flags, 0);
spe_program_load(ctx, program);
spe_context_run(ctx, &entry, flags, argp, envp, NULL);
spe_context_destroy(ctx);
+
+ return 0;
}
Index: b/tests/testinfo.c
===================================================================
--- a/tests/testinfo.c 2008-03-26 15:32:18.000000000 +0900
+++ b/tests/testinfo.c 2008-03-26 15:32:32.000000000 +0900
@@ -21,5 +21,7 @@ int main(void)
no = spe_cpu_info_get(SPE_COUNT_USABLE_SPES, i);
printf("%2d ==> %d (%d)\n",i, no, errno);
}
+
+ return 0;
}
More information about the cbe-oss-dev
mailing list