Integrate (soft) float support

master
kaqu 2 years ago
parent d4948f201e
commit 728f258fd9
  1. BIN
      software/lib/libm.a
  2. BIN
      software/lib/rv32ilibgcc.a
  3. 10
      software/ramcreate.sh
  4. 1
      software/source/README.md
  5. 24
      software/source/main.c
  6. 437
      software/source/my_vsnprintf.c

Binary file not shown.

Binary file not shown.

@ -60,9 +60,15 @@ echo "calling gcc with: -c $COMMONFLAGS $CFLAGS -Wa,-fPIC for $1 & $2"
#$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -O0 -S -nostdinc $COMMONFLAGS $INCLUDES -Wa,-fPIC source/$1.c
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC source/$2.c -o build/$2.o
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC source/$1.c -o build/$1.o
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC source/my_vsnprintf.c -o build/my_vsnprintf.o
#$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC source/my_printf.c -o build/my_printf.o
echo "--"
echo "calling ld for RAM bank #$3 with: $LDFLAGS $OBJECTS build/$2.o build/$1.o -o build/$1.bin"
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-ld $LDFLAGS -T linker/ram$3.ld -N $CRT0 $OBJECTS $LXR build/$2.o build/$1.o -o build/$1.elf
echo "calling ld for RAM bank #$3 with: $LDFLAGS $OBJECTS build/$2.o build/$1.o build/my_vsnprintf.o lib/libm.a lib/rv32ilibgcc.a -o build/$1.bin"
# /home/kln/fpga/litex/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/riscv64-unknown-elf/lib/rv32i/ilp32 <-- libs
# /home/kln/fpga/litex/litex-boards/litex_boards/targets/build/colorlight_5a_75b/software/libbase <-- board specific
#$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-ld $LDFLAGS -T linker/ram$3.ld -N $CRT0 $OBJECTS $LXR build/$2.o build/$1.o lib/rv32ilibgcc.a -o build/$1.elf
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-ld $LDFLAGS -T linker/ram$3.ld -N $CRT0 $OBJECTS $LXR build/$2.o build/$1.o build/my_vsnprintf.o lib/libm.a lib/rv32ilibgcc.a -o build/$1.elf
#$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-ld $LDFLAGS -T linker/ram$3.ld -N $CRT0 $OBJECTS $LXR build/$2.o build/$1.o build/my_printf.o lib/libm.a lib/rv32ilibgcc.a -o build/$1.elf
echo "--"
echo "creating raw binary from elf-file"
if [ "$3" = "1" ]; then

@ -2,4 +2,5 @@ main.c - This is the rudimentary BIOS loop
illumination.c - This is a sample application, demonstrating the use
of the 'neopixelengine' (the documentation can be found
under ./build/documentation/http/index.html)
my_vsnprintf.c - Some helpers. For float formatting use printf1() (really ugly!)

