native simulator: Get latest from upstream

Align with native_simulator's upstream main
64b8be6311a61df2c63987813e8058560c8dc49c

Which includes:
 * 64b8be6 Make: Give option to add extra localization parameters
 * 05bc3ce Generalize code for N CPUs/MCUs
 * 489069b Makefile: Generalize for N embedded images
 * a4c817e runner->embedded trampolines: Improve definitions
 * 8d8dd29 nsi_utils: Provide debracket macro
 * 6b4956e Add optional embedded test hook definition

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
This commit is contained in:
Alberto Escolar Piedras 2023-09-04 15:20:35 +02:00 committed by Fabio Baltieri
commit e3aa649ee0
11 changed files with 260 additions and 109 deletions

View file

@ -27,12 +27,15 @@ NSI_BUILD_PATH?=$(abspath _build/)
EXE_NAME?=native_simulator.exe
# Final executable path/file_name which will be produced
NSI_EXE?=${NSI_BUILD_PATH}/${EXE_NAME}
# Path to the embedded SW which will be linked with the final executable
# Number of embedded CPUs/MCUs
NSI_N_CPUS?=1
# Path to all CPUs embedded SW which will be linked with the final executable
NSI_EMBEDDED_CPU_SW?=
# Host architecture configuration switch
NSI_ARCH?=-m32
# Coverage switch (GCOV coverage is enabled by default)
NSI_COVERAGE?=--coverage
NSI_LOCALIZE_OPTIONS?=
NSI_BUILD_OPTIONS?=${NSI_ARCH} ${NSI_COVERAGE}
NSI_LINK_OPTIONS?=${NSI_ARCH} ${NSI_COVERAGE}
# Extra source files to be built in the runner context
@ -61,7 +64,7 @@ NSI_CPPFLAGS?=-D_POSIX_C_SOURCE=200809 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTEN
NO_PIE_CO:=-fno-pie -fno-pic
DEPENDFLAGS:=-MMD -MP
CFLAGS:=${NSI_DEBUG} ${NSI_WARNINGS} ${NSI_OPT} ${NO_PIE_CO} \
CFLAGS:=${NSI_DEBUG} ${NSI_WARNINGS} ${NSI_OPT} ${NO_PIE_CO} -DNSI_N_CPUS=${NSI_N_CPUS} \
-ffunction-sections -fdata-sections ${DEPENDFLAGS} -std=c11 ${NSI_BUILD_OPTIONS}
FINALLINK_FLAGS:=${NO_PIE_CO} -no-pie ${NSI_WARNINGS} \
-Wl,--gc-sections -ldl -pthread \
@ -93,6 +96,8 @@ DEPENDFILES:=$(addsuffix .d,$(basename ${OBJS}))
-include ${DEPENDFILES}
LOCALIZED_EMBSW:=$(abspath $(addprefix $(NSI_BUILD_PATH)/,$(addsuffix .loc_cpusw.o,${NSI_EMBEDDED_CPU_SW})))
${NSI_BUILD_PATH}:
@if [ ! -d ${NSI_BUILD_PATH} ]; then mkdir -p ${NSI_BUILD_PATH}; fi
@ -112,16 +117,19 @@ ${NSI_BUILD_PATH}/${RUNNER_LIB}: ${OBJS}
if [ -f $@ ]; then rm $@ ; fi
${NSI_AR} -cr $@ ${OBJS}
${NSI_EXE}: ${NSI_BUILD_PATH}/${RUNNER_LIB} ${NSI_EMBEDDED_CPU_SW} ${NSI_EXTRA_LIBS} \
${NSI_BUILD_PATH}/linker_script.ld
@if [ -z ${NSI_EMBEDDED_CPU_SW} ] || [ ! -f ${NSI_EMBEDDED_CPU_SW} ]; then \
echo "Error: Input embedded CPU SW not found (NSI_EMBEDDED_CPU_SW=${NSI_EMBEDDED_CPU_SW} )"; \
${NSI_BUILD_PATH}/%.loc_cpusw.o: /% ${NSI_CONFIG_FILE}
@if [ -z $< ] || [ ! -f $< ]; then \
echo "Error: Input embedded CPU SW ($<) not found \
(NSI_EMBEDDED_CPU_SW=${NSI_EMBEDDED_CPU_SW} )"; \
false; \
fi
${NSI_OBJCOPY} --localize-hidden ${NSI_EMBEDDED_CPU_SW} ${NSI_BUILD_PATH}/cpu_0.sw.o \
-w --localize-symbol=_*
${NSI_CC} -Wl,--whole-archive ${NSI_BUILD_PATH}/cpu_0.sw.o ${NSI_BUILD_PATH}/${RUNNER_LIB} \
${NSI_EXTRA_LIBS} -Wl,--no-whole-archive \
@if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
${NSI_OBJCOPY} --localize-hidden $< $@ -w --localize-symbol=_* ${NSI_LOCALIZE_OPTIONS}
${NSI_EXE}: ${NSI_BUILD_PATH}/${RUNNER_LIB} ${LOCALIZED_EMBSW} ${NSI_EXTRA_LIBS} \
${NSI_BUILD_PATH}/linker_script.ld
${NSI_CC} -Wl,--whole-archive ${LOCALIZED_EMBSW} ${NSI_BUILD_PATH}/${RUNNER_LIB} \
${NSI_EXTRA_LIBS} -Wl,--no-whole-archive \
-o $@ ${FINALLINK_FLAGS} -T ${NSI_BUILD_PATH}/linker_script.ld
Makefile: ;

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef NSI_COMMON_SRC_INCL_NSI_CPU_CTRL_H
#define NSI_COMMON_SRC_INCL_NSI_CPU_CTRL_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Define if a CPU should automatically start at boot or not
*
* @param[in] cpu_n: Which CPU
* @param[in] auto_start: If true, it will autostart on its own,
* if 0, it won't
*/
void nsi_cpu_set_auto_start(int cpu_n, bool auto_start);
bool nsi_cpu_get_auto_start(int cpu_n);
/**
* @brief Boot CPU <cpu_n>
*
* Note: This API may only be called if that CPU was not stared before
*
* @param[in] cpu_n: Which CPU
*/
void nsi_cpu_boot(int cpu_n);
/*
* Internal native simulator runner API.
* Boot all CPUs which are configured to boot automatically
*/
void nsi_cpu_auto_boot(void);
#ifdef __cplusplus
}
#endif
#endif /* NSI_COMMON_SRC_INCL_NSI_CPU_CTRL_H */

