Commit fad56fd1 authored by Thanassis Tsiodras's avatar Thanassis Tsiodras

For completion - GAISLER builds

parent ca9a018c
# 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
#include "system.h"
#include <stdio.h>
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);
}
/*
* Example initialization file - spawns 2 native FPU tasks
*
*/
#define CONFIGURE_INIT
#define TASKS 4
#define DEFINE_VARS
#include "system.h"
#include <stdio.h>
#include <stdlib.h>
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<TASKS; i++)
in |= (RTEMS_EVENT_0 << i);
rtems_event_set out;
rtems_event_set non_completed = in;
while (non_completed) {
status = rtems_event_receive(in, options, RTEMS_NO_TIMEOUT, &out);
if ( status == RTEMS_SUCCESSFUL ) {
non_completed &= ~out;
printf("[MAIN] Task completed.\n");
fflush(stdout);
}
}
printf("[MAIN] All testing tasks completed.\n");
if (!all_OK)
printf("[MAIN] Some tests failed... :-(\n");
else
printf("[MAIN] All tests passed! :-)\n");
fflush(stdout);
}
exit(0);
}
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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<sizeof(primes)/sizeof(primes[0]); i++) {
uint8_t *pc = p;
unsigned prime = primes[i];
unsigned bytes = space;
printf("%s%d", i?", ":"", prime);
fflush(stdout);
cnt = 0;
while (bytes--) {
*pc++ = cnt;
cnt++;
if (cnt == prime) {
cnt = 0;
}
}
pc = p;
bytes = space;
cnt = 0;
while (bytes--) {
if (*pc != cnt) {
printf("[MEMCHECK] Address space wrapped around at 0x%x!\n",
(unsigned)pc);
fflush(stdout);
exit(1);
}
pc++;
cnt++;
if (cnt == prime) {
cnt = 0;
}
}
}
puts("");
#endif
// Write all over the memory using alternating bit values; this verifies
// proper memory operations, by stressing (electrically) the circuits.
for(i=0; i<sizeof(patterns)/sizeof(patterns[0]); i++) {
unsigned pattern = patterns[i];
uint32_t *pw = p;
unsigned words = space/4;
printf("[MEMCHECK] Writing memory pattern 0x%08x ", pattern);
fflush(stdout);
// Writing the pattern
while(words--) {
*pw++ = pattern;
if ((words & 0xFFFFFF) == 0xFFFFFF) {
printf("\b\b\b\b\b\b%5.2f%%", 100.0*((space/4.0)-words)/(space/4.0));
fflush(stdout);
}
}
printf("\b\b\b\b\b\b\b%5.2f%%\n", 100.0);
pw = p;
words = space/4;
// Verifying the pattern
printf("[MEMCHECK] Reading memory, checking for 0x%08x ", pattern);
fflush(stdout);
while(words--) {
if (*pw != pattern) {
printf(
"\n[MEMCHECK] Failed with pattern 0x%x at offset 0x%x\n",
pattern, (unsigned)pw);
fflush(stdout);
exit(1);
}
if ((words & 0xFFFFFF) == 0xFFFFFF) {
printf("\b\b\b\b\b\b%5.2f%%", 100.0*((space/4.0)-words)/(space/4.0));
fflush(stdout);
}
pw++;
}
printf("\b\b\b\b\b\b\b%5.2f%%\n", 100.0);
}
// A simple final run storing big numbers consecutively.
printf("[MEMCHECK] Writing 32-bit numbers from 0 up to %d ", space/4);
{
uint32_t *pw = p;
unsigned words = space/4;
while(words--) {
*pw++ = words;
if ((words & 0xFFFFFF) == 0xFFFFFF) {
printf("\b\b\b\b\b\b%5.2f%%", 100.0*((space/4.0)-words)/(space/4.0));
fflush(stdout);
}
}
printf("\b\b\b\b\b\b\b%5.2f%%\n", 100.0);
printf("[MEMCHECK] Reading 32-bit numbers from 0 up to %d ", space/4);
pw = p;
words = space/4;
// Verifying the big numbers
while(words--) {
if (*pw != words) {
printf(
"\n[MEMCHECK] Failed with big value 0x%x at offset 0x%x\n",
words, (unsigned)pw);
fflush(stdout);
exit(1);
}
pw++;
if ((words & 0xFFFFFF) == 0xFFFFFF) {
printf("\b\b\b\b\b\b%5.2f%%", 100.0*((space/4.0)-words)/(space/4.0));
fflush(stdout);
}
}
printf("\b\b\b\b\b\b\b%5.2f%%\n", 100.0);
}
free(p);
#else
puts("[MEMCHECK] Memory checks are disabled. Proceeding with main execution...");
fflush(stdout);
#endif
}
// Comment this to skip memory checks at startup
#define MEMCHECK
#include <rtems.h>
// #include <rtems/score/types.h>
// #include <rtems/rtems/types.h>
// #include <rtems/rtems/tasks.h>
// #include <rtems/rtems/event.h>
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 <rtems/confdefs.h>
#include "system.h"
#include <stdio.h>
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);
}
#include "system.h"
#include <stdio.h>
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);
}
#ifndef __VERSION_H__
#define __VERSION_H__
const char version[] = "1.75 (ca9a018)";
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment