From 5d4e860f924830e9a2ec612db1254a015d2ad0bf Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Fri, 30 May 2025 23:45:46 +0200 Subject: [PATCH 01/10] Add Coremark benchmark. --- .github/workflows/lint.yml | 1 + .gitmodules | 3 +++ cheshire.mk | 2 +- sw/deps/coremark | 1 + sw/lib/dif/uart.c | 1 + sw/sw.mk | 18 ++++++++++++++---- sw/tests/coremark.c | 1 + 7 files changed, 22 insertions(+), 5 deletions(-) create mode 160000 sw/deps/coremark create mode 120000 sw/tests/coremark.c diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1ea888589..3f5f15906 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -70,6 +70,7 @@ jobs: exclude: | ./sw/include/regs/*.h ./target/sim/src/elfloader.cpp + ./sw/tests/coremark.c lint-tcl: runs-on: ubuntu-latest diff --git a/.gitmodules b/.gitmodules index 620a456ac..d79282a91 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,6 @@ path = sw/deps/cva6-sdk url = https://github.com/pulp-platform/cva6-sdk.git ignore = dirty +[submodule "sw/deps/coremark"] + path = sw/deps/coremark + url = https://github.com/yvantor/coremark.git diff --git a/cheshire.mk b/cheshire.mk index f838911b7..06984daf5 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -43,7 +43,7 @@ BENDER_ROOT ?= $(CHS_ROOT)/.bender # Ensure both Bender dependencies and (essential) submodules are checked out $(BENDER_ROOT)/.chs_deps: $(BENDER) checkout - cd $(CHS_ROOT) && git submodule update --init --recursive sw/deps/printf + cd $(CHS_ROOT) && git submodule update --init --recursive sw/deps/printf sw/deps/coremark @touch $@ # Make sure dependencies are more up-to-date than any targets run diff --git a/sw/deps/coremark b/sw/deps/coremark new file mode 160000 index 000000000..12ceef596 --- /dev/null +++ b/sw/deps/coremark @@ -0,0 +1 @@ +Subproject commit 12ceef596c5e3980def9bd01a8de8cc394e28cf4 diff --git a/sw/lib/dif/uart.c b/sw/lib/dif/uart.c index 782cf31b7..7f0c16648 100644 --- a/sw/lib/dif/uart.c +++ b/sw/lib/dif/uart.c @@ -66,6 +66,7 @@ void uart_read_str(void *uart_base, void *dst, uint64_t len) { // Default UART provides console void _putchar(char byte) { uart_write(&__base_uart, byte); + uart_write_flush(&__base_uart); } char _getchar() { diff --git a/sw/sw.mk b/sw/sw.mk index baa9ee411..c7517dc94 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -48,6 +48,16 @@ CHS_SW_DEPS_SRCS += $(wildcard $(OTPROOT)/sw/device/lib/base/*.c) CHS_SW_DEPS_SRCS += $(wildcard $(OTPROOT)/sw/device/lib/dif/*.c) CHS_SW_DEPS_SRCS += $(wildcard $(OTPROOT)/sw/device/lib/dif/autogen/*.c) +# Coremark-dependant parameters +COREMARK_FLAGS_STR ?= $(CHS_SW_CCFLAGS) $(CHS_SW_LDFLAGS) +COREMARK_ITERATIONS ?= 10 +# The following parameter is the core frequency in Hz (e.g. 200'000'000 Hz) +COREMARK_CLOCKS_PER_SEC ?= 200000000 +CHS_SW_DEPS_INCS += -I$(CHS_SW_DIR)/deps/coremark +CHS_SW_DEPS_INCS += -I$(CHS_SW_DIR)/deps/coremark/cheshire +CHS_SW_DEPS_SRCS += $(wildcard $(CHS_SW_DIR)/deps/coremark/*.c) +CHS_SW_DEPS_SRCS += $(wildcard $(CHS_SW_DIR)/deps/coremark/cheshire/*.c) +COREMARK_SW_FLAGS += -DFLAGS_STR="\"$(COREMARK_FLAGS_STR)\"" -DITERATIONS=$(COREMARK_ITERATIONS) -DCLOCKS_PER_SEC=$(COREMARK_CLOCKS_PER_SEC) ############# # Libraries # ############# @@ -95,10 +105,10 @@ CHS_SW_GEN_HDRS += $(OTPROOT)/.generated # All objects require up-to-date patches and headers %.o: %.c $(CHS_SW_GEN_HDRS) - $(CHS_SW_CC) $(CHS_SW_INCLUDES) $(CHS_SW_CCFLAGS) -c $< -o $@ + $(CHS_SW_CC) $(CHS_SW_INCLUDES) $(CHS_SW_CCFLAGS) $(COREMARK_SW_FLAGS) -c $< -o $@ %.o: %.S $(CHS_SW_GEN_HDRS) - $(CHS_SW_CC) $(CHS_SW_INCLUDES) $(CHS_SW_CCFLAGS) -c $< -o $@ + $(CHS_SW_CC) $(CHS_SW_INCLUDES) $(CHS_SW_CCFLAGS) $(COREMARK_SW_FLAGS) -c $< -o $@ # Programs may specify a linking mode in their name, e.g. `helloworld.spm.c`. # Tests with such infixes are built only for one linking mode, tests without them for all @@ -106,10 +116,10 @@ define chs_sw_ld_elf_rule .PRECIOUS: %.$(1).elf %.$(1).elf: $$(CHS_SW_LD_DIR)/$(1).ld %.o $$(CHS_SW_LIBS) - $$(CHS_SW_CC) $$(CHS_SW_INCLUDES) -T$$< $$(CHS_SW_LDFLAGS) -o $$@ $$*.o $$(CHS_SW_LIBS) + $$(CHS_SW_CC) $$(CHS_SW_INCLUDES) -T$$< $$(CHS_SW_LDFLAGS) $(COREMARK_SW_FLAGS) -o $$@ $$*.o $$(CHS_SW_LIBS) %.$(1).elf: $$(CHS_SW_LD_DIR)/$(1).ld %.$(1).o $$(CHS_SW_LIBS) - $$(CHS_SW_CC) $$(CHS_SW_INCLUDES) -T$$< $$(CHS_SW_LDFLAGS) -o $$@ $$*.$(1).o $$(CHS_SW_LIBS) + $$(CHS_SW_CC) $$(CHS_SW_INCLUDES) -T$$< $$(CHS_SW_LDFLAGS) $(COREMARK_SW_FLAGS) -o $$@ $$*.$(1).o $$(CHS_SW_LIBS) endef CHS_SW_LINK_MODES ?= $(patsubst $(CHS_SW_LD_DIR)/%.ld,%,$(wildcard $(CHS_SW_LD_DIR)/*.ld)) diff --git a/sw/tests/coremark.c b/sw/tests/coremark.c new file mode 120000 index 000000000..83c4abc94 --- /dev/null +++ b/sw/tests/coremark.c @@ -0,0 +1 @@ +../deps/coremark/core_main.c \ No newline at end of file From 154d60a3afa71fe5d65c1ce4822e627d52b2629e Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sun, 29 Jun 2025 09:40:38 +0200 Subject: [PATCH 02/10] Bump Coremark for printf carriage return. --- sw/deps/coremark | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sw/deps/coremark b/sw/deps/coremark index 12ceef596..3194584e7 160000 --- a/sw/deps/coremark +++ b/sw/deps/coremark @@ -1 +1 @@ -Subproject commit 12ceef596c5e3980def9bd01a8de8cc394e28cf4 +Subproject commit 3194584e7be45807d7c0c1f1f3d2867bfb1bd272 From bd18a14476c42259b49d99ca3feee0fd452ec125 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sun, 29 Jun 2025 10:19:09 +0200 Subject: [PATCH 03/10] Fix `CHS_XILINX_FLASH_IMG` reference in docs. --- docs/tg/xilinx.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tg/xilinx.md b/docs/tg/xilinx.md index bf3bb8e28..b36ec6ef9 100644 --- a/docs/tg/xilinx.md +++ b/docs/tg/xilinx.md @@ -135,12 +135,12 @@ Insert your SD card and reset into boot mode 1. You should see a `Hello World!` Build a GPT disk image for your desired binary as explained above, then flash it to your board's flash. For `helloworld`: ``` -make CHS_XILINX_FLASH_BIN=sw/tests/helloworld.gpt.bin chs-xilinx-flash- +make CHS_XILINX_FLASH_IMG=sw/tests/helloworld.gpt.bin chs-xilinx-flash- ``` Flashing an image should take about 10 minutes. *Note that after flashing, your board's bitstream must be reprogrammed* as it is overridden for this task. -If the image given by `CHS_XILINX_FLASH_BIN` does not exist, `make` will attempt to build it before flashing. If `CHS_XILINX_FLASH_BIN` is not provided, the target assumes the default Linux image for your board. +If the image given by `CHS_XILINX_FLASH_IMG` does not exist, `make` will attempt to build it before flashing. If `CHS_XILINX_FLASH_IMG` is not provided, the target assumes the default Linux image for your board. After flashing your disk image and reprogramming your bitstream, reset into boot mode 2. For `helloworld`, you should again see a `Hello World!` UART output. From 861f9300af40067604e2720b183d58f33a3064be Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sun, 29 Jun 2025 13:48:10 +0200 Subject: [PATCH 04/10] Bump nonfree to add coremark step. --- cheshire.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheshire.mk b/cheshire.mk index 06984daf5..98897d900 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -63,7 +63,7 @@ chs-clean-deps: ###################### CHS_NONFREE_REMOTE ?= git@iis-git.ee.ethz.ch:pulp-restricted/cheshire-nonfree.git -CHS_NONFREE_COMMIT ?= 92f6f02 +CHS_NONFREE_COMMIT ?= ad9f538 # yt/coremark CHS_PHONY += chs-nonfree-init chs-nonfree-init: From f0cc06a9ac2302544389c5eadd50dc9e1a33cdf1 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sun, 29 Jun 2025 14:07:04 +0200 Subject: [PATCH 05/10] Default coremark iterations to 5000 to satisfy execution time requirements. --- sw/sw.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sw/sw.mk b/sw/sw.mk index c7517dc94..c75e9864b 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -50,7 +50,7 @@ CHS_SW_DEPS_SRCS += $(wildcard $(OTPROOT)/sw/device/lib/dif/autogen/*.c) # Coremark-dependant parameters COREMARK_FLAGS_STR ?= $(CHS_SW_CCFLAGS) $(CHS_SW_LDFLAGS) -COREMARK_ITERATIONS ?= 10 +COREMARK_ITERATIONS ?= 5000 # The following parameter is the core frequency in Hz (e.g. 200'000'000 Hz) COREMARK_CLOCKS_PER_SEC ?= 200000000 CHS_SW_DEPS_INCS += -I$(CHS_SW_DIR)/deps/coremark From 81f4a0358a35fa8b56b0204ad6686946f34a2233 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Mon, 30 Jun 2025 09:08:04 +0200 Subject: [PATCH 06/10] Bump nonfree. --- cheshire.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheshire.mk b/cheshire.mk index 98897d900..20b9e1a17 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -63,7 +63,7 @@ chs-clean-deps: ###################### CHS_NONFREE_REMOTE ?= git@iis-git.ee.ethz.ch:pulp-restricted/cheshire-nonfree.git -CHS_NONFREE_COMMIT ?= ad9f538 # yt/coremark +CHS_NONFREE_COMMIT ?= 703e598 # yt/coremark CHS_PHONY += chs-nonfree-init chs-nonfree-init: From 65f59626a8d9ef39f8a9ab42b9428152837dc3ee Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Mon, 30 Jun 2025 11:24:35 +0200 Subject: [PATCH 07/10] Bump nonfree. --- cheshire.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cheshire.mk b/cheshire.mk index 20b9e1a17..358c43e42 100644 --- a/cheshire.mk +++ b/cheshire.mk @@ -63,7 +63,7 @@ chs-clean-deps: ###################### CHS_NONFREE_REMOTE ?= git@iis-git.ee.ethz.ch:pulp-restricted/cheshire-nonfree.git -CHS_NONFREE_COMMIT ?= 703e598 # yt/coremark +CHS_NONFREE_COMMIT ?= 23bf67d # yt/coremark CHS_PHONY += chs-nonfree-init chs-nonfree-init: From 3dfe3a3b8e18ab5429a3bdeeaa23f57d471b14cf Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Fri, 11 Jul 2025 23:00:52 +0200 Subject: [PATCH 08/10] Migrate Cheshire-specific files to avoid Coremark fork. --- .github/workflows/lint.yml | 4 + .gitmodules | 2 +- sw/deps/coremark | 2 +- sw/include/coremark/core_portme.h | 217 ++++++++++ sw/lib/coremark/core_portme.c | 159 +++++++ sw/lib/coremark/ee_printf.c | 687 ++++++++++++++++++++++++++++++ sw/sw.mk | 4 +- 7 files changed, 1071 insertions(+), 4 deletions(-) create mode 100644 sw/include/coremark/core_portme.h create mode 100644 sw/lib/coremark/core_portme.c create mode 100644 sw/lib/coremark/ee_printf.c diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3f5f15906..09bde303d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -27,6 +27,8 @@ jobs: # Exclude generated headers (no license checker support for optional lines) exclude_paths: | sw/include/regs/*.h + sw/include/coremark/* + sw/lib/coremark/* lint-sv: runs-on: ubuntu-latest @@ -69,6 +71,8 @@ jobs: } exclude: | ./sw/include/regs/*.h + ./sw/include/coremark/* + ./sw/lib/coremark/* ./target/sim/src/elfloader.cpp ./sw/tests/coremark.c diff --git a/.gitmodules b/.gitmodules index d79282a91..d52835915 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,4 +8,4 @@ ignore = dirty [submodule "sw/deps/coremark"] path = sw/deps/coremark - url = https://github.com/yvantor/coremark.git + url = https://github.com/eembc/coremark.git diff --git a/sw/deps/coremark b/sw/deps/coremark index 3194584e7..1f483d5b8 160000 --- a/sw/deps/coremark +++ b/sw/deps/coremark @@ -1 +1 @@ -Subproject commit 3194584e7be45807d7c0c1f1f3d2867bfb1bd272 +Subproject commit 1f483d5b8316753a742cbf5590caf5bd0a4e4777 diff --git a/sw/include/coremark/core_portme.h b/sw/include/coremark/core_portme.h new file mode 100644 index 000000000..bf248a357 --- /dev/null +++ b/sw/include/coremark/core_portme.h @@ -0,0 +1,217 @@ +// 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 "regs/cheshire.h" +#include "dif/clint.h" +#include "dif/uart.h" +#include "params.h" +#include "util.h" + +/* 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 1 +#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 . + + *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 float ee_f32; +typedef double ee_f64; +typedef unsigned char ee_u8; +typedef unsigned int ee_u32; +typedef unsigned long ee_u64; +typedef ee_u64 ee_ptr_int; +typedef ee_u64 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_STATIC +#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 or + to enable them. + + It is valid to have a different implementation of + and in , 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 contain 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 */ diff --git a/sw/lib/coremark/core_portme.c b/sw/lib/coremark/core_portme.c new file mode 100644 index 000000000..cf9ad650d --- /dev/null +++ b/sw/lib/coremark/core_portme.c @@ -0,0 +1,159 @@ +// 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" + +#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() +{ + CORETIMETYPE cycle_count; + asm volatile("csrr %0, mcycle" : "=r"(cycle_count)); + return cycle_count; +} +/* 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 . This + methodology is taken to accommodate any hardware or simulated platform. The + sample implementation returns millisecs by default, and the resolution is + controlled by +*/ +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 type is used to accommodate 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[]) +{ + + ee_u32 rtc_freq = *reg32(&__base_regs, CHESHIRE_RTC_FREQ_REG_OFFSET); + ee_u64 reset_freq = clint_get_core_freq(rtc_freq, 2500); + uart_init(&__base_uart, reset_freq, __BOOT_BAUDRATE); + + (void)argc; // prevent unused warning + (void)argv; // prevent unused warning + + if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) + { + ee_printf( + "ERROR! Please define ee_ptr_int to a type that holds a " + "pointer!\n\r"); + } + if (sizeof(ee_u32) != 4) + { + ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n\r"); + } + p->portable_id = 1; +} +/* Function : portable_fini + Target specific final code +*/ +void +portable_fini(core_portable *p) +{ + p->portable_id = 0; +} diff --git a/sw/lib/coremark/ee_printf.c b/sw/lib/coremark/ee_printf.c new file mode 100644 index 000000000..f19f826b5 --- /dev/null +++ b/sw/lib/coremark/ee_printf.c @@ -0,0 +1,687 @@ +// 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 +// #include +#include "printf.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 = ""; +// 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; +// } +// +// void +// uart_send_char(char c) +// { +// uart_write(&__base_uart, (ee_u8)c); +// uart_write_flush(&__base_uart); +// } + +// 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; +// } +int ee_printf(const char *fmt, ...) { printf_(fmt); } diff --git a/sw/sw.mk b/sw/sw.mk index c75e9864b..f95d79d3a 100644 --- a/sw/sw.mk +++ b/sw/sw.mk @@ -54,9 +54,9 @@ COREMARK_ITERATIONS ?= 5000 # The following parameter is the core frequency in Hz (e.g. 200'000'000 Hz) COREMARK_CLOCKS_PER_SEC ?= 200000000 CHS_SW_DEPS_INCS += -I$(CHS_SW_DIR)/deps/coremark -CHS_SW_DEPS_INCS += -I$(CHS_SW_DIR)/deps/coremark/cheshire +CHS_SW_DEPS_INCS += -I$(CHS_SW_DIR)/include/coremark CHS_SW_DEPS_SRCS += $(wildcard $(CHS_SW_DIR)/deps/coremark/*.c) -CHS_SW_DEPS_SRCS += $(wildcard $(CHS_SW_DIR)/deps/coremark/cheshire/*.c) +CHS_SW_DEPS_SRCS += $(wildcard $(CHS_SW_DIR)/lib/coremark/*.c) COREMARK_SW_FLAGS += -DFLAGS_STR="\"$(COREMARK_FLAGS_STR)\"" -DITERATIONS=$(COREMARK_ITERATIONS) -DCLOCKS_PER_SEC=$(COREMARK_CLOCKS_PER_SEC) ############# # Libraries # From 7eb1a41db336620e23932926c842300c607569d6 Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sat, 12 Jul 2025 00:13:53 +0200 Subject: [PATCH 09/10] Add carriage return if \n is dectected. --- sw/lib/dif/uart.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sw/lib/dif/uart.c b/sw/lib/dif/uart.c index 7f0c16648..e6b983b4d 100644 --- a/sw/lib/dif/uart.c +++ b/sw/lib/dif/uart.c @@ -65,6 +65,8 @@ void uart_read_str(void *uart_base, void *dst, uint64_t len) { // Default UART provides console void _putchar(char byte) { + // Add carriage return if newline character is detected + if (byte == '\n') uart_write(&__base_uart, '\r'); uart_write(&__base_uart, byte); uart_write_flush(&__base_uart); } From bc4f1802cc79392de40a3022ff524cc71c678e0c Mon Sep 17 00:00:00 2001 From: Yvan Tortorella Date: Sat, 12 Jul 2025 00:17:32 +0200 Subject: [PATCH 10/10] Cleanup ee_printf. --- sw/lib/coremark/ee_printf.c | 670 ------------------------------------ 1 file changed, 670 deletions(-) diff --git a/sw/lib/coremark/ee_printf.c b/sw/lib/coremark/ee_printf.c index f19f826b5..7ba2cc15e 100644 --- a/sw/lib/coremark/ee_printf.c +++ b/sw/lib/coremark/ee_printf.c @@ -12,676 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// #include -// #include #include "printf.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 = ""; -// 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; -// } -// -// void -// uart_send_char(char c) -// { -// uart_write(&__base_uart, (ee_u8)c); -// uart_write_flush(&__base_uart); -// } -// 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; -// } int ee_printf(const char *fmt, ...) { printf_(fmt); }