View file

@ -11,6 +11,8 @@
extern "C" {
#endif
#include "nsi_cpu_if_internal.h"
/*
* Any symbol annotated by this macro will be visible outside of the
* embedded SW library, both by the native simulator runner,
@ -93,31 +95,21 @@ NATIVE_SIMULATOR_IF void nsif_cpu0_irq_raised(void);
*/
NATIVE_SIMULATOR_IF void nsif_cpu0_irq_raised_from_sw(void);
#define NSI_CPU_IF_N(i) \
NATIVE_SIMULATOR_IF void nsif_cpu##i##_pre_cmdline_hooks(void); \
NATIVE_SIMULATOR_IF void nsif_cpu##i##_pre_hw_init_hooks(void); \
NATIVE_SIMULATOR_IF void nsif_cpu##i##_boot(void); \
NATIVE_SIMULATOR_IF int nsif_cpu##i##_cleanup(void); \
NATIVE_SIMULATOR_IF void nsif_cpu##i##_irq_raised(void); \
NATIVE_SIMULATOR_IF void nsif_cpu##i##_irq_raised_from_sw(void);
/*
* Optional hook which may be used for test functionality.
* When the runner HW models use them and for what is up to those
* specific models.
*/
NATIVE_SIMULATOR_IF int nsif_cpu0_test_hook(void *p);
NSI_CPU_IF_N(1)
NSI_CPU_IF_N(2)
NSI_CPU_IF_N(3)
NSI_CPU_IF_N(4)
NSI_CPU_IF_N(5)
NSI_CPU_IF_N(6)
NSI_CPU_IF_N(7)
NSI_CPU_IF_N(8)
NSI_CPU_IF_N(9)
NSI_CPU_IF_N(10)
NSI_CPU_IF_N(11)
NSI_CPU_IF_N(12)
NSI_CPU_IF_N(13)
NSI_CPU_IF_N(14)
NSI_CPU_IF_N(15)
#undef NSI_CPU_IF_N
/* Provide prototypes for all n instances of these hooks */
F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _pre_cmdline_hooks(void))
F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _pre_hw_init_hooks(void))
F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _boot(void))
F_TRAMP_LIST(NATIVE_SIMULATOR_IF int nsif_cpu, _cleanup(void))
F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _irq_raised(void))
F_TRAMP_LIST(NATIVE_SIMULATOR_IF void nsif_cpu, _irq_raised_from_sw(void))
F_TRAMP_LIST(NATIVE_SIMULATOR_IF int nsif_cpu, _test_hook(void *p))
#ifdef __cplusplus
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef NSI_COMMON_SRC_INCL_NSI_CPU_IF_INTERNAL_H
#define NSI_COMMON_SRC_INCL_NSI_CPU_IF_INTERNAL_H
#include "nsi_utils.h"
#ifdef __cplusplus
extern "C" {
#endif
#define FUNCT(i, pre, post) \
pre##i##post
#define FUNCT_LIST(pre, post, sep) \
FUNCT(0, pre, post) NSI_DEBRACKET sep \
FUNCT(1, pre, post) NSI_DEBRACKET sep \
FUNCT(2, pre, post) NSI_DEBRACKET sep \
FUNCT(3, pre, post) NSI_DEBRACKET sep \
FUNCT(4, pre, post) NSI_DEBRACKET sep \
FUNCT(5, pre, post) NSI_DEBRACKET sep \
FUNCT(6, pre, post) NSI_DEBRACKET sep \
FUNCT(7, pre, post) NSI_DEBRACKET sep \
FUNCT(8, pre, post) NSI_DEBRACKET sep \
FUNCT(9, pre, post) NSI_DEBRACKET sep \
FUNCT(10, pre, post) NSI_DEBRACKET sep \
FUNCT(11, pre, post) NSI_DEBRACKET sep \
FUNCT(12, pre, post) NSI_DEBRACKET sep \
FUNCT(13, pre, post) NSI_DEBRACKET sep \
FUNCT(14, pre, post) NSI_DEBRACKET sep \
FUNCT(15, pre, post) NSI_DEBRACKET sep \
#define F_TRAMP_TABLE(pre, post) FUNCT_LIST(pre, post, (,))
#define F_TRAMP_LIST(pre, post) FUNCT_LIST(pre, post, (;))
#define F_TRAMP_BODY_LIST(pre, post) FUNCT_LIST(pre, post, ())
#define TRAMPOLINES(pre, post) \
void pre ## n ## post(int n) \
{ \
void(*fptrs[])(void) = { \
F_TRAMP_TABLE(pre, post) \
}; \
fptrs[n](); \
}
#define TRAMPOLINES_i_vp(pre, post) \
int pre ## n ## post(int n, void *p) \
{ \
int(*fptrs[])(void *p) = { \
F_TRAMP_TABLE(pre, post) \
}; \
return fptrs[n](p); \
}
#define TRAMPOLINES_i_(pre, post) \
int pre ## n ## post(int n) \
{ \
int(*fptrs[])(void) = { \
F_TRAMP_TABLE(pre, post) \
}; \
return fptrs[n](); \
}
#ifdef __cplusplus
}
#endif
#endif /* NSI_COMMON_SRC_INCL_NSI_CPU_IF_INTERNAL_H */