@ -17,6 +17,7 @@
#include <id.h>
#include <irq.h>
#include <crc.h>
#include <math.h>
#include "boot.h"
#include "readline.h"
@ -51,6 +52,7 @@ extern int get_console(void);
#endif
static int32_t mycpc; // Current PC storage
int __errno; // Needed by lib
int main(int i, char **c)
{
@ -101,10 +103,30 @@ int main(int i, char **c)
*statept = get_console(); // Make sure, we know what was going on ...
#endif
printf("\e[1mExecuting within RAM ...\e[0m\n");
while(1)
if(illumination()) // The DEMO !
break;
*statept = get_console(); // Make sure, we know what was going on ...
*statept = get_console(); // Make sure, we know what was going on ...
#ifdef FLOAT_TEST
// Float test
void printf1(const char *fmt, float f1);
double f1, f2;
f1 = 1.5;
f2 = 3.5;
printf1("1. %4.2f ...\n", f1);
printf1("2. %4.2f ...\n", f2);
double f4sin = sin(3.1415/2.0); // 1/2 PI
printf1("sin(PI/2) => %6.3f\n", f4sin);
float f4pow = pow(10.0, 2);
printf1("pow(10,2) => %6.4f\n", f4pow);
float f3add = f1 + f2;
printf1("1.5+3.5 => %8.5f\n", f3add);
#endif
while(1) {
printf("\n%s", PROMPT);
readline(buffer, CMD_LINE_BUFFER_SIZE);

@ -0,0 +1,437 @@
/*
* MiSoC
* Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
* Copyright (C) Linux kernel developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
// Taken from <base/limits.h>
#define INT_MAX 0x7fffffff
/**
* vsnprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @size: The size of the buffer, including the trailing null space
* @fmt: The format string to use
* @args: Arguments for the format string
*
* The return value is the number of characters which would
* be generated for the given input, excluding the trailing
* '\0', as per ISO C99. If you want to have the exact
* number of characters written into @buf as return value
* (not including the trailing '\0'), use vscnprintf(). If the
* return is greater than or equal to @size, the resulting
* string is truncated.
*
* Call this function if you are already dealing with a va_list.
* You probably want snprintf() instead.
*/
extern int my_vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
int my_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
{
int len;
unsigned long long num;
int i, base;
char *str, *end, c;
const char *s;
int flags; /* flags to number() */
int field_width; /* width of output field */
int precision; /* min. # of digits for integers; max
number of chars for from string */
int qualifier; /* 'h', 'l', or 'L' for integer fields */
/* 'z' support added 23/7/1999 S.H. */
/* 'z' changed to 'Z' --davidm 1/25/99 */
/* 't' added for ptrdiff_t */
/* Reject out-of-range values early. Large positive sizes are
used for unknown buffer sizes. */
if (unlikely((int) size < 0))
return 0;
str = buf;
end = buf + size;
/* Make sure end is always >= buf */
if (end < buf) {
end = ((void *)-1);
size = end - buf;
}
for (; *fmt ; ++fmt) {
if (*fmt != '%') {
if (str < end)
*str = *fmt;
++str;
continue;
}
/* process flags */
flags = 0;
repeat:
++fmt; /* this also skips first '%' */
switch (*fmt) {
case '-': flags |= PRINTF_LEFT; goto repeat;
case '+': flags |= PRINTF_PLUS; goto repeat;
case ' ': flags |= PRINTF_SPACE; goto repeat;
case '#': flags |= PRINTF_SPECIAL; goto repeat;
case '0': flags |= PRINTF_ZEROPAD; goto repeat;
}
/* get field width */
field_width = -1;
if (isdigit(*fmt))
field_width = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
/* it's the next argument */
field_width = va_arg(args, int);
if (field_width < 0) {
field_width = -field_width;
flags |= PRINTF_LEFT;
}
}
/* get the precision */
precision = -1;
if (*fmt == '.') {
++fmt;
if (isdigit(*fmt))
precision = skip_atoi(&fmt);
else if (*fmt == '*') {
++fmt;
/* it's the next argument */
precision = va_arg(args, int);
}
if (precision < 0)
precision = 0;
}
/* get the conversion qualifier */
qualifier = -1;
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
*fmt =='Z' || *fmt == 'z' || *fmt == 't') {
qualifier = *fmt;
++fmt;
if (qualifier == 'l' && *fmt == 'l') {
qualifier = 'L';
++fmt;
}
}
/* default base */
base = 10;
switch (*fmt) {
case 'c':
if (!(flags & PRINTF_LEFT)) {
while (--field_width > 0) {
if (str < end)
*str = ' ';
++str;
}
}
c = (unsigned char) va_arg(args, int);
if (str < end)
*str = c;
++str;
while (--field_width > 0) {
if (str < end)
*str = ' ';
++str;
}
continue;
case 's':
s = va_arg(args, char *);
if (s == NULL)
s = "<NULL>";
len = strnlen(s, precision);
if (!(flags & PRINTF_LEFT)) {
while (len < field_width--) {
if (str < end)
*str = ' ';
++str;
}
}
for (i = 0; i < len; ++i) {
if (str < end)
*str = *s;
++str; ++s;
}
while (len < field_width--) {
if (str < end)
*str = ' ';
++str;
}
continue;
case 'p':
if (field_width == -1) {
field_width = 2*sizeof(void *);
flags |= PRINTF_ZEROPAD;
}
str = number(str, end,
(unsigned long) va_arg(args, void *),
16, field_width, precision, flags);
continue;
#undef NO_FLOAT
#ifndef NO_FLOAT
case 'g':
case 'f': {
double f, g;
f = va_arg(args, double);
if(f < 0.0) {
if(str < end)
*str = '-';
str++;
f = -f;
}
g = pow(10.0, floor(log10(f)));
if(g < 1.0) {
if(str < end)
*str = '0';
str++;
}
while(g >= 1.0) {
if(str < end)
*str = '0' + fmod(f/g, 10.0);
str++;
g /= 10.0;
}
if(str < end)
*str = '.';
str++;
for(i=0;i<6;i++) {
f = fmod(f*10.0, 10.0);
if(str < end)
*str = '0' + f;
str++;
}
continue;
}
#endif
case 'n':
/* FIXME:
* What does C99 say about the overflow case here? */
if (qualifier == 'l') {
long * ip = va_arg(args, long *);
*ip = (str - buf);
} else if (qualifier == 'Z' || qualifier == 'z') {
size_t * ip = va_arg(args, size_t *);
*ip = (str - buf);
} else {
int * ip = va_arg(args, int *);
*ip = (str - buf);
}
continue;
case '%':
if (str < end)
*str = '%';
++str;
continue;
/* integer number formats - set up the flags and "break" */
case 'o':
base = 8;
break;
case 'X':
flags |= PRINTF_LARGE;
/* FALLTHRU */
case 'x':
base = 16;
break;
case 'd':
case 'i':
flags |= PRINTF_SIGN;
case 'u':
break;
default:
if (str < end)
*str = '%';
++str;
if (*fmt) {
if (str < end)
*str = *fmt;
++str;
} else {
--fmt;
}
continue;
}
if (qualifier == 'L')
num = va_arg(args, long long);
else if (qualifier == 'l') {
num = va_arg(args, unsigned long);
if (flags & PRINTF_SIGN)
num = (signed long) num;
} else if (qualifier == 'Z' || qualifier == 'z') {
num = va_arg(args, size_t);
} else if (qualifier == 't') {
num = va_arg(args, ptrdiff_t);
} else if (qualifier == 'h') {
num = (unsigned short) va_arg(args, int);
if (flags & PRINTF_SIGN)
num = (signed short) num;
} else {
num = va_arg(args, unsigned int);
if (flags & PRINTF_SIGN)
num = (signed int) num;
}
str = number(str, end, num, base,
field_width, precision, flags);
}
if (size > 0) {
if (str < end)
*str = '\0';
else
end[-1] = '\0';
}
/* the trailing null byte doesn't count towards the total */
return str-buf;
}
/**
* vscnprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @size: The size of the buffer, including the trailing null space
* @fmt: The format string to use
* @args: Arguments for the format string
*
* The return value is the number of characters which have been written into
* the @buf not including the trailing '\0'. If @size is <= 0 the function
* returns 0.
*
* Call this function if you are already dealing with a va_list.
* You probably want scnprintf() instead.
*/
extern int my_vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
int my_vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
{
size_t i;
i=my_vsnprintf(buf,size,fmt,args);
return (i >= size) ? (size - 1) : i;
}
/**
* sprintf - Format a string and place it in a buffer
* @buf: The buffer to place the result into
* @fmt: The format string to use
* @...: Arguments for the format string
*
* The function returns the number of characters written
* into @buf. Use snprintf() or scnprintf() in order to avoid
* buffer overflows.
*/
extern int my_sprintf(char * buf, const char *fmt, ...);
int my_sprintf(char * buf, const char *fmt, ...)
{
va_list args;
int i;
va_start(args, fmt);
i=my_vsnprintf(buf, INT_MAX, fmt, args);
va_end(args);
return i;
}
#ifdef NOT_WORKING
#define PRINTF_BUFFER_SIZE 256
extern int my_vprintf(const char *fmt, va_list args);
int my_vprintf(const char *fmt, va_list args)
{
int len;
char outbuf[PRINTF_BUFFER_SIZE];
len = my_vscnprintf(outbuf, sizeof(outbuf), fmt, args);
outbuf[len] = 0;
extern void putsnonl(char *);
putsnonl(outbuf);
return len;
}
extern int my_printf(const char *fmt, ...);
int my_printf(const char *fmt, ...)
{
char outputstr[PRINTF_BUFFER_SIZE];
va_list args;
int len;
va_start(args, fmt);
len = my_vsnprintf(outputstr, INT_MAX, fmt, args);
va_end(args);
return len;
}
#endif
//
// Nasty little helper, very vulgar implementation based on ridiculous fixed assumptions ...
// But: Worx for me ;)
void printf1(const char *fmt, float f1);
void printf1(const char *fmt, float f1)
{
extern int my_sprintf(char * buf, const char *fmt, ...);
static char outputstr[120]; // Output helper
static char fstr[16];
int width = 0, remainder = 0;
char *fr = strchr(fmt,'\%');
if(fr != NULL) {
if((fr[1] >= '0') && (fr[1] <= '9')) { // %<n>.<n>f
width = atoi(&fr[1]);
if(fr[2] == '.') {
if((fr[3] >= '0') && (fr[3] <= '9')) {
remainder = atoi(&fr[3]);
}
}
}
strncpy(fstr, fr, 5); // Copy format only
my_sprintf(outputstr, fstr, f1); // Eval separately ...
outputstr[width] = '\0'; // Respect field width
char *rest = strchr(outputstr,'.');
if(rest != NULL)
*(rest + remainder + 1) = '\0'; // & precision
strcpy(fstr,outputstr); // Local copy
strcpy(outputstr,fmt); // Copy original format -> outputstr["XX%6.2fXX"]
char *fr2 = strchr(outputstr,'\%'); // Select target -> ^
strcpy(fr2, fstr); // Substitute %<n>.<n>f w/ value -> outputstr["XXnnnnnnn"]
strcat(fr2, fr+5); // Concatenate remaining format -> ^
printf(outputstr);
return;
}
my_sprintf(outputstr, fmt, f1);
printf(outputstr);
}
Loading…
Cancel
Save