forked from Firmware/Firmwares
		
	rework structure
This commit is contained in:
		
							
								
								
									
										197
									
								
								benchmarks/coremark/tgc/core_portme.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								benchmarks/coremark/tgc/core_portme.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| /* | ||||
| Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
|  | ||||
| Original Author: Shay Gal-on | ||||
| */ | ||||
| #include "coremark.h" | ||||
| #include "core_portme.h" | ||||
| //Read cycle CSR | ||||
| unsigned long long _read_cycle() | ||||
| { | ||||
|     unsigned long long result; | ||||
|     unsigned long lower; | ||||
|     unsigned long upper1; | ||||
|     unsigned long upper2; | ||||
|  | ||||
|     asm volatile ( | ||||
|         "repeat_cycle_%=: csrr %0, cycleh;\n" | ||||
|         "        csrr %1, cycle;\n" | ||||
|         "        csrr %2, cycleh;\n" | ||||
|         "        bne %0, %2, repeat_cycle_%=;\n" | ||||
|         : "=r" (upper1),"=r" (lower),"=r" (upper2)    // Outputs   : temp variable for load result | ||||
|         : | ||||
|         : | ||||
|     ); | ||||
|     *(unsigned long *)(&result) = lower; | ||||
|     *((unsigned long *)(&result)+1) = upper1; | ||||
|  | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| volatile int tohost; | ||||
| volatile int fromhost; | ||||
|  | ||||
| void exit(int n){ | ||||
|       tohost = 0x1; | ||||
|       for (;;); | ||||
| } | ||||
|  | ||||
| void __libc_init_array (void) { | ||||
| /* | ||||
|     size_t count; | ||||
|     size_t i; | ||||
|     count = __preinit_array_end - __preinit_array_start; | ||||
|     for (i = 0; i < count; i++) | ||||
|         __preinit_array_start[i] (); | ||||
|  | ||||
| #ifdef HAVE_INIT_FINI | ||||
|     _init (); | ||||
| #endif | ||||
|  | ||||
|     count = __init_array_end - __init_array_start; | ||||
|     for (i = 0; i < count; i++) | ||||
|     __init_array_start[i] (); | ||||
| */ | ||||
| } | ||||
| #if VALIDATION_RUN | ||||
| volatile ee_s32 seed1_volatile = 0x3415; | ||||
| volatile ee_s32 seed2_volatile = 0x3415; | ||||
| volatile ee_s32 seed3_volatile = 0x66; | ||||
| #endif | ||||
| #if PERFORMANCE_RUN | ||||
| volatile ee_s32 seed1_volatile = 0x0; | ||||
| volatile ee_s32 seed2_volatile = 0x0; | ||||
| volatile ee_s32 seed3_volatile = 0x66; | ||||
| #endif | ||||
| #if PROFILE_RUN | ||||
| volatile ee_s32 seed1_volatile = 0x8; | ||||
| volatile ee_s32 seed2_volatile = 0x8; | ||||
| volatile ee_s32 seed3_volatile = 0x8; | ||||
| #endif | ||||
| volatile ee_s32 seed4_volatile = ITERATIONS; | ||||
| volatile ee_s32 seed5_volatile = 0; | ||||
| /* Porting : Timing functions | ||||
|         How to capture time and convert to seconds must be ported to whatever is | ||||
|    supported by the platform. e.g. Read value from on board RTC, read value from | ||||
|    cpu clock cycles performance counter etc. Sample implementation for standard | ||||
|    time.h and windows.h definitions included. | ||||
| */ | ||||
| CORETIMETYPE | ||||
| barebones_clock() | ||||
| { | ||||
|     return (CORETIMETYPE)_read_cycle(); | ||||
| } | ||||
| /* Define : TIMER_RES_DIVIDER | ||||
|         Divider to trade off timer resolution and total time that can be | ||||
|    measured. | ||||
|  | ||||
|         Use lower values to increase resolution, but make sure that overflow | ||||
|    does not occur. If there are issues with the return value overflowing, | ||||
|    increase this value. | ||||
|         */ | ||||
| #define GETMYTIME(_t)              (*_t = barebones_clock()) | ||||
| #define MYTIMEDIFF(fin, ini)       ((fin) - (ini)) | ||||
| #define TIMER_RES_DIVIDER          1 | ||||
| #define SAMPLE_TIME_IMPLEMENTATION 1 | ||||
| #define EE_TICKS_PER_SEC           (CLOCKS_PER_SEC / TIMER_RES_DIVIDER) | ||||
|  | ||||
| /** Define Host specific (POSIX), or target specific global time variables. */ | ||||
| static CORETIMETYPE start_time_val, stop_time_val; | ||||
|  | ||||
| /* Function : start_time | ||||
|         This function will be called right before starting the timed portion of | ||||
|    the benchmark. | ||||
|  | ||||
|         Implementation may be capturing a system timer (as implemented in the | ||||
|    example code) or zeroing some system parameters - e.g. setting the cpu clocks | ||||
|    cycles to 0. | ||||
| */ | ||||
| void | ||||
| start_time(void) | ||||
| { | ||||
|     GETMYTIME(&start_time_val); | ||||
| } | ||||
| /* Function : stop_time | ||||
|         This function will be called right after ending the timed portion of the | ||||
|    benchmark. | ||||
|  | ||||
|         Implementation may be capturing a system timer (as implemented in the | ||||
|    example code) or other system parameters - e.g. reading the current value of | ||||
|    cpu cycles counter. | ||||
| */ | ||||
| void | ||||
| stop_time(void) | ||||
| { | ||||
|     GETMYTIME(&stop_time_val); | ||||
| } | ||||
| /* Function : get_time | ||||
|         Return an abstract "ticks" number that signifies time on the system. | ||||
|  | ||||
|         Actual value returned may be cpu cycles, milliseconds or any other | ||||
|    value, as long as it can be converted to seconds by <time_in_secs>. This | ||||
|    methodology is taken to accomodate any hardware or simulated platform. The | ||||
|    sample implementation returns millisecs by default, and the resolution is | ||||
|    controlled by <TIMER_RES_DIVIDER> | ||||
| */ | ||||
| CORE_TICKS | ||||
| get_time(void) | ||||
| { | ||||
|     CORE_TICKS elapsed | ||||
|         = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val)); | ||||
|     return elapsed; | ||||
| } | ||||
| /* Function : time_in_secs | ||||
|         Convert the value returned by get_time to seconds. | ||||
|  | ||||
|         The <secs_ret> type is used to accomodate systems with no support for | ||||
|    floating point. Default implementation implemented by the EE_TICKS_PER_SEC | ||||
|    macro above. | ||||
| */ | ||||
| secs_ret | ||||
| time_in_secs(CORE_TICKS ticks) | ||||
| { | ||||
|     secs_ret retval = ((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC; | ||||
|     return retval; | ||||
| } | ||||
|  | ||||
| ee_u32 default_num_contexts = 1; | ||||
|  | ||||
| /* Function : portable_init | ||||
|         Target specific initialization code | ||||
|         Test for some common mistakes. | ||||
| */ | ||||
| void | ||||
| portable_init(core_portable *p, int *argc, char *argv[]) | ||||
| { | ||||
|     if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) | ||||
|     { | ||||
|         ee_printf( | ||||
|             "ERROR! Please define ee_ptr_int to a type that holds a " | ||||
|             "pointer!\n"); | ||||
|     } | ||||
|     if (sizeof(ee_u32) != 4) | ||||
|     { | ||||
|         ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n"); | ||||
|     } | ||||
|     p->portable_id = 1; | ||||
| } | ||||
| /* Function : portable_fini | ||||
|         Target specific final code | ||||
| */ | ||||
| void | ||||
| portable_fini(core_portable *p) | ||||
| { | ||||
|     p->portable_id = 0; | ||||
| } | ||||
							
								
								
									
										210
									
								
								benchmarks/coremark/tgc/core_portme.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								benchmarks/coremark/tgc/core_portme.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| /* | ||||
| Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
|  | ||||
| Original Author: Shay Gal-on | ||||
| */ | ||||
| /* Topic : Description | ||||
|         This file contains configuration constants required to execute on | ||||
|    different platforms | ||||
| */ | ||||
| #ifndef CORE_PORTME_H | ||||
| #define CORE_PORTME_H | ||||
| /************************/ | ||||
| /* Data types and settings */ | ||||
| /************************/ | ||||
| /* Configuration : HAS_FLOAT | ||||
|         Define to 1 if the platform supports floating point. | ||||
| */ | ||||
| #ifndef HAS_FLOAT | ||||
| #define HAS_FLOAT 0 | ||||
| #endif | ||||
| /* Configuration : HAS_TIME_H | ||||
|         Define to 1 if platform has the time.h header file, | ||||
|         and implementation of functions thereof. | ||||
| */ | ||||
| #ifndef HAS_TIME_H | ||||
| #define HAS_TIME_H 0 | ||||
| #endif | ||||
| /* Configuration : USE_CLOCK | ||||
|         Define to 1 if platform has the time.h header file, | ||||
|         and implementation of functions thereof. | ||||
| */ | ||||
| #ifndef USE_CLOCK | ||||
| #define USE_CLOCK 0 | ||||
| #endif | ||||
| /* Configuration : HAS_STDIO | ||||
|         Define to 1 if the platform has stdio.h. | ||||
| */ | ||||
| #ifndef HAS_STDIO | ||||
| #define HAS_STDIO 0 | ||||
| #endif | ||||
| /* Configuration : HAS_PRINTF | ||||
|         Define to 1 if the platform has stdio.h and implements the printf | ||||
|    function. | ||||
| */ | ||||
| #ifndef HAS_PRINTF | ||||
| #define HAS_PRINTF 0 | ||||
| #endif | ||||
|  | ||||
| /* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION | ||||
|         Initialize these strings per platform | ||||
| */ | ||||
| #ifndef COMPILER_VERSION | ||||
| #ifdef __GNUC__ | ||||
| #define COMPILER_VERSION "GCC"__VERSION__ | ||||
| #else | ||||
| #define COMPILER_VERSION "Please put compiler version here (e.g. gcc 4.1)" | ||||
| #endif | ||||
| #endif | ||||
| #ifndef COMPILER_FLAGS | ||||
| #define COMPILER_FLAGS \ | ||||
|     FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */ | ||||
| #endif | ||||
| #ifndef MEM_LOCATION | ||||
| #define MEM_LOCATION "STACK" | ||||
| #endif | ||||
|  | ||||
| /* Data Types : | ||||
|         To avoid compiler issues, define the data types that need ot be used for | ||||
|    8b, 16b and 32b in <core_portme.h>. | ||||
|  | ||||
|         *Imprtant* : | ||||
|         ee_ptr_int needs to be the data type used to hold pointers, otherwise | ||||
|    coremark may fail!!! | ||||
| */ | ||||
| typedef signed short   ee_s16; | ||||
| typedef unsigned short ee_u16; | ||||
| typedef signed int     ee_s32; | ||||
| typedef double         ee_f32; | ||||
| typedef unsigned char  ee_u8; | ||||
| typedef unsigned int   ee_u32; | ||||
| typedef ee_u32         ee_ptr_int; | ||||
| typedef ee_u32         ee_size_t; | ||||
| #define NULL ((void *)0) | ||||
| /* align_mem : | ||||
|         This macro is used to align an offset to point to a 32b value. It is | ||||
|    used in the Matrix algorithm to initialize the input memory blocks. | ||||
| */ | ||||
| #define align_mem(x) (void *)(4 + (((ee_ptr_int)(x)-1) & ~3)) | ||||
|  | ||||
| /* Configuration : CORE_TICKS | ||||
|         Define type of return from the timing functions. | ||||
|  */ | ||||
| #define CORETIMETYPE ee_u32 | ||||
| typedef ee_u32 CORE_TICKS; | ||||
|  | ||||
| /* Configuration : SEED_METHOD | ||||
|         Defines method to get seed values that cannot be computed at compile | ||||
|    time. | ||||
|  | ||||
|         Valid values : | ||||
|         SEED_ARG - from command line. | ||||
|         SEED_FUNC - from a system function. | ||||
|         SEED_VOLATILE - from volatile variables. | ||||
| */ | ||||
| #ifndef SEED_METHOD | ||||
| #define SEED_METHOD SEED_VOLATILE | ||||
| #endif | ||||
|  | ||||
| /* Configuration : MEM_METHOD | ||||
|         Defines method to get a block of memry. | ||||
|  | ||||
|         Valid values : | ||||
|         MEM_MALLOC - for platforms that implement malloc and have malloc.h. | ||||
|         MEM_STATIC - to use a static memory array. | ||||
|         MEM_STACK - to allocate the data block on the stack (NYI). | ||||
| */ | ||||
| #ifndef MEM_METHOD | ||||
| #define MEM_METHOD MEM_STACK | ||||
| #endif | ||||
|  | ||||
| /* Configuration : MULTITHREAD | ||||
|         Define for parallel execution | ||||
|  | ||||
|         Valid values : | ||||
|         1 - only one context (default). | ||||
|         N>1 - will execute N copies in parallel. | ||||
|  | ||||
|         Note : | ||||
|         If this flag is defined to more then 1, an implementation for launching | ||||
|    parallel contexts must be defined. | ||||
|  | ||||
|         Two sample implementations are provided. Use <USE_PTHREAD> or <USE_FORK> | ||||
|    to enable them. | ||||
|  | ||||
|         It is valid to have a different implementation of <core_start_parallel> | ||||
|    and <core_end_parallel> in <core_portme.c>, to fit a particular architecture. | ||||
| */ | ||||
| #ifndef MULTITHREAD | ||||
| #define MULTITHREAD 1 | ||||
| #define USE_PTHREAD 0 | ||||
| #define USE_FORK    0 | ||||
| #define USE_SOCKET  0 | ||||
| #endif | ||||
|  | ||||
| /* Configuration : MAIN_HAS_NOARGC | ||||
|         Needed if platform does not support getting arguments to main. | ||||
|  | ||||
|         Valid values : | ||||
|         0 - argc/argv to main is supported | ||||
|         1 - argc/argv to main is not supported | ||||
|  | ||||
|         Note : | ||||
|         This flag only matters if MULTITHREAD has been defined to a value | ||||
|    greater then 1. | ||||
| */ | ||||
| #ifndef MAIN_HAS_NOARGC | ||||
| #define MAIN_HAS_NOARGC 0 | ||||
| #endif | ||||
|  | ||||
| /* Configuration : MAIN_HAS_NORETURN | ||||
|         Needed if platform does not support returning a value from main. | ||||
|  | ||||
|         Valid values : | ||||
|         0 - main returns an int, and return value will be 0. | ||||
|         1 - platform does not support returning a value from main | ||||
| */ | ||||
| #ifndef MAIN_HAS_NORETURN | ||||
| #define MAIN_HAS_NORETURN 0 | ||||
| #endif | ||||
|  | ||||
| /* Variable : default_num_contexts | ||||
|         Not used for this simple port, must cintain the value 1. | ||||
| */ | ||||
| extern ee_u32 default_num_contexts; | ||||
|  | ||||
| typedef struct CORE_PORTABLE_S | ||||
| { | ||||
|     ee_u8 portable_id; | ||||
| } core_portable; | ||||
|  | ||||
| /* target specific init/fini */ | ||||
| void portable_init(core_portable *p, int *argc, char *argv[]); | ||||
| void portable_fini(core_portable *p); | ||||
|  | ||||
| #if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) \ | ||||
|     && !defined(VALIDATION_RUN) | ||||
| #if (TOTAL_DATA_SIZE == 1200) | ||||
| #define PROFILE_RUN 1 | ||||
| #elif (TOTAL_DATA_SIZE == 2000) | ||||
| #define PERFORMANCE_RUN 1 | ||||
| #else | ||||
| #define VALIDATION_RUN 1 | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| int ee_printf(const char *fmt, ...); | ||||
|  | ||||
| #endif /* CORE_PORTME_H */ | ||||
							
								
								
									
										94
									
								
								benchmarks/coremark/tgc/core_portme.mak
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										94
									
								
								benchmarks/coremark/tgc/core_portme.mak
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| # Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #    http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| #  | ||||
| # Original Author: Shay Gal-on | ||||
|  | ||||
| #File : core_portme.mak | ||||
| ISA?=imc | ||||
| RISCV_ARCH:=rv32$(ISA) | ||||
| RISCV_ABI:=ilp32 | ||||
|  | ||||
| # Flag : OUTFLAG | ||||
| #	Use this flag to define how to to get an executable (e.g -o) | ||||
| OUTFLAG= -o | ||||
| # Flag : CC | ||||
| #	Use this flag to define compiler to use | ||||
| CC 		= riscv32-unknown-elf-gcc | ||||
| # Flag : LD | ||||
| #	Use this flag to define compiler to use | ||||
| LD		= riscv32-unknown-elf-gcc | ||||
| # Flag : AS | ||||
| #	Use this flag to define compiler to use | ||||
| AS		= riscv32-unknown-elf-as | ||||
| # 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 = -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI) -O3 -DCLOCKS_PER_SEC=10000000 -nostdlib -nostartfiles -nodefaultlibs \ | ||||
|  -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las -flto | ||||
| FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)" | ||||
| CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\"  | ||||
| #Flag : LFLAGS_END | ||||
| #	Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).  | ||||
| #	Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt. | ||||
| SEPARATE_COMPILE=1 | ||||
| # Flag : SEPARATE_COMPILE | ||||
| # You must also define below how to create an object file, and how to link. | ||||
| OBJOUT 	= -o | ||||
| LFLAGS 	=  | ||||
| #--specs=nano.specs -march=$(RISCV_ARCH) -mabi=$(RISCV_ABI)  | ||||
| ASFLAGS = | ||||
| OFLAG 	= -o | ||||
| COUT 	= -c | ||||
|  | ||||
| LFLAGS_END =  | ||||
| # Flag : PORT_SRCS | ||||
| # 	Port specific source files can be added here | ||||
| #	You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler! | ||||
| PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c | ||||
| vpath %.c $(PORT_DIR) | ||||
| vpath %.s $(PORT_DIR) | ||||
| PORT_OBJS = core_portme.o ee_printf.o | ||||
| # Flag : LOAD | ||||
| #	For a simple port, we assume self hosted compile and run, no load needed. | ||||
|  | ||||
| # Flag : RUN | ||||
| #	For a simple port, we assume self hosted compile and run, simple invocation of the executable | ||||
|  | ||||
| LOAD = echo "" | ||||
| RUN = echo "" | ||||
|  | ||||
| OEXT = .o | ||||
| EXE = .elf | ||||
|  | ||||
| $(OPATH)$(PORT_DIR)/%$(OEXT) : %.c | ||||
| 	$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@ | ||||
|  | ||||
| $(OPATH)%$(OEXT) : %.c | ||||
| 	$(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@ | ||||
|  | ||||
| $(OPATH)$(PORT_DIR)/%$(OEXT) : %.s | ||||
| 	$(AS) $(ASFLAGS) $< $(OBJOUT) $@ | ||||
|  | ||||
| # Target : port_pre% and port_post% | ||||
| # For the purpose of this simple port, no pre or post steps needed. | ||||
|  | ||||
| .PHONY : port_prebuild port_postbuild port_prerun port_postrun port_preload port_postload | ||||
| port_pre% port_post% :  | ||||
|  | ||||
| # FLAG : OPATH | ||||
| # Path to the output folder. Default - current folder. | ||||
| OPATH = ./ | ||||
| MKDIR = mkdir -p | ||||
|  | ||||
| dist-clean: clean | ||||
| 	rm -f *.o | ||||
							
								
								
									
										127
									
								
								benchmarks/coremark/tgc/cvt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								benchmarks/coremark/tgc/cvt.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| /* | ||||
| Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
| #include <math.h> | ||||
| #define CVTBUFSIZE 80 | ||||
| static char CVTBUF[CVTBUFSIZE]; | ||||
|  | ||||
| static char * | ||||
| cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag) | ||||
| { | ||||
|     int    r2; | ||||
|     double fi, fj; | ||||
|     char * p, *p1; | ||||
|  | ||||
|     if (ndigits < 0) | ||||
|         ndigits = 0; | ||||
|     if (ndigits >= CVTBUFSIZE - 1) | ||||
|         ndigits = CVTBUFSIZE - 2; | ||||
|     r2    = 0; | ||||
|     *sign = 0; | ||||
|     p     = &buf[0]; | ||||
|     if (arg < 0) | ||||
|     { | ||||
|         *sign = 1; | ||||
|         arg   = -arg; | ||||
|     } | ||||
|     arg = modf(arg, &fi); | ||||
|     p1  = &buf[CVTBUFSIZE]; | ||||
|  | ||||
|     if (fi != 0) | ||||
|     { | ||||
|         p1 = &buf[CVTBUFSIZE]; | ||||
|         while (fi != 0) | ||||
|         { | ||||
|             fj    = modf(fi / 10, &fi); | ||||
|             *--p1 = (int)((fj + .03) * 10) + '0'; | ||||
|             r2++; | ||||
|         } | ||||
|         while (p1 < &buf[CVTBUFSIZE]) | ||||
|             *p++ = *p1++; | ||||
|     } | ||||
|     else if (arg > 0) | ||||
|     { | ||||
|         while ((fj = arg * 10) < 1) | ||||
|         { | ||||
|             arg = fj; | ||||
|             r2--; | ||||
|         } | ||||
|     } | ||||
|     p1 = &buf[ndigits]; | ||||
|     if (eflag == 0) | ||||
|         p1 += r2; | ||||
|     *decpt = r2; | ||||
|     if (p1 < &buf[0]) | ||||
|     { | ||||
|         buf[0] = '\0'; | ||||
|         return buf; | ||||
|     } | ||||
|     while (p <= p1 && p < &buf[CVTBUFSIZE]) | ||||
|     { | ||||
|         arg *= 10; | ||||
|         arg  = modf(arg, &fj); | ||||
|         *p++ = (int)fj + '0'; | ||||
|     } | ||||
|     if (p1 >= &buf[CVTBUFSIZE]) | ||||
|     { | ||||
|         buf[CVTBUFSIZE - 1] = '\0'; | ||||
|         return buf; | ||||
|     } | ||||
|     p = p1; | ||||
|     *p1 += 5; | ||||
|     while (*p1 > '9') | ||||
|     { | ||||
|         *p1 = '0'; | ||||
|         if (p1 > buf) | ||||
|             ++*--p1; | ||||
|         else | ||||
|         { | ||||
|             *p1 = '1'; | ||||
|             (*decpt)++; | ||||
|             if (eflag == 0) | ||||
|             { | ||||
|                 if (p > buf) | ||||
|                     *p = '0'; | ||||
|                 p++; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     *p = '\0'; | ||||
|     return buf; | ||||
| } | ||||
|  | ||||
| char * | ||||
| ecvt(double arg, int ndigits, int *decpt, int *sign) | ||||
| { | ||||
|     return cvt(arg, ndigits, decpt, sign, CVTBUF, 1); | ||||
| } | ||||
|  | ||||
| char * | ||||
| ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf) | ||||
| { | ||||
|     return cvt(arg, ndigits, decpt, sign, buf, 1); | ||||
| } | ||||
|  | ||||
| char * | ||||
| fcvt(double arg, int ndigits, int *decpt, int *sign) | ||||
| { | ||||
|     return cvt(arg, ndigits, decpt, sign, CVTBUF, 0); | ||||
| } | ||||
|  | ||||
| char * | ||||
| fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf) | ||||
| { | ||||
|     return cvt(arg, ndigits, decpt, sign, buf, 0); | ||||
| } | ||||
							
								
								
									
										701
									
								
								benchmarks/coremark/tgc/ee_printf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										701
									
								
								benchmarks/coremark/tgc/ee_printf.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,701 @@ | ||||
| /* | ||||
| Copyright 2018 Embedded Microprocessor Benchmark Consortium (EEMBC) | ||||
|  | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
|  | ||||
|     http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
|  | ||||
| #include <coremark.h> | ||||
| #include <stdarg.h> | ||||
|  | ||||
| #define ZEROPAD   (1 << 0) /* Pad with zero */ | ||||
| #define SIGN      (1 << 1) /* Unsigned/signed long */ | ||||
| #define PLUS      (1 << 2) /* Show plus */ | ||||
| #define SPACE     (1 << 3) /* Spacer */ | ||||
| #define LEFT      (1 << 4) /* Left justified */ | ||||
| #define HEX_PREP  (1 << 5) /* 0x */ | ||||
| #define UPPERCASE (1 << 6) /* 'ABCDEF' */ | ||||
|  | ||||
| #define is_digit(c) ((c) >= '0' && (c) <= '9') | ||||
|  | ||||
| static char *    digits       = "0123456789abcdefghijklmnopqrstuvwxyz"; | ||||
| static char *    upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||||
| static ee_size_t strnlen(const char *s, ee_size_t count); | ||||
|  | ||||
| static ee_size_t | ||||
| strnlen(const char *s, ee_size_t count) | ||||
| { | ||||
|     const char *sc; | ||||
|     for (sc = s; *sc != '\0' && count--; ++sc) | ||||
|         ; | ||||
|     return sc - s; | ||||
| } | ||||
|  | ||||
| static int | ||||
| skip_atoi(const char **s) | ||||
| { | ||||
|     int i = 0; | ||||
|     while (is_digit(**s)) | ||||
|         i = i * 10 + *((*s)++) - '0'; | ||||
|     return i; | ||||
| } | ||||
|  | ||||
| static char * | ||||
| number(char *str, long num, int base, int size, int precision, int type) | ||||
| { | ||||
|     char  c, sign, tmp[66]; | ||||
|     char *dig = digits; | ||||
|     int   i; | ||||
|  | ||||
|     if (type & UPPERCASE) | ||||
|         dig = upper_digits; | ||||
|     if (type & LEFT) | ||||
|         type &= ~ZEROPAD; | ||||
|     if (base < 2 || base > 36) | ||||
|         return 0; | ||||
|  | ||||
|     c    = (type & ZEROPAD) ? '0' : ' '; | ||||
|     sign = 0; | ||||
|     if (type & SIGN) | ||||
|     { | ||||
|         if (num < 0) | ||||
|         { | ||||
|             sign = '-'; | ||||
|             num  = -num; | ||||
|             size--; | ||||
|         } | ||||
|         else if (type & PLUS) | ||||
|         { | ||||
|             sign = '+'; | ||||
|             size--; | ||||
|         } | ||||
|         else if (type & SPACE) | ||||
|         { | ||||
|             sign = ' '; | ||||
|             size--; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (type & HEX_PREP) | ||||
|     { | ||||
|         if (base == 16) | ||||
|             size -= 2; | ||||
|         else if (base == 8) | ||||
|             size--; | ||||
|     } | ||||
|  | ||||
|     i = 0; | ||||
|  | ||||
|     if (num == 0) | ||||
|         tmp[i++] = '0'; | ||||
|     else | ||||
|     { | ||||
|         while (num != 0) | ||||
|         { | ||||
|             tmp[i++] = dig[((unsigned long)num) % (unsigned)base]; | ||||
|             num      = ((unsigned long)num) / (unsigned)base; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (i > precision) | ||||
|         precision = i; | ||||
|     size -= precision; | ||||
|     if (!(type & (ZEROPAD | LEFT))) | ||||
|         while (size-- > 0) | ||||
|             *str++ = ' '; | ||||
|     if (sign) | ||||
|         *str++ = sign; | ||||
|  | ||||
|     if (type & HEX_PREP) | ||||
|     { | ||||
|         if (base == 8) | ||||
|             *str++ = '0'; | ||||
|         else if (base == 16) | ||||
|         { | ||||
|             *str++ = '0'; | ||||
|             *str++ = digits[33]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!(type & LEFT)) | ||||
|         while (size-- > 0) | ||||
|             *str++ = c; | ||||
|     while (i < precision--) | ||||
|         *str++ = '0'; | ||||
|     while (i-- > 0) | ||||
|         *str++ = tmp[i]; | ||||
|     while (size-- > 0) | ||||
|         *str++ = ' '; | ||||
|  | ||||
|     return str; | ||||
| } | ||||
|  | ||||
| static char * | ||||
| eaddr(char *str, unsigned char *addr, int size, int precision, int type) | ||||
| { | ||||
|     char  tmp[24]; | ||||
|     char *dig = digits; | ||||
|     int   i, len; | ||||
|  | ||||
|     if (type & UPPERCASE) | ||||
|         dig = upper_digits; | ||||
|     len = 0; | ||||
|     for (i = 0; i < 6; i++) | ||||
|     { | ||||
|         if (i != 0) | ||||
|             tmp[len++] = ':'; | ||||
|         tmp[len++] = dig[addr[i] >> 4]; | ||||
|         tmp[len++] = dig[addr[i] & 0x0F]; | ||||
|     } | ||||
|  | ||||
|     if (!(type & LEFT)) | ||||
|         while (len < size--) | ||||
|             *str++ = ' '; | ||||
|     for (i = 0; i < len; ++i) | ||||
|         *str++ = tmp[i]; | ||||
|     while (len < size--) | ||||
|         *str++ = ' '; | ||||
|  | ||||
|     return str; | ||||
| } | ||||
|  | ||||
| static char * | ||||
| iaddr(char *str, unsigned char *addr, int size, int precision, int type) | ||||
| { | ||||
|     char tmp[24]; | ||||
|     int  i, n, len; | ||||
|  | ||||
|     len = 0; | ||||
|     for (i = 0; i < 4; i++) | ||||
|     { | ||||
|         if (i != 0) | ||||
|             tmp[len++] = '.'; | ||||
|         n = addr[i]; | ||||
|  | ||||
|         if (n == 0) | ||||
|             tmp[len++] = digits[0]; | ||||
|         else | ||||
|         { | ||||
|             if (n >= 100) | ||||
|             { | ||||
|                 tmp[len++] = digits[n / 100]; | ||||
|                 n          = n % 100; | ||||
|                 tmp[len++] = digits[n / 10]; | ||||
|                 n          = n % 10; | ||||
|             } | ||||
|             else if (n >= 10) | ||||
|             { | ||||
|                 tmp[len++] = digits[n / 10]; | ||||
|                 n          = n % 10; | ||||
|             } | ||||
|  | ||||
|             tmp[len++] = digits[n]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!(type & LEFT)) | ||||
|         while (len < size--) | ||||
|             *str++ = ' '; | ||||
|     for (i = 0; i < len; ++i) | ||||
|         *str++ = tmp[i]; | ||||
|     while (len < size--) | ||||
|         *str++ = ' '; | ||||
|  | ||||
|     return str; | ||||
| } | ||||
|  | ||||
| #if HAS_FLOAT | ||||
|  | ||||
| char *      ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); | ||||
| char *      fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf); | ||||
| static void ee_bufcpy(char *d, char *s, int count); | ||||
|  | ||||
| void | ||||
| ee_bufcpy(char *pd, char *ps, int count) | ||||
| { | ||||
|     char *pe = ps + count; | ||||
|     while (ps != pe) | ||||
|         *pd++ = *ps++; | ||||
| } | ||||
|  | ||||
| static void | ||||
| parse_float(double value, char *buffer, char fmt, int precision) | ||||
| { | ||||
|     int   decpt, sign, exp, pos; | ||||
|     char *digits = NULL; | ||||
|     char  cvtbuf[80]; | ||||
|     int   capexp = 0; | ||||
|     int   magnitude; | ||||
|  | ||||
|     if (fmt == 'G' || fmt == 'E') | ||||
|     { | ||||
|         capexp = 1; | ||||
|         fmt += 'a' - 'A'; | ||||
|     } | ||||
|  | ||||
|     if (fmt == 'g') | ||||
|     { | ||||
|         digits    = ecvtbuf(value, precision, &decpt, &sign, cvtbuf); | ||||
|         magnitude = decpt - 1; | ||||
|         if (magnitude < -4 || magnitude > precision - 1) | ||||
|         { | ||||
|             fmt = 'e'; | ||||
|             precision -= 1; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             fmt = 'f'; | ||||
|             precision -= decpt; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (fmt == 'e') | ||||
|     { | ||||
|         digits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf); | ||||
|  | ||||
|         if (sign) | ||||
|             *buffer++ = '-'; | ||||
|         *buffer++ = *digits; | ||||
|         if (precision > 0) | ||||
|             *buffer++ = '.'; | ||||
|         ee_bufcpy(buffer, digits + 1, precision); | ||||
|         buffer += precision; | ||||
|         *buffer++ = capexp ? 'E' : 'e'; | ||||
|  | ||||
|         if (decpt == 0) | ||||
|         { | ||||
|             if (value == 0.0) | ||||
|                 exp = 0; | ||||
|             else | ||||
|                 exp = -1; | ||||
|         } | ||||
|         else | ||||
|             exp = decpt - 1; | ||||
|  | ||||
|         if (exp < 0) | ||||
|         { | ||||
|             *buffer++ = '-'; | ||||
|             exp       = -exp; | ||||
|         } | ||||
|         else | ||||
|             *buffer++ = '+'; | ||||
|  | ||||
|         buffer[2] = (exp % 10) + '0'; | ||||
|         exp       = exp / 10; | ||||
|         buffer[1] = (exp % 10) + '0'; | ||||
|         exp       = exp / 10; | ||||
|         buffer[0] = (exp % 10) + '0'; | ||||
|         buffer += 3; | ||||
|     } | ||||
|     else if (fmt == 'f') | ||||
|     { | ||||
|         digits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf); | ||||
|         if (sign) | ||||
|             *buffer++ = '-'; | ||||
|         if (*digits) | ||||
|         { | ||||
|             if (decpt <= 0) | ||||
|             { | ||||
|                 *buffer++ = '0'; | ||||
|                 *buffer++ = '.'; | ||||
|                 for (pos = 0; pos < -decpt; pos++) | ||||
|                     *buffer++ = '0'; | ||||
|                 while (*digits) | ||||
|                     *buffer++ = *digits++; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 pos = 0; | ||||
|                 while (*digits) | ||||
|                 { | ||||
|                     if (pos++ == decpt) | ||||
|                         *buffer++ = '.'; | ||||
|                     *buffer++ = *digits++; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             *buffer++ = '0'; | ||||
|             if (precision > 0) | ||||
|             { | ||||
|                 *buffer++ = '.'; | ||||
|                 for (pos = 0; pos < precision; pos++) | ||||
|                     *buffer++ = '0'; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     *buffer = '\0'; | ||||
| } | ||||
|  | ||||
| static void | ||||
| decimal_point(char *buffer) | ||||
| { | ||||
|     while (*buffer) | ||||
|     { | ||||
|         if (*buffer == '.') | ||||
|             return; | ||||
|         if (*buffer == 'e' || *buffer == 'E') | ||||
|             break; | ||||
|         buffer++; | ||||
|     } | ||||
|  | ||||
|     if (*buffer) | ||||
|     { | ||||
|         int n = strnlen(buffer, 256); | ||||
|         while (n > 0) | ||||
|         { | ||||
|             buffer[n + 1] = buffer[n]; | ||||
|             n--; | ||||
|         } | ||||
|  | ||||
|         *buffer = '.'; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         *buffer++ = '.'; | ||||
|         *buffer   = '\0'; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| cropzeros(char *buffer) | ||||
| { | ||||
|     char *stop; | ||||
|  | ||||
|     while (*buffer && *buffer != '.') | ||||
|         buffer++; | ||||
|     if (*buffer++) | ||||
|     { | ||||
|         while (*buffer && *buffer != 'e' && *buffer != 'E') | ||||
|             buffer++; | ||||
|         stop = buffer--; | ||||
|         while (*buffer == '0') | ||||
|             buffer--; | ||||
|         if (*buffer == '.') | ||||
|             buffer--; | ||||
|         while (buffer != stop) | ||||
|             *++buffer = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static char * | ||||
| flt(char *str, double num, int size, int precision, char fmt, int flags) | ||||
| { | ||||
|     char tmp[80]; | ||||
|     char c, sign; | ||||
|     int  n, i; | ||||
|  | ||||
|     // Left align means no zero padding | ||||
|     if (flags & LEFT) | ||||
|         flags &= ~ZEROPAD; | ||||
|  | ||||
|     // Determine padding and sign char | ||||
|     c    = (flags & ZEROPAD) ? '0' : ' '; | ||||
|     sign = 0; | ||||
|     if (flags & SIGN) | ||||
|     { | ||||
|         if (num < 0.0) | ||||
|         { | ||||
|             sign = '-'; | ||||
|             num  = -num; | ||||
|             size--; | ||||
|         } | ||||
|         else if (flags & PLUS) | ||||
|         { | ||||
|             sign = '+'; | ||||
|             size--; | ||||
|         } | ||||
|         else if (flags & SPACE) | ||||
|         { | ||||
|             sign = ' '; | ||||
|             size--; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Compute the precision value | ||||
|     if (precision < 0) | ||||
|         precision = 6; // Default precision: 6 | ||||
|  | ||||
|     // Convert floating point number to text | ||||
|     parse_float(num, tmp, fmt, precision); | ||||
|  | ||||
|     if ((flags & HEX_PREP) && precision == 0) | ||||
|         decimal_point(tmp); | ||||
|     if (fmt == 'g' && !(flags & HEX_PREP)) | ||||
|         cropzeros(tmp); | ||||
|  | ||||
|     n = strnlen(tmp, 256); | ||||
|  | ||||
|     // Output number with alignment and padding | ||||
|     size -= n; | ||||
|     if (!(flags & (ZEROPAD | LEFT))) | ||||
|         while (size-- > 0) | ||||
|             *str++ = ' '; | ||||
|     if (sign) | ||||
|         *str++ = sign; | ||||
|     if (!(flags & LEFT)) | ||||
|         while (size-- > 0) | ||||
|             *str++ = c; | ||||
|     for (i = 0; i < n; i++) | ||||
|         *str++ = tmp[i]; | ||||
|     while (size-- > 0) | ||||
|         *str++ = ' '; | ||||
|  | ||||
|     return str; | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| static int | ||||
| ee_vsprintf(char *buf, const char *fmt, va_list args) | ||||
| { | ||||
|     int           len; | ||||
|     unsigned long num; | ||||
|     int           i, base; | ||||
|     char *        str; | ||||
|     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 | ||||
|  | ||||
|     for (str = buf; *fmt; fmt++) | ||||
|     { | ||||
|         if (*fmt != '%') | ||||
|         { | ||||
|             *str++ = *fmt; | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         // Process flags | ||||
|         flags = 0; | ||||
|     repeat: | ||||
|         fmt++; // This also skips first '%' | ||||
|         switch (*fmt) | ||||
|         { | ||||
|             case '-': | ||||
|                 flags |= LEFT; | ||||
|                 goto repeat; | ||||
|             case '+': | ||||
|                 flags |= PLUS; | ||||
|                 goto repeat; | ||||
|             case ' ': | ||||
|                 flags |= SPACE; | ||||
|                 goto repeat; | ||||
|             case '#': | ||||
|                 flags |= HEX_PREP; | ||||
|                 goto repeat; | ||||
|             case '0': | ||||
|                 flags |= ZEROPAD; | ||||
|                 goto repeat; | ||||
|         } | ||||
|  | ||||
|         // Get field width | ||||
|         field_width = -1; | ||||
|         if (is_digit(*fmt)) | ||||
|             field_width = skip_atoi(&fmt); | ||||
|         else if (*fmt == '*') | ||||
|         { | ||||
|             fmt++; | ||||
|             field_width = va_arg(args, int); | ||||
|             if (field_width < 0) | ||||
|             { | ||||
|                 field_width = -field_width; | ||||
|                 flags |= LEFT; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Get the precision | ||||
|         precision = -1; | ||||
|         if (*fmt == '.') | ||||
|         { | ||||
|             ++fmt; | ||||
|             if (is_digit(*fmt)) | ||||
|                 precision = skip_atoi(&fmt); | ||||
|             else if (*fmt == '*') | ||||
|             { | ||||
|                 ++fmt; | ||||
|                 precision = va_arg(args, int); | ||||
|             } | ||||
|             if (precision < 0) | ||||
|                 precision = 0; | ||||
|         } | ||||
|  | ||||
|         // Get the conversion qualifier | ||||
|         qualifier = -1; | ||||
|         if (*fmt == 'l' || *fmt == 'L') | ||||
|         { | ||||
|             qualifier = *fmt; | ||||
|             fmt++; | ||||
|         } | ||||
|  | ||||
|         // Default base | ||||
|         base = 10; | ||||
|  | ||||
|         switch (*fmt) | ||||
|         { | ||||
|             case 'c': | ||||
|                 if (!(flags & LEFT)) | ||||
|                     while (--field_width > 0) | ||||
|                         *str++ = ' '; | ||||
|                 *str++ = (unsigned char)va_arg(args, int); | ||||
|                 while (--field_width > 0) | ||||
|                     *str++ = ' '; | ||||
|                 continue; | ||||
|  | ||||
|             case 's': | ||||
|                 s = va_arg(args, char *); | ||||
|                 if (!s) | ||||
|                     s = "<NULL>"; | ||||
|                 len = strnlen(s, precision); | ||||
|                 if (!(flags & LEFT)) | ||||
|                     while (len < field_width--) | ||||
|                         *str++ = ' '; | ||||
|                 for (i = 0; i < len; ++i) | ||||
|                     *str++ = *s++; | ||||
|                 while (len < field_width--) | ||||
|                     *str++ = ' '; | ||||
|                 continue; | ||||
|  | ||||
|             case 'p': | ||||
|                 if (field_width == -1) | ||||
|                 { | ||||
|                     field_width = 2 * sizeof(void *); | ||||
|                     flags |= ZEROPAD; | ||||
|                 } | ||||
|                 str = number(str, | ||||
|                              (unsigned long)va_arg(args, void *), | ||||
|                              16, | ||||
|                              field_width, | ||||
|                              precision, | ||||
|                              flags); | ||||
|                 continue; | ||||
|  | ||||
|             case 'A': | ||||
|                 flags |= UPPERCASE; | ||||
|  | ||||
|             case 'a': | ||||
|                 if (qualifier == 'l') | ||||
|                     str = eaddr(str, | ||||
|                                 va_arg(args, unsigned char *), | ||||
|                                 field_width, | ||||
|                                 precision, | ||||
|                                 flags); | ||||
|                 else | ||||
|                     str = iaddr(str, | ||||
|                                 va_arg(args, unsigned char *), | ||||
|                                 field_width, | ||||
|                                 precision, | ||||
|                                 flags); | ||||
|                 continue; | ||||
|  | ||||
|             // Integer number formats - set up the flags and "break" | ||||
|             case 'o': | ||||
|                 base = 8; | ||||
|                 break; | ||||
|  | ||||
|             case 'X': | ||||
|                 flags |= UPPERCASE; | ||||
|  | ||||
|             case 'x': | ||||
|                 base = 16; | ||||
|                 break; | ||||
|  | ||||
|             case 'd': | ||||
|             case 'i': | ||||
|                 flags |= SIGN; | ||||
|  | ||||
|             case 'u': | ||||
|                 break; | ||||
|  | ||||
| #if HAS_FLOAT | ||||
|  | ||||
|             case 'f': | ||||
|                 str = flt(str, | ||||
|                           va_arg(args, double), | ||||
|                           field_width, | ||||
|                           precision, | ||||
|                           *fmt, | ||||
|                           flags | SIGN); | ||||
|                 continue; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|             default: | ||||
|                 if (*fmt != '%') | ||||
|                     *str++ = '%'; | ||||
|                 if (*fmt) | ||||
|                     *str++ = *fmt; | ||||
|                 else | ||||
|                     --fmt; | ||||
|                 continue; | ||||
|         } | ||||
|  | ||||
|         if (qualifier == 'l') | ||||
|             num = va_arg(args, unsigned long); | ||||
|         else if (flags & SIGN) | ||||
|             num = va_arg(args, int); | ||||
|         else | ||||
|             num = va_arg(args, unsigned int); | ||||
|  | ||||
|         str = number(str, num, base, field_width, precision, flags); | ||||
|     } | ||||
|  | ||||
|     *str = '\0'; | ||||
|     return str - buf; | ||||
| } | ||||
|  | ||||
| #define UART0_BASE_ADDR 0xffff0000ULL | ||||
|  | ||||
| #define UART_REG_TXFIFO         0x00 | ||||
| #define UART_REG_RXFIFO         0x04 | ||||
| #define UART_REG_TXCTRL         0x08 | ||||
| #define UART_REG_RXCTRL         0x0c | ||||
| #define UART_REG_IE             0x10 | ||||
| #define UART_REG_IP             0x14 | ||||
| #define UART_REG_DIV            0x18 | ||||
| #define UART_TXEN               0x1 | ||||
|  | ||||
| #define UART0_REG(ADDR) *((ee_u32*) (UART0_BASE_ADDR + ADDR)) | ||||
|  | ||||
| void | ||||
| uart_send_char(char c) | ||||
| { | ||||
|       while (UART0_REG(UART_REG_TXFIFO) & 0x80000000) ; | ||||
|       UART0_REG(UART_REG_TXFIFO) = (unsigned char)c; | ||||
| } | ||||
|  | ||||
| int | ||||
| ee_printf(const char *fmt, ...) | ||||
| { | ||||
|     char    buf[1024], *p; | ||||
|     va_list args; | ||||
|     int     n = 0; | ||||
|  | ||||
|     va_start(args, fmt); | ||||
|     ee_vsprintf(buf, fmt, args); | ||||
|     va_end(args); | ||||
|     p = buf; | ||||
|     while (*p) | ||||
|     { | ||||
|         uart_send_char(*p); | ||||
|         n++; | ||||
|         p++; | ||||
|     } | ||||
|  | ||||
|     return n; | ||||
| } | ||||
							
								
								
									
										241
									
								
								benchmarks/coremark/tgc/tgc.lds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								benchmarks/coremark/tgc/tgc.lds
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,241 @@ | ||||
| OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") | ||||
| OUTPUT_ARCH(riscv) | ||||
| MEMORY | ||||
| { | ||||
|    RAM (rwx)  : ORIGIN = 0x0, LENGTH = 128M  | ||||
| } | ||||
|  | ||||
| ENTRY(_start) | ||||
|  | ||||
| SECTIONS | ||||
| { | ||||
|   /* Read-only sections, merged into text segment: */ | ||||
|   .interp         : { *(.interp) } | ||||
|   .note.gnu.build-id  : { *(.note.gnu.build-id) } | ||||
|   .hash           : { *(.hash) } | ||||
|   .gnu.hash       : { *(.gnu.hash) } | ||||
|   .dynsym         : { *(.dynsym) } | ||||
|   .dynstr         : { *(.dynstr) } | ||||
|   .gnu.version    : { *(.gnu.version) } | ||||
|   .gnu.version_d  : { *(.gnu.version_d) } | ||||
|   .gnu.version_r  : { *(.gnu.version_r) } | ||||
|   .rela.dyn       : | ||||
|     { | ||||
|       *(.rela.init) | ||||
|       *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) | ||||
|       *(.rela.fini) | ||||
|       *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) | ||||
|       *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) | ||||
|       *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) | ||||
|       *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) | ||||
|       *(.rela.ctors) | ||||
|       *(.rela.dtors) | ||||
|       *(.rela.got) | ||||
|       *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) | ||||
|       *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) | ||||
|       *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) | ||||
|       *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) | ||||
|       *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) | ||||
|       PROVIDE_HIDDEN (__rela_iplt_start = .); | ||||
|       *(.rela.iplt) | ||||
|       PROVIDE_HIDDEN (__rela_iplt_end = .); | ||||
|     } | ||||
|   .rela.plt       : | ||||
|     { | ||||
|       *(.rela.plt) | ||||
|     } | ||||
|   .plt            : { *(.plt) } | ||||
|   .iplt           : { *(.iplt) } | ||||
|   .init           : | ||||
|   { | ||||
|     KEEP (*(SORT_NONE(.init))) | ||||
|     *crt0.o(.text .text.*) | ||||
|   } > RAM | ||||
|   .text      : | ||||
|   { | ||||
|     *(.text.init) | ||||
|     *(.text.unlikely .text.*_unlikely .text.unlikely.*) | ||||
|     *(.text.exit .text.exit.*) | ||||
|     *(.text.startup .text.startup.*) | ||||
|     *(.text.hot .text.hot.*) | ||||
|     *(.text .stub .text.* .gnu.linkonce.t.*) | ||||
|     /* .gnu.warning sections are handled specially by elf32.em.  */ | ||||
|     *(.gnu.warning) | ||||
|   } | ||||
|   .fini           : | ||||
|   { | ||||
|     KEEP (*(SORT_NONE(.fini))) | ||||
|   } | ||||
|   PROVIDE (__etext = .); | ||||
|   PROVIDE (_etext = .); | ||||
|   PROVIDE (etext = .); | ||||
|   .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) } | ||||
|   .rodata1        : { *(.rodata1) } | ||||
|   .sdata2         : | ||||
|   { | ||||
|     *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) | ||||
|   } | ||||
|   .sbss2          : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } | ||||
|   .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } | ||||
|   .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } | ||||
|   .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } | ||||
|   .gnu_extab   : ONLY_IF_RO { *(.gnu_extab*) } | ||||
|   /* These sections are generated by the Sun/Oracle C++ compiler.  */ | ||||
|   .exception_ranges   : ONLY_IF_RO { *(.exception_ranges*) } | ||||
|   /* Adjust the address for the data segment.  We want to adjust up to | ||||
|      the same address within the page on the next page up.  */ | ||||
|   . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); | ||||
|   /* Exception handling  */ | ||||
|   .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } | ||||
|   .gnu_extab      : ONLY_IF_RW { *(.gnu_extab) } | ||||
|   .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } | ||||
|   .exception_ranges   : ONLY_IF_RW { *(.exception_ranges*) } | ||||
|   /* Thread Local Storage sections  */ | ||||
|   .tdata	  : | ||||
|    { | ||||
|      PROVIDE_HIDDEN (__tdata_start = .); | ||||
|      *(.tdata .tdata.* .gnu.linkonce.td.*) | ||||
|    } | ||||
|   .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } | ||||
|   .preinit_array    : | ||||
|   { | ||||
|     PROVIDE_HIDDEN (__preinit_array_start = .); | ||||
|     KEEP (*(.preinit_array)) | ||||
|     PROVIDE_HIDDEN (__preinit_array_end = .); | ||||
|   } | ||||
|   .init_array    : | ||||
|   { | ||||
|     PROVIDE_HIDDEN (__init_array_start = .); | ||||
|     KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) | ||||
|     KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) | ||||
|     PROVIDE_HIDDEN (__init_array_end = .); | ||||
|   } | ||||
|   .fini_array    : | ||||
|   { | ||||
|     PROVIDE_HIDDEN (__fini_array_start = .); | ||||
|     KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) | ||||
|     KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) | ||||
|     PROVIDE_HIDDEN (__fini_array_end = .); | ||||
|   } | ||||
|   .ctors          : | ||||
|   { | ||||
|     /* gcc uses crtbegin.o to find the start of | ||||
|        the constructors, so we make sure it is | ||||
|        first.  Because this is a wildcard, it | ||||
|        doesn't matter if the user does not | ||||
|        actually link against crtbegin.o; the | ||||
|        linker won't look for a file to match a | ||||
|        wildcard.  The wildcard also means that it | ||||
|        doesn't matter which directory crtbegin.o | ||||
|        is in.  */ | ||||
|     KEEP (*crtbegin.o(.ctors)) | ||||
|     KEEP (*crtbegin?.o(.ctors)) | ||||
|     /* We don't want to include the .ctor section from | ||||
|        the crtend.o file until after the sorted ctors. | ||||
|        The .ctor section from the crtend file contains the | ||||
|        end of ctors marker and it must be last */ | ||||
|     KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) | ||||
|     KEEP (*(SORT(.ctors.*))) | ||||
|     KEEP (*(.ctors)) | ||||
|   } | ||||
|   .dtors          : | ||||
|   { | ||||
|     KEEP (*crtbegin.o(.dtors)) | ||||
|     KEEP (*crtbegin?.o(.dtors)) | ||||
|     KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) | ||||
|     KEEP (*(SORT(.dtors.*))) | ||||
|     KEEP (*(.dtors)) | ||||
|   } | ||||
|   .jcr            : { KEEP (*(.jcr)) } | ||||
|   .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } | ||||
|   .dynamic        : { *(.dynamic) } | ||||
|   . = DATA_SEGMENT_RELRO_END (0, .); | ||||
|   .data           : | ||||
|   { | ||||
|     __DATA_BEGIN__ = .; | ||||
|     *(.data .data.* .gnu.linkonce.d.*) | ||||
|     SORT(CONSTRUCTORS) | ||||
|   } | ||||
|   .data1          : { *(.data1) } | ||||
|   .got            : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } | ||||
|   /* We want the small data sections together, so single-instruction offsets | ||||
|      can access them all, and initialized data all before uninitialized, so | ||||
|      we can shorten the on-disk segment size.  */ | ||||
|   .sdata          : | ||||
|   { | ||||
|     __SDATA_BEGIN__ = .; | ||||
|     *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) | ||||
|     *(.sdata .sdata.* .gnu.linkonce.s.*) | ||||
|   } | ||||
|   _edata = .; PROVIDE (edata = .); | ||||
|   . = .; | ||||
|   __bss_start = .; | ||||
|   .sbss           : | ||||
|   { | ||||
|     *(.dynsbss) | ||||
|     *(.sbss .sbss.* .gnu.linkonce.sb.*) | ||||
|     *(.scommon) | ||||
|   } | ||||
|   .bss            : | ||||
|   { | ||||
|    *(.dynbss) | ||||
|    *(.bss .bss.* .gnu.linkonce.b.*) | ||||
|    *(COMMON) | ||||
|    /* Align here to ensure that the .bss section occupies space up to | ||||
|       _end.  Align after .bss to ensure correct alignment even if the | ||||
|       .bss section disappears because there are no input sections. | ||||
|       FIXME: Why do we need it? When there is no .bss section, we do not | ||||
|       pad the .data section.  */ | ||||
|    . = ALIGN(. != 0 ? 32 / 8 : 1); | ||||
|   } | ||||
|   . = ALIGN(32 / 8); | ||||
|   . = SEGMENT_START("ldata-segment", .); | ||||
|   . = ALIGN(32 / 8); | ||||
|   __BSS_END__ = .; | ||||
|     __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800, | ||||
| 		            MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800)); | ||||
|   _end = .; PROVIDE (end = .); | ||||
|   . = DATA_SEGMENT_END (.); | ||||
|   /* Stabs debugging sections.  */ | ||||
|   .stab          0 : { *(.stab) } | ||||
|   .stabstr       0 : { *(.stabstr) } | ||||
|   .stab.excl     0 : { *(.stab.excl) } | ||||
|   .stab.exclstr  0 : { *(.stab.exclstr) } | ||||
|   .stab.index    0 : { *(.stab.index) } | ||||
|   .stab.indexstr 0 : { *(.stab.indexstr) } | ||||
|   .comment       0 : { *(.comment) } | ||||
|   .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } | ||||
|   /* DWARF debug sections. | ||||
|      Symbols in the DWARF debugging sections are relative to the beginning | ||||
|      of the section so we begin them at 0.  */ | ||||
|   /* DWARF 1 */ | ||||
|   .debug          0 : { *(.debug) } | ||||
|   .line           0 : { *(.line) } | ||||
|   /* GNU DWARF 1 extensions */ | ||||
|   .debug_srcinfo  0 : { *(.debug_srcinfo) } | ||||
|   .debug_sfnames  0 : { *(.debug_sfnames) } | ||||
|   /* DWARF 1.1 and DWARF 2 */ | ||||
|   .debug_aranges  0 : { *(.debug_aranges) } | ||||
|   .debug_pubnames 0 : { *(.debug_pubnames) } | ||||
|   /* DWARF 2 */ | ||||
|   .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) } | ||||
|   .debug_abbrev   0 : { *(.debug_abbrev) } | ||||
|   .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end) } | ||||
|   .debug_frame    0 : { *(.debug_frame) } | ||||
|   .debug_str      0 : { *(.debug_str) } | ||||
|   .debug_loc      0 : { *(.debug_loc) } | ||||
|   .debug_macinfo  0 : { *(.debug_macinfo) } | ||||
|   /* SGI/MIPS DWARF 2 extensions */ | ||||
|   .debug_weaknames 0 : { *(.debug_weaknames) } | ||||
|   .debug_funcnames 0 : { *(.debug_funcnames) } | ||||
|   .debug_typenames 0 : { *(.debug_typenames) } | ||||
|   .debug_varnames  0 : { *(.debug_varnames) } | ||||
|   /* DWARF 3 */ | ||||
|   .debug_pubtypes 0 : { *(.debug_pubtypes) } | ||||
|   .debug_ranges   0 : { *(.debug_ranges) } | ||||
|   /* DWARF Extension.  */ | ||||
|   .debug_macro    0 : { *(.debug_macro) } | ||||
|   .debug_addr     0 : { *(.debug_addr) } | ||||
|   .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } | ||||
|   /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user