View file

@ -8,6 +8,8 @@
#ifndef NSI_COMMON_SRC_INCL_NSI_UTILS_H
#define NSI_COMMON_SRC_INCL_NSI_UTILS_H
/* Remove brackets from around a single argument: */
#define NSI_DEBRACKET(...) __VA_ARGS__
#define _NSI_STRINGIFY(x) #x
#define NSI_STRINGIFY(s) _NSI_STRINGIFY(s)

View file

@ -14,25 +14,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "nsi_cpu_if.h"
#include "nsi_cpun_if.h"
#include "nsi_tasks.h"
#include "nsi_cmdline_main_if.h"
#include "nsi_utils.h"
#include "nsi_hw_scheduler.h"
#include "nsi_config.h"
#include "nsi_cpu_ctrl.h"
int nsi_exit_inner(int exit_code)
{
static int max_exit_code;
int cpu_ret;
max_exit_code = NSI_MAX(exit_code, max_exit_code);
/*
* nsif_cpu0_cleanup may not return if this is called from a SW thread,
* nsif_cpun_cleanup may not return if this is called from a SW thread,
* but instead it would get nsi_exit() recalled again
* ASAP from the HW thread
*/
int cpu_0_ret = nsif_cpu0_cleanup();
max_exit_code = NSI_MAX(cpu_0_ret, max_exit_code);
for (int i = 0; i < NSI_N_CPUS; i++) {
cpu_ret = nsif_cpun_cleanup(i);
max_exit_code = NSI_MAX(cpu_ret, max_exit_code);
}
nsi_run_tasks(NSITASK_ON_EXIT_PRE_LEVEL);
nsi_hws_cleanup();
@ -62,19 +66,23 @@ static void nsi_init(int argc, char *argv[])
setvbuf(stderr, NULL, _IOLBF, 512);
nsi_run_tasks(NSITASK_PRE_BOOT_1_LEVEL);
nsif_cpu0_pre_cmdline_hooks();
for (int i = 0; i < NSI_N_CPUS; i++) {
nsif_cpun_pre_cmdline_hooks(i);
}
nsi_handle_cmd_line(argc, argv);
nsi_run_tasks(NSITASK_PRE_BOOT_2_LEVEL);
nsif_cpu0_pre_hw_init_hooks();
for (int i = 0; i < NSI_N_CPUS; i++) {
nsif_cpun_pre_hw_init_hooks(i);
}
nsi_run_tasks(NSITASK_HW_INIT_LEVEL);
nsi_hws_init();
nsi_run_tasks(NSITASK_PRE_BOOT_3_LEVEL);
nsif_cpu0_boot();
nsi_cpu_auto_boot();
nsi_run_tasks(NSITASK_FIRST_SLEEP_LEVEL);
}

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef NSI_COMMON_SRC_NSI_CONFIG_H
#define NSI_COMMON_SRC_NSI_CONFIG_H
#ifndef NSI_N_CPUS
#define NSI_N_CPUS 1
#endif
#endif /* NSI_COMMON_SRC_NSI_CONFIG_H */

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include "nsi_config.h"
#include "nsi_cpun_if.h"
#include "nsi_tracing.h"
static bool cpu_auto_start[NSI_N_CPUS] = {true}; /* Only the first core starts on its own */
static bool cpu_booted[NSI_N_CPUS];
#define CPU_N_RANGE_CHECK(cpu_n) \
if (cpu_n >= NSI_N_CPUS) { \
nsi_print_error_and_exit("%s called with cpu_n(%i) >= NSI_N_CPUS (%i)\n", \
cpu_n, NSI_N_CPUS); \
}
void nsi_cpu_set_auto_start(int cpu_n, bool auto_start)
{
CPU_N_RANGE_CHECK(cpu_n);
cpu_auto_start[cpu_n] = auto_start;
}
bool nsi_cpu_get_auto_start(int cpu_n)
{
return cpu_auto_start[cpu_n];
}
void nsi_cpu_auto_boot(void)
{
for (int i = 0; i < NSI_N_CPUS; i++) {
if (cpu_auto_start[i] == true) {
cpu_booted[i] = true;
nsif_cpun_boot(i);
}
}
}
void nsi_cpu_boot(int cpu_n)
{
CPU_N_RANGE_CHECK(cpu_n);
if (cpu_booted[cpu_n]) {
nsi_print_warning("%s called with cpu_n(%i) which was already booted\n",
cpu_n);
}
cpu_booted[cpu_n] = true;
nsif_cpun_boot(cpu_n);
}

