diff --git a/build-coremark.sh b/build-coremark.sh index fafb55d..2449d2d 100755 --- a/build-coremark.sh +++ b/build-coremark.sh @@ -12,5 +12,5 @@ echo "Start compilation" make PORT_DIR=../riscv64 compile mv coremark.riscv ../ -make PORT_DIR=../riscv64-baremetal compile ITERATIONS=100 +make PORT_DIR=../riscv64-baremetal compile mv coremark.bare.riscv ../ diff --git a/coremark b/coremark index 2e9d616..d5fad6b 160000 --- a/coremark +++ b/coremark @@ -1 +1 @@ -Subproject commit 2e9d6165f362f7071d29b7f88c6d32655e5d4a3c +Subproject commit d5fad6bd094899101a4e5fd53af7298160ced6ab diff --git a/riscv64-baremetal/core_portme.c b/riscv64-baremetal/core_portme.c index 8f17cb8..a989d11 100755 --- a/riscv64-baremetal/core_portme.c +++ b/riscv64-baremetal/core_portme.c @@ -119,7 +119,11 @@ void portable_free(void *p) { #define TIMER_RES_DIVIDER 1 #define SAMPLE_TIME_IMPLEMENTATION 1 #endif + +// Allow overriding EE_TICKS_PER_SEC +#ifndef EE_TICKS_PER_SEC #define EE_TICKS_PER_SEC (NSECS_PER_SEC / TIMER_RES_DIVIDER) +#endif #if SAMPLE_TIME_IMPLEMENTATION /** Define Host specific (POSIX), or target specific global time variables. */ @@ -344,3 +348,9 @@ ee_u8 core_stop_parallel(core_results *res) { #error "Please implement multicore functionality in core_portme.c to use multiple contexts." #endif /* multithread implementations */ #endif + +extern int putchar(int ch); + +void uart_send_char (char ch) { + putchar(ch); +} diff --git a/riscv64-baremetal/core_portme.h b/riscv64-baremetal/core_portme.h index ef26e88..feb095f 100755 --- a/riscv64-baremetal/core_portme.h +++ b/riscv64-baremetal/core_portme.h @@ -54,7 +54,7 @@ Original Author: Shay Gal-on Define to 1 if the platform has stdio.h and implements the printf function. */ #ifndef HAS_PRINTF -#define HAS_PRINTF 1 +#define HAS_PRINTF 0 #endif /* Configuration: CORE_TICKS @@ -293,4 +293,7 @@ void portable_fini(core_portable *p); #endif #endif /* SEED_METHOD==SEED_VOLATILE */ +extern void uart_send_char (char); +extern int ee_printf (const char *, ...); + #endif /* CORE_PORTME_H */ diff --git a/riscv64-baremetal/core_portme.mak b/riscv64-baremetal/core_portme.mak index 2f5ee14..a2932b2 100755 --- a/riscv64-baremetal/core_portme.mak +++ b/riscv64-baremetal/core_portme.mak @@ -16,6 +16,20 @@ #File: core_portme.mak +# Flag: ARCH +# RISC-V ISA specification string +ARCH ?= rv64imafdc +# Flag: ABI +# RISC-V ABI +ABI ?= lp64d +ARCHFLAGS = -march=$(ARCH) -mabi=$(ABI) +# Flag: DEBUG +# Enable debugging output +DEBUG ?= +# Flag: TICKS_PER_SEC +# Hard-coded clock frequency of the tested CPU. Set to a reasonably low value +# when running in a RTL simulation. +TICKS_PER_SEC ?= # Flag: RISCVTOOLS # Use this flag to point to your RISCV tools RISCVTOOLS=$(RISCV) @@ -31,7 +45,13 @@ CC = $(RISCVTOOLS)/bin/$(RISCVTYPE)-gcc # Flag: CFLAGS # Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags" #PORT_CFLAGS = -O2 -static -std=gnu99 -PORT_CFLAGS = -O2 -mcmodel=medany -static -std=gnu99 -fno-common -fno-tree-loop-distribute-patterns -nostdlib -nostartfiles -lm -lgcc -T $(PORT_DIR)/link.ld +PORT_CFLAGS = $(ARCHFLAGS) -O2 -mcmodel=medany -static -std=gnu99 -fno-common -fno-tree-loop-distribute-patterns -nostdlib -nostartfiles -fno-builtin -lm -lgcc -T $(PORT_DIR)/link.ld +ifneq ($(TICKS_PER_SEC),) + PORT_CFLAGS += -DEE_TICKS_PER_SEC=$(TICKS_PER_SEC) +endif +ifneq ($(DEBUG),) + PORT_CFLAGS += -DCORE_DEBUG=1 +endif FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)" CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\" #Flag: LFLAGS_END @@ -40,7 +60,7 @@ CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\" LFLAGS_END += # Flag: PORT_SRCS # Port specific source files can be added here -PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/syscalls.c $(PORT_DIR)/crt.S +PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/syscalls.c $(PORT_DIR)/crt.S $(PORT_DIR)/ee_printf.c barebones/cvt.c # Flag: LOAD # Define this flag if you need to load to a target, as in a cross compile environment. @@ -48,6 +68,15 @@ PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/syscalls.c $(PORT_DIR)/crt.S # Define this flag if running does not consist of simple invocation of the binary. # In a cross compile environment, you need to define this. +# Instead of copying and manually modifying ee_printf.c file its done on the fly: +# - uart_send_char() is marked as weak. It's implemented in a different file +# - the #error directive is removed +# - ee_printf() buffer is increased to 1KB +$(PORT_DIR)/ee_printf.c: barebones/ee_printf.c + @sed '/uart_send_char(char c)/s/^/__attribute__((weak)) /' $< >$@ + @sed -ie '/#error/d' $@ + @sed -i 's/char buf\[256\]/char buf\[1024\]/g' $@ + #For flashing and using a tera term macro, you could use #LOAD = flash ADDR #RUN = ttpmacro coremark.ttl diff --git a/riscv64-baremetal/syscalls.c b/riscv64-baremetal/syscalls.c index 0bf0ea6..a633b4f 100644 --- a/riscv64-baremetal/syscalls.c +++ b/riscv64-baremetal/syscalls.c @@ -12,6 +12,8 @@ #undef strcmp +extern int ee_printf(const char *fmt, ...); + extern volatile uint64_t tohost; extern volatile uint64_t fromhost; @@ -112,18 +114,15 @@ void _init(int cid, int nc) // only single-threaded programs should ever get here. int ret = main(0, 0); - char buf[NUM_COUNTERS * 32] __attribute__((aligned(64))); - char* pbuf = buf; - for (int i = 0; i < NUM_COUNTERS; i++) - if (counters[i]) - pbuf += sprintf(pbuf, "%s = %d\n", counter_names[i], counters[i]); - if (pbuf != buf) - printstr(buf); + for (int i = 0; i < NUM_COUNTERS; i++) { + if (counters[i]) { + ee_printf("%s = %d\n", counter_names[i], counters[i]); + } + } exit(ret); } -#undef putchar int putchar(int ch) { static __thread char buf[64] __attribute__((aligned(64))); @@ -140,251 +139,12 @@ int putchar(int ch) return 0; } -void printhex(uint64_t x) -{ - char str[17]; - int i; - for (i = 0; i < 16; i++) - { - str[15-i] = (x & 0xF) + ((x & 0xF) < 10 ? '0' : 'a'-10); - x >>= 4; - } - str[16] = 0; - - printstr(str); -} - -static inline void printnum(void (*putch)(int, void**), void **putdat, - unsigned long long num, unsigned base, int width, int padc) -{ - unsigned digs[sizeof(num)*CHAR_BIT]; - int pos = 0; - - while (1) - { - digs[pos++] = num % base; - if (num < base) - break; - num /= base; - } - - while (width-- > pos) - putch(padc, putdat); - - while (pos-- > 0) - putch(digs[pos] + (digs[pos] >= 10 ? 'a' - 10 : '0'), putdat); -} - -static unsigned long long getuint(va_list *ap, int lflag) -{ - if (lflag >= 2) - return va_arg(*ap, unsigned long long); - else if (lflag) - return va_arg(*ap, unsigned long); - else - return va_arg(*ap, unsigned int); -} - -static long long getint(va_list *ap, int lflag) -{ - if (lflag >= 2) - return va_arg(*ap, long long); - else if (lflag) - return va_arg(*ap, long); - else - return va_arg(*ap, int); -} - -static void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap) -{ - register const char* p; - const char* last_fmt; - register int ch, err; - unsigned long long num; - int base, lflag, width, precision, altflag; - char padc; - - while (1) { - while ((ch = *(unsigned char *) fmt) != '%') { - if (ch == '\0') - return; - fmt++; - putch(ch, putdat); - } - fmt++; - - // Process a %-escape sequence - last_fmt = fmt; - padc = ' '; - width = -1; - precision = -1; - lflag = 0; - altflag = 0; - reswitch: - switch (ch = *(unsigned char *) fmt++) { - - // flag to pad on the right - case '-': - padc = '-'; - goto reswitch; - - // flag to pad with 0's instead of spaces - case '0': - padc = '0'; - goto reswitch; - - // width field - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - for (precision = 0; ; ++fmt) { - precision = precision * 10 + ch - '0'; - ch = *fmt; - if (ch < '0' || ch > '9') - break; - } - goto process_precision; - - case '*': - precision = va_arg(ap, int); - goto process_precision; - - case '.': - if (width < 0) - width = 0; - goto reswitch; - - case '#': - altflag = 1; - goto reswitch; - - process_precision: - if (width < 0) - width = precision, precision = -1; - goto reswitch; - - // long flag (doubled for long long) - case 'l': - lflag++; - goto reswitch; - - // character - case 'c': - putch(va_arg(ap, int), putdat); - break; - - // string - case 's': - if ((p = va_arg(ap, char *)) == NULL) - p = "(null)"; - if (width > 0 && padc != '-') - for (width -= strnlen(p, precision); width > 0; width--) - putch(padc, putdat); - for (; (ch = *p) != '\0' && (precision < 0 || --precision >= 0); width--) { - putch(ch, putdat); - p++; - } - for (; width > 0; width--) - putch(' ', putdat); - break; - - // (signed) decimal - case 'd': - num = getint(&ap, lflag); - if ((long long) num < 0) { - putch('-', putdat); - num = -(long long) num; - } - base = 10; - goto signed_number; - - // unsigned decimal - case 'u': - base = 10; - goto unsigned_number; - - // (unsigned) octal - case 'o': - // should do something with padding so it's always 3 octits - base = 8; - goto unsigned_number; - - // pointer - case 'p': - static_assert(sizeof(long) == sizeof(void*)); - lflag = 1; - putch('0', putdat); - putch('x', putdat); - /* fall through to 'x' */ - - // (unsigned) hexadecimal - case 'X': - case 'x': - base = 16; - unsigned_number: - num = getuint(&ap, lflag); - signed_number: - printnum(putch, putdat, num, base, width, padc); - break; - - // escaped '%' character - case '%': - putch(ch, putdat); - break; - - // unrecognized escape sequence - just print it literally - default: - putch('%', putdat); - fmt = last_fmt; - break; - } - } -} - -int printf(const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - - vprintfmt((void*)putchar, 0, fmt, ap); - - va_end(ap); - return 0; // incorrect return value, but who cares, anyway? -} - int puts(const char* s) { - printf(s); - printf("\n"); + syscall(SYS_write, 1, (uintptr_t)s, strlen(s)); return 0; // incorrect return value, but who cares, anyway? } -int sprintf(char* str, const char* fmt, ...) -{ - va_list ap; - char* str0 = str; - va_start(ap, fmt); - - void sprintf_putch(int ch, void** data) - { - char** pstr = (char**)data; - **pstr = ch; - (*pstr)++; - } - - vprintfmt(sprintf_putch, (void**)&str, fmt, ap); - *str = 0; - - va_end(ap); - return str - str0; -} - void* memcpy(void* dest, const void* src, size_t len) { if ((((uintptr_t)dest | (uintptr_t)src | len) & (sizeof(uintptr_t)-1)) == 0) { @@ -476,3 +236,40 @@ long atol(const char* str) return sign ? -res : res; } + +double modf (double num, double* iptr) { + /* + * Source: https://git.musl-libc.org/cgit/musl/tree/src/math/modf.c + * Copyright (c) 2005-2020 Rich Felker, et al. + * License (MIT) https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT + */ + union {double f; uint64_t i;} u = {num}; + uint64_t mask; + int e = (int)(u.i>>52 & 0x7ff) - 0x3ff; + + /* no fractional part */ + if (e >= 52) { + *iptr = num; + if (e == 0x400 && u.i<<12 != 0) /* nan */ + return num; + u.i &= 1ULL<<63; + return u.f; + } + + /* no integral part*/ + if (e < 0) { + u.i &= 1ULL<<63; + *iptr = u.f; + return num; + } + + mask = -1ULL>>12>>e; + if ((u.i & mask) == 0) { + *iptr = num; + u.i &= 1ULL<<63; + return u.f; + } + u.i &= ~mask; + *iptr = u.f; + return num - u.f; +}