diff --git a/GAISLER/Makefile b/GAISLER/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3c526c7c4cc68f696c0e50230edcf8361086e7d5 --- /dev/null +++ b/GAISLER/Makefile @@ -0,0 +1,156 @@ +# Configuration section +# +# Use environment variables if found, otherwise fallback to sane defaults + +# If not explicitely selected (with 'make FPU=1'), compile for FPU emulation +ifeq ($(FPU),) +FPU=0 +endif + +# To be able to properly handle any combination of (FPU, LEON, release) +# options, create a SUFFIX (see below) to differentiate output folders +ifeq ($(FPU),1) +FPU_SUFFIX=FPU +else +FPU_SUFFIX=NONFPU +endif + +# Build up our settings from our inputs and our environment +LEON ?= ngmp +CROSS_PREFIX ?= sparc-rtems +RTEMS ?= /opt/rtems-4.10 + +# If not selected, compile debug version of binary (no optimizations) +#ifeq ($(CFG),) +#CFG=debug +#endif + +# The directories containing the source files, separated by ':' +# +# DEAR USER, YOU MUST EDIT THIS AND ADD YOUR SOURCE FOLDERS +VPATH=src + +# Your source files: regardless of where they reside in the source tree, +# VPATH will locate them... +# +# DEAR USER, YOU MUST EDIT THIS +SRC= \ + init.c \ + task1.c \ + task2.c \ + common.c \ + memcheck.c + +SUFFIX=$(CFG).$(FPU_SUFFIX).$(LEON) + +# Build a Dependency list and an Object list, by replacing the .c +# extension to .d for dependency files, and .o for object files. +DEP = $(patsubst %.c, deps.$(SUFFIX)/%.d, ${SRC}) +OBJ = $(patsubst %.c, objs.$(SUFFIX)/%.o, ${SRC}) + +# Your final binary +# +# DEAR USER, YOU MUST EDIT THIS +TARGET=fputest + +# What compiler to use for generating dependencies: +# it will be invoked with -MM -MP +CC = ${RTEMS}/bin/${CROSS_PREFIX}-gcc +CDEP = ${CC} + +# What include flags to pass to the compiler +INCLUDEFLAGS= -I src + +COMMON += -qngmp -mcpu=v8 -Wall \ + -Wmissing-prototypes -Wimplicit-function-declaration \ + -Wstrict-prototypes -Wnested-externs + +# Separate compile options per configuration +ifeq ($(CFG),debug) +CFLAGS += ${COMMON} -g -Wall -D_DEBUG ${INCLUDEFLAGS} +else +CFLAGS += ${COMMON} -g -O2 -Wall ${INCLUDEFLAGS} +endif + +# Should we generate native FPU instructions for the SRC or not? +ifeq ($(FPU),0) +CFLAGS += -msoft-float +LDFLAGS += -msoft-float +endif + +# A common link flag for all configurations +LDFLAGS += ${COMMON} + +all: inform bin.$(SUFFIX)/${TARGET} + +inform: +ifneq ($(CFG),release) +ifneq ($(CFG),debug) + @echo " " + @echo "Invalid or missing configuration (CFG) "$(CFG)" specified." + @echo " " + @echo "You must specify a configuration when running make, e.g." + @echo " " + @echo " make CFG=debug LEON=leon3 FPU=1 V=1" + @echo " " + @echo "- Possible choices for CFG are 'release' and 'debug'" + @echo "- Possible choices for LEON are 'leon2' and 'leon3' (default)" + @echo "- Possible choices for FPU are '1' (native) and '0' (emulated) (default)" + @echo "- Possible choices for V are '1' (show commands) and '0' (silent) (default)" + @echo " " + @exit 1 +endif +endif + + +bin.$(SUFFIX)/${TARGET}: ${OBJ} | inform + @mkdir -p $(dir $@) +ifeq ($(V),1) + $(CC) -g -o $@ $^ ${LDFLAGS} +else + @echo [LD] $@ + @$(CC) -g -o $@ $^ ${LDFLAGS} +endif +ifeq ($(CFG),release) + @${RTEMS}/bin/${CROSS_PREFIX}-objcopy --only-keep-debug $@ ${@}.debug + @${RTEMS}/bin/${CROSS_PREFIX}-strip $@ +endif + @echo Built with RTEMS at ${RTEMS_LIB} for ${LEON}. + +objs.$(SUFFIX)/%.o: %.c | src/version.h + @mkdir -p $(dir $@) +ifeq ($(V),1) + $(CC) -c $(CFLAGS) -o $@ $< +else + @echo [CC] $@ + @$(CC) -c $(CFLAGS) -o $@ $< +endif + +deps.$(SUFFIX)/%.d: %.c + @mkdir -p $(dir $@) + @echo Generating dependencies for $< + @set -e ; $(CDEP) -MM -MP $(INCLUDEFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,objs.$(SUFFIX)\/\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +src/version.h: $(patsubst %, src/%, ${SRC}) Makefile + @/bin/echo -en '#ifndef __VERSION_H__\n' > $@ + @/bin/echo -en "#define __VERSION_H__\n" >> $@ + @/bin/echo -en 'const char version[] = "1.' >> $@ + @git log --oneline | wc -l | tr -d '\n' >> $@ + @/bin/echo -n " (" >> $@ + @git log --oneline | head -1 | cut -d\ -f1 | tr -d '\n' >> $@ + @/bin/echo ')";' >> $@ + @/bin/echo -en "#endif\n" >> $@ + +clean: + @rm -rf deps.* objs.* bin.* + +# Unless "make clean" is called, include the dependency files +# which are auto-generated. Don't fail if they are missing +# (-include), since they will be missing in the first invocation! +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(CFG),) +-include ${DEP} +endif +endif diff --git a/GAISLER/src/common.c b/GAISLER/src/common.c new file mode 100644 index 0000000000000000000000000000000000000000..5b865ba8edb89c48f788a0fccc39264817fe9887 --- /dev/null +++ b/GAISLER/src/common.c @@ -0,0 +1,15 @@ +#include "system.h" +#include + +void task_begin(int task_no) +{ + printf("[TASK %d] Starting...\n", task_no); + fflush(stdout); + +} + +void task_end(int task_no) +{ + rtems_event_send(g_init_task_id, RTEMS_EVENT_0 << task_no); + rtems_task_delete(RTEMS_SELF); +} diff --git a/GAISLER/src/init.c b/GAISLER/src/init.c new file mode 100644 index 0000000000000000000000000000000000000000..3434863d92a13db7a7bf43170adee0004398a9d3 --- /dev/null +++ b/GAISLER/src/init.c @@ -0,0 +1,83 @@ +/* + * Example initialization file - spawns 2 native FPU tasks + * + */ +#define CONFIGURE_INIT +#define TASKS 4 + +#define DEFINE_VARS +#include "system.h" + +#include +#include + +rtems_task Init(rtems_task_argument argument) +{ + rtems_status_code status; + rtems_name Task_name[TASKS]; /* task names */ + rtems_id Task_id[TASKS]; /* task ids */ + int i; + + memcheck(); + all_OK = 1; + g_init_task_id = rtems_task_self(); + for(i = 0; i < TASKS; i++) + { + // Initialize Task name + Task_name[i] = rtems_build_name('T', 'T', "0" + i / 10, "0" + i % 10); + + // Create Task + status = rtems_task_create( + Task_name[i], + (rtems_task_priority) 2, + RTEMS_MINIMUM_STACK_SIZE, +#if CONFIGURE_SMP_MAXIMUM_PROCESSORS == 4 + // LEON3/LEON4 system - use full SMP + RTEMS_DEFAULT_MODES, +#else + // LEON2 system - emulate SMP via Linux/Windows-like + // handling of tasks with same priority (i.e. pre-emption) + RTEMS_DEFAULT_MODES | RTEMS_TIMESLICE, +#endif + (i%2) == 0 ? RTEMS_FLOATING_POINT : RTEMS_DEFAULT_ATTRIBUTES, + &Task_id[i]); + if (status != RTEMS_SUCCESSFUL) { + printf( + "[MAIN] Failed to rtems_task_create... status:%0x\n", + status); + rtems_task_delete(RTEMS_SELF); + } + + // Start Task + status = rtems_task_start( + Task_id[i], + (i%2) == 0 ? Task1_EntryPoint : Task2_EntryPoint, + i); + } + // To give coverage code the opportunity to work, wait for children tasks + // to die first. RTEMS events are used for synchronization. + { + printf("[MAIN] Waiting for testing tasks to complete...\n"); + rtems_option options = (RTEMS_EVENT_ANY | RTEMS_WAIT); + rtems_event_set in = 0; + for (i=0; i +#include +#include + +#include "version.h" +#include "system.h" + +void memcheck() +{ +#ifdef MEMCHECK + // Use alternating bit values to verify proper memory operations, + // by writing values in memory that stress (electrically) the circuits + uint32_t patterns[] = { + 0x0, + 0xFFFFFFFF, + 0xAAAAAAAA, + 0x55555555, + 0xAA55AA55, + 0x55AA55AA, + }; + +#ifdef CHECK_WRAPAROUNDS_WITH_PRIME_SIZED_WINDOWS + // Prime numbers used to check for potential address space overlaps + // (read comments in the code below that uses this) + unsigned primes[] = { 3, 7, 31, 127 }; + unsigned cnt = 0; +#endif + + // Counters used in loops below. + int i = 0; + + // Detect available memory by repeated allocations. + // Start at 512K. + size_t space = 512*1024; + void *p = malloc(space); + printf("[BOARD TESTER, version %s] - see https://goo.gl/CLrIOC for details\n", version); + printf("[MEMCHECK] Detecting available memory... "); + fflush(stdout); + while(p) { + free(p); + space += 1024*1024; // test memory increases in 1MB increments + p = malloc(space); + } + space -= 1024*1024; + printf("%dK\n", space/1024); + + // Now that we know the amount of memory available, reserve it all. + p = malloc(space); + if (!p) { + puts("[MEMCHECK] Unexpected heap error. Aborting..."); + fflush(stdout); + exit(1); + } + +#ifdef CHECK_WRAPAROUNDS_WITH_PRIME_SIZED_WINDOWS + // How can we make sure that RTEMS doesn't mis-identify our available + // memory and doesn't return 'windowed' areas? (i.e. we think we have + // e.g. 128KB, but in fact, the last 64KB 'mirror' back to the first + // 64KB)? + // + // Simple: we write sequences of values up to prime numbers - e.g. + // + // 0 1 2 0 1 2 0 1 ... + // + // If there is a wrap-around at some offset, the value written will + // NOT be the same as the first time we wrote at the 'mirror' offset, + // since any wraparounds will happen at power-of-two boundaries. + // + // e.g. for a mis-identified 8-byte area as a 16-byte one, we write... + // + // Offset: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // Values written: 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 + // ^ + // `----- Here memory wraps-around + // Values read: 2 0 1 2 0 1 2 0 + // + // Due to the use of a prime number, the wrap-around will be detected; + // we wrote a 0 at offset 0, but it was overwritten with a 2 when we + // wrote at offset 8 (which wrapped around - 'ghost' address space). + + printf("[MEMCHECK] Checking for potential address space overlap. Window: "); + for (i=0; i + +// #include +// #include +// #include +// #include + +rtems_task Init(rtems_task_argument argument); +rtems_task Task1_EntryPoint(rtems_task_argument argument); +rtems_task Task2_EntryPoint(rtems_task_argument argument); +void task_begin(int task_no); +void task_end(int task_no); +void memcheck(void); + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_MAXIMUM_TASKS 64 +#define CONFIGURE_TICKS_PER_TIMESLICE 100 +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_SMP_APPLICATION +#ifdef BSP_leon2 +#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 1 +#else +#define CONFIGURE_SMP_MAXIMUM_PROCESSORS 4 +#endif +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT +#ifndef DEFINE_VARS +#define GLOBAL +#else +#define GLOBAL extern +#endif + +GLOBAL rtems_id g_init_task_id; +GLOBAL int all_OK; + +#include diff --git a/GAISLER/src/task1.c b/GAISLER/src/task1.c new file mode 100644 index 0000000000000000000000000000000000000000..96f7ba822e85498084d539b6c4d1b5ee2f368be7 --- /dev/null +++ b/GAISLER/src/task1.c @@ -0,0 +1,49 @@ +#include "system.h" +#include + +rtems_task Task1_EntryPoint(rtems_task_argument argument) +{ + int task_no = (int) argument; + task_begin(task_no); + + int j; + double d=task_no; + for(j=0; j<10000; j++) { + int k; + for(k=0; k<10000; k++) + d+=1.001; + d*=1.0001; + } + { + long result = (long) d; + long target = 0; + switch(task_no) { + case 0: + target = 172003605L; + break; + case 2: + target = 172003611L; + break; + default: + printf( + "[TASK %d] Failed! Unexpected task number for FPU tests...\n", + task_no); + fflush(stdout); + all_OK = 0; + task_end(task_no); + return; + } + if (target != result) { + printf( + "[TASK %d] Failed! Computed value was %ld instead of %ld\n", + task_no, result, target); + fflush(stdout); + all_OK = 0; + task_end(task_no); + return; + } + } + printf("[TASK %d] Computed the correct floating point result.\n", task_no); + fflush(stdout); + task_end(task_no); +} diff --git a/GAISLER/src/task2.c b/GAISLER/src/task2.c new file mode 100644 index 0000000000000000000000000000000000000000..90465a1996bafb4484f19bc7ce85ce49398b8704 --- /dev/null +++ b/GAISLER/src/task2.c @@ -0,0 +1,29 @@ +#include "system.h" +#include + +rtems_task Task2_EntryPoint(rtems_task_argument argument) +{ + int task_no = (int) argument; + task_begin(task_no); + + int j; + long long int dummy = 0; + for(j=0; j<500000; j++) { + int k; + for(k=0; k<100; k++) + dummy ^= k; + dummy++; + } + if (dummy != 500000) { + printf( + "[TASK %d] Failed! Computed value was %lld instead of 500000\n", + task_no, dummy); + fflush(stdout); + all_OK = 0; + task_end(task_no); + return; + } + printf("[TASK %d] Computed the correct integer result.\n", task_no); + fflush(stdout); + task_end((int) argument); +} diff --git a/GAISLER/src/version.h b/GAISLER/src/version.h new file mode 100644 index 0000000000000000000000000000000000000000..fbfc46566d362f066c9c04e0910a0458148ea23a --- /dev/null +++ b/GAISLER/src/version.h @@ -0,0 +1,4 @@ +#ifndef __VERSION_H__ +#define __VERSION_H__ +const char version[] = "1.75 (ca9a018)"; +#endif