View file

@ -11,48 +11,10 @@
* for ex., nsif_cpun_boot(4) -> nsif_cpu4_boot()
*/
#define FUNCT(i, pre, post) \
pre##i##post
#define F_TABLE(pre, post) \
FUNCT(0, pre, post), \
FUNCT(1, pre, post), \
FUNCT(2, pre, post), \
FUNCT(3, pre, post), \
FUNCT(4, pre, post), \
FUNCT(5, pre, post), \
FUNCT(6, pre, post), \
FUNCT(7, pre, post), \
FUNCT(8, pre, post), \
FUNCT(9, pre, post), \
FUNCT(10, pre, post), \
FUNCT(11, pre, post), \
FUNCT(12, pre, post), \
FUNCT(13, pre, post), \
FUNCT(14, pre, post), \
FUNCT(15, pre, post)
#define TRAMPOLINES(pre, post) \
void pre ## n ## post(int n) \
{ \
void(*fptrs[])(void) = { \
F_TABLE(pre, post) \
}; \
fptrs[n](); \
}
#define TRAMPOLINES_i(pre, post) \
int pre ## n ## post(int n) \
{ \
int(*fptrs[])(void) = { \
F_TABLE(pre, post) \
}; \
return fptrs[n](); \
}
TRAMPOLINES(nsif_cpu, _pre_cmdline_hooks)
TRAMPOLINES(nsif_cpu, _pre_hw_init_hooks)
TRAMPOLINES(nsif_cpu, _boot)
TRAMPOLINES_i(nsif_cpu, _cleanup)
TRAMPOLINES_i_(nsif_cpu, _cleanup)
TRAMPOLINES(nsif_cpu, _irq_raised)
TRAMPOLINES(nsif_cpu, _irq_raised_from_sw)
TRAMPOLINES_i_vp(nsif_cpu, _test_hook)

View file

@ -21,6 +21,7 @@ void nsif_cpun_boot(int n);
int nsif_cpun_cleanup(int n);
void nsif_cpun_irq_raised(int n);
void nsif_cpun_irq_raised_from_sw(int n);
void nsif_cpun_test_hook(int n, void *p);
#ifdef __cplusplus
}

View file

@ -12,33 +12,25 @@
* The CPU does not boot, and interrupts are just ignored
* These are all defined as weak, so if an actual image is present for that CPU,
* that will be linked against.
*
* This exists in case the total device image is assembled lacking some of the embedded CPU images
*/
#define NSI_CPU_STUBBED_IMAGE(i) \
__attribute__((weak)) void nsif_cpu##i##_pre_cmdline_hooks(void) { } \
__attribute__((weak)) void nsif_cpu##i##_pre_hw_init_hooks(void) { } \
__attribute__((weak)) void nsif_cpu##i##_boot(void) \
{ \
nsi_print_trace("Attempted boot of CPU %i without image. "\
"CPU %i shut down permanently\n", i, i); \
} \
__attribute__((weak)) int nsif_cpu##i##_cleanup(void) { return 0; } \
__attribute__((weak)) void nsif_cpu##i##_irq_raised(void) { } \
__attribute__((weak)) void nsif_cpu##i##_irq_raised_from_sw(void) { }
static void nsi_boot_warning(const char *func)
{
nsi_print_trace("%s: Attempted boot of CPU without image. "
"CPU shut down permanently\n", func);
}
NSI_CPU_STUBBED_IMAGE(0)
NSI_CPU_STUBBED_IMAGE(1)
NSI_CPU_STUBBED_IMAGE(2)
NSI_CPU_STUBBED_IMAGE(3)
NSI_CPU_STUBBED_IMAGE(4)
NSI_CPU_STUBBED_IMAGE(5)
NSI_CPU_STUBBED_IMAGE(6)
NSI_CPU_STUBBED_IMAGE(7)
NSI_CPU_STUBBED_IMAGE(8)
NSI_CPU_STUBBED_IMAGE(9)
NSI_CPU_STUBBED_IMAGE(10)
NSI_CPU_STUBBED_IMAGE(11)
NSI_CPU_STUBBED_IMAGE(12)
NSI_CPU_STUBBED_IMAGE(13)
NSI_CPU_STUBBED_IMAGE(14)
NSI_CPU_STUBBED_IMAGE(15)
/*
* These will define N functions like
* int nsif_cpu<n>_cleanup(void) { return 0; }
*/
F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, _pre_cmdline_hooks(void) { })
F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, _pre_hw_init_hooks(void) { })
F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu,
_boot(void) { nsi_boot_warning(__func__); })
F_TRAMP_BODY_LIST(__attribute__((weak)) int nsif_cpu, _cleanup(void) { return 0; })
F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, _irq_raised(void) { })
F_TRAMP_BODY_LIST(__attribute__((weak)) void nsif_cpu, _irq_raised_from_sw(void) { })
F_TRAMP_BODY_LIST(__attribute__((weak)) int nsif_cpu, _test_hook(void *p) { return 0; })