From e923ce8dee13d08d04a29a2fd9701b9cafde2ec9 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 6 May 2025 14:45:13 +0200 Subject: [PATCH 01/28] Patmos and S4NoC support: init commit --- CMakeLists.txt | 9 ++ include/reactor-uc/network_channel.h | 9 +- .../platform/patmos/s4noc_channel.h | 39 ++++++ .../target/property/PlatformProperty.java | 5 + .../target/property/type/PlatformType.java | 3 +- src/network_channel.c | 4 +- src/platform/patmos/s4noc_channel.c | 126 ++++++++++++++++++ test/lf/src/HelloPatmos.lf | 31 +++++ test/platform/patmos/HelloPatmos.c | 3 + test/platform/patmos/Makefile | 28 ++++ test/platform/patmos/runAll.sh | 4 + test/unit/s4noc_channel_test.c | 89 +++++++++++++ 12 files changed, 346 insertions(+), 4 deletions(-) create mode 100644 include/reactor-uc/platform/patmos/s4noc_channel.h create mode 100644 src/platform/patmos/s4noc_channel.c create mode 100644 test/lf/src/HelloPatmos.lf create mode 100644 test/platform/patmos/HelloPatmos.c create mode 100644 test/platform/patmos/Makefile create mode 100755 test/platform/patmos/runAll.sh create mode 100644 test/unit/s4noc_channel_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 66b128bc7..4e74e53ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,8 @@ set(SCHEDULER "DYNAMIC" CACHE STRING "Scheduler to use") set(NETWORK_CHANNEL_TCP_POSIX OFF CACHE BOOL "Use POSIX TCP NetworkChannel") set(FEDERATED OFF CACHE BOOL "Compile with federated sources") +message("PLATFORM is set to: ${PLATFORM}") + # Code coverage setup if(TEST_COVERAGE) set(CMAKE_BUILD_TYPE "Debug") @@ -65,6 +67,13 @@ elseif (PLATFORM STREQUAL "PICO") target_link_libraries(reactor-uc PUBLIC pico_stdlib pico_sync) elseif (PLATFORM STREQUAL "PATMOS") + find_program(CLANG_EXECUTABLE NAMES patmos-clang REQUIRED DOC \"Path to the clang" + " front-end.\") + set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE}) + message("Using compiler: ${CMAKE_C_COMPILER}") + set(CMAKE_C_FLAGS_RELEASE \"-O2 -DNDEBUG\") + # target_compile_options(reactor-uc PRIVATE -Wno-zero-length-bounds) + file(GLOB PATMOS_SOURCES "src/platform/patmos/*.c") + list(APPEND SOURCES ${PATMOS_SOURCES}) add_library(reactor-uc STATIC ${SOURCES}) else () message(FATAL_ERROR "No valid platform specified") diff --git a/include/reactor-uc/network_channel.h b/include/reactor-uc/network_channel.h index 8796528bf..d8ce2a2bf 100644 --- a/include/reactor-uc/network_channel.h +++ b/include/reactor-uc/network_channel.h @@ -31,7 +31,8 @@ typedef enum { typedef enum { NETWORK_CHANNEL_TYPE_TCP_IP, NETWORK_CHANNEL_TYPE_COAP_UDP_IP, - NETWORK_CHANNEL_TYPE_UART + NETWORK_CHANNEL_TYPE_UART, + NETWORK_CHANNEL_TYPE_S4NOC } NetworkChannelType; typedef enum { @@ -158,6 +159,12 @@ struct AsyncNetworkChannel { #ifdef NETWORK_CHANNEL_TCP_POSIX #error "NETWORK_POSIX_TCP not supported on FlexPRET" #endif + +#elif defined(PLATFORM_PATMOS) +#ifdef NETWORK_CHANNEL_S4NOC +#include "platform/patmos/s4noc_channel.h" +#endif + #endif #endif // REACTOR_UC_NETWORK_CHANNEL_H diff --git a/include/reactor-uc/platform/patmos/s4noc_channel.h b/include/reactor-uc/platform/patmos/s4noc_channel.h new file mode 100644 index 000000000..2963d13aa --- /dev/null +++ b/include/reactor-uc/platform/patmos/s4noc_channel.h @@ -0,0 +1,39 @@ +#ifndef REACTOR_UC_S4NOC_CHANNEL_H +#define REACTOR_UC_S4NOC_CHANNEL_H + +#include "reactor-uc/network_channel.h" +#include "reactor-uc/environment.h" + +typedef struct FederatedConnectionBundle FederatedConnectionBundle; +typedef struct S4NOCPollChannel S4NOCPollChannel; +typedef struct S4NOCGlobalState S4NOCGlobalState; + +#define S4NOC_CHANNEL_BUFFERSIZE 1024 + +#ifndef S4NOC_CORE_COUNT +#define S4NOC_CORE_COUNT 4 +#endif + +struct S4NOCGlobalState { + S4NOCPollChannel *core_channels[S4NOC_CORE_COUNT][S4NOC_CORE_COUNT]; +}; + +S4NOCGlobalState s4noc_global_state; + +struct S4NOCPollChannel { + NetworkChannel super; + NetworkChannelState state; + + FederateMessage output; + unsigned char write_buffer[S4NOC_CHANNEL_BUFFERSIZE]; + unsigned char receive_buffer[S4NOC_CHANNEL_BUFFERSIZE]; + unsigned int receive_buffer_index; + unsigned int destination_core; + + FederatedConnectionBundle *federated_connection; + void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *message); +}; + +extern void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned int destination_core); + +#endif diff --git a/lfc/core/src/main/java/org/lflang/target/property/PlatformProperty.java b/lfc/core/src/main/java/org/lflang/target/property/PlatformProperty.java index 82c8038d2..1c3c5188e 100644 --- a/lfc/core/src/main/java/org/lflang/target/property/PlatformProperty.java +++ b/lfc/core/src/main/java/org/lflang/target/property/PlatformProperty.java @@ -121,6 +121,9 @@ public void validate(TargetConfig config, MessageReporter reporter) { case ZEPHYR: validateZephyr(config, reporter); break; + case PATMOS: + validatePatmos(config, reporter); + break; default: break; } @@ -165,6 +168,8 @@ private void validateFlexPRET(TargetConfig config, MessageReporter reporter) { private void validateZephyr(TargetConfig config, MessageReporter reporter) {} + private void validatePatmos(TargetConfig config, MessageReporter reporter) {} + @Override public Element toAstElement(PlatformOptions value) { Element e = LfFactory.eINSTANCE.createElement(); diff --git a/lfc/core/src/main/java/org/lflang/target/property/type/PlatformType.java b/lfc/core/src/main/java/org/lflang/target/property/type/PlatformType.java index 0cc6b2f56..a92456534 100644 --- a/lfc/core/src/main/java/org/lflang/target/property/type/PlatformType.java +++ b/lfc/core/src/main/java/org/lflang/target/property/type/PlatformType.java @@ -21,7 +21,8 @@ public enum Platform { ZEPHYR("Zephyr"), RIOT("RIOT"), FLEXPRET("FlexPRET"), - WINDOWS("Windows"); + WINDOWS("Windows"), + PATMOS("Patmos"); final String cMakeName; diff --git a/src/network_channel.c b/src/network_channel.c index 43c91f93f..f690dd31e 100644 --- a/src/network_channel.c +++ b/src/network_channel.c @@ -31,8 +31,8 @@ #endif #elif defined(PLATFORM_PATMOS) -#ifdef NETWORK_CHANNEL_TCP_POSIX -#error "NETWORK_POSIX_TCP not supported on Patmos" +#ifdef NETWORK_CHANNEL_S4NOC +#include "platform/patmos/s4noc_channel.c" #endif #endif diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c new file mode 100644 index 000000000..967c29a20 --- /dev/null +++ b/src/platform/patmos/s4noc_channel.c @@ -0,0 +1,126 @@ +#include "reactor-uc/platform/patmos/s4noc_channel.h" +#include "reactor-uc/logging.h" +#include "reactor-uc/serialization.h" +#include "machine/patmos.h" +#include + +#define S4NOC_CHANNEL_ERR(fmt, ...) LF_ERR(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) +#define S4NOC_CHANNEL_WARN(fmt, ...) LF_WARN(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) +#define S4NOC_CHANNEL_INFO(fmt, ...) LF_INFO(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) +#define S4NOC_CHANNEL_DEBUG(fmt, ...) LF_DEBUG(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) + +static lf_ret_t S4NOCPollChannel_open_connection(NetworkChannel *untyped_self) { + S4NOC_CHANNEL_DEBUG("Open connection"); + (void)untyped_self; + return LF_OK; +} + +static void S4NOCPollChannel_close_connection(NetworkChannel *untyped_self) { + S4NOC_CHANNEL_DEBUG("Close connection"); + (void)untyped_self; +} + +static void S4NOCPollChannel_free(NetworkChannel *untyped_self) { + S4NOC_CHANNEL_DEBUG("Free"); + (void)untyped_self; +} + +static bool S4NOCPollChannel_is_connected(NetworkChannel *untyped_self) { + S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; + + return self->state == NETWORK_CHANNEL_STATE_CONNECTED; +} + +static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, const FederateMessage *message) { + S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; + + volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); + volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); + + if (self->state == NETWORK_CHANNEL_STATE_CONNECTED) { + int message_size = serialize_message(message, self->write_buffer, S4NOC_CHANNEL_BUFFERSIZE); + S4NOC_CHANNEL_DEBUG("Sending Message of Size: %i", message_size); + + *s4noc_dest = self->destination_core; + int bytes_send = 0; + while (bytes_send < message_size) { + *s4noc_data = ((int *)self->write_buffer)[bytes_send / 4]; + bytes_send += 4; + } + + return LF_OK; + } else { + return LF_ERR; + } +} + +static void S4NOCPollChannel_register_receive_callback(NetworkChannel *untyped_self, + void (*receive_callback)(FederatedConnectionBundle *conn, + const FederateMessage *msg), + FederatedConnectionBundle *conn) { + S4NOC_CHANNEL_INFO("Register receive callback"); + S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; + + self->receive_callback = receive_callback; + self->federated_connection = conn; +} + +void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { + S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; + + volatile _IODEV int *s4noc_status = (volatile _IODEV int *)PATMOS_IO_S4NOC; + volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); + volatile _IODEV int *s4noc_source = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); + + if (((*s4noc_status) & 0x02) == 0) { + return; + } + + int value = *s4noc_data; + int source = *s4noc_source; + + S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[get_cpuid()][source]; + + ((int *)receive_channel->receive_buffer)[receive_channel->receive_buffer_index / 4] = value; + receive_channel->receive_buffer_index += 4; + + int expected_message_size = ntohl(*((int *)receive_channel->receive_buffer)); + if (expected_message_size + 4 > receive_channel->receive_buffer_index) { + int bytes_left = deserialize_from_protobuf(&receive_channel->output, receive_channel->receive_buffer + 1, + self->receive_buffer_index - 4); + S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize %d", bytes_left); + + if (bytes_left >= 0) { + int receive_buffer_index = receive_channel->receive_buffer_index; + receive_channel->receive_buffer_index = bytes_left; + + if (receive_channel->receive_callback != NULL) { + S4NOC_CHANNEL_DEBUG("calling user callback!"); + receive_channel->receive_callback(self->federated_connection, &self->output); + } + } + } +} + +void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned int destination_core) { + assert(self != NULL); + assert(env != NULL); + + self->super.super.mode = NETWORK_CHANNEL_MODE_POLL; + self->super.super.expected_connect_duration = SEC(0); + self->super.super.type = NETWORK_CHANNEL_TYPE_S4NOC; + self->super.super.is_connected = S4NOCPollChannel_is_connected; + self->super.super.open_connection = S4NOCPollChannel_open_connection; + self->super.super.close_connection = S4NOCPollChannel_close_connection; + self->super.super.send_blocking = S4NOCPollChannel_send_blocking; + self->super.super.register_receive_callback = S4NOCPollChannel_register_receive_callback; + self->super.super.free = S4NOCPollChannel_free; + self->super.poll = S4NOCPollChannel_poll; + + // Concrete fields + self->receive_buffer_index = 0; + self->receive_callback = NULL; + self->federated_connection = NULL; + self->state = NETWORK_CHANNEL_STATE_CONNECTED; + self->destination_core = destination_core; +} diff --git a/test/lf/src/HelloPatmos.lf b/test/lf/src/HelloPatmos.lf new file mode 100644 index 000000000..37aa76248 --- /dev/null +++ b/test/lf/src/HelloPatmos.lf @@ -0,0 +1,31 @@ +target uC { + platform: Patmos, + logging:debug +} + +reactor R1 { + output out: int + + reaction(startup) -> out {= + lf_set(out, 42); + =} +} + +reactor R2 { + input in: int + + reaction(startup) {= + printf("Hello from R2, Patmos!\n"); + =} + + reaction(in) {= + printf("Received: %d\n", in->value); + validate(in->value == 42); + =} +} + +main reactor { + r1 = new R1() + r2 = new R2() + r1.out -> r2.in +} diff --git a/test/platform/patmos/HelloPatmos.c b/test/platform/patmos/HelloPatmos.c new file mode 100644 index 000000000..75073ca5a --- /dev/null +++ b/test/platform/patmos/HelloPatmos.c @@ -0,0 +1,3 @@ +void main () { + printf("Hello Patmos!\n"); +} \ No newline at end of file diff --git a/test/platform/patmos/Makefile b/test/platform/patmos/Makefile new file mode 100644 index 000000000..6956d946c --- /dev/null +++ b/test/platform/patmos/Makefile @@ -0,0 +1,28 @@ +# Rules +all: build/HelloPatmos.elf + +# Compiler and tools for PATMOS +CC = patmos-clang + +# Paths +SRC_DIR = $(CURDIR) +BUILD_DIR = $(CURDIR)/build + +# Source files +SOURCES = $(SRC_DIR)/HelloPatmos.c + +# Compiler flags +CFLAGS = -O2 -Wall -Wextra -Werror + +# Output binary +OUTPUT = $(BUILD_DIR)/HelloPatmos.elf + +# Build rule +$(OUTPUT): $(SOURCES) + mkdir -p $(BUILD_DIR) + $(CC) $(CFLAGS) $(SOURCES) -o $(OUTPUT) + +clean: + rm -rf $(BUILD_DIR) + +.PHONY: all clean diff --git a/test/platform/patmos/runAll.sh b/test/platform/patmos/runAll.sh new file mode 100755 index 000000000..61d0f2d01 --- /dev/null +++ b/test/platform/patmos/runAll.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +# Make test +make all diff --git a/test/unit/s4noc_channel_test.c b/test/unit/s4noc_channel_test.c new file mode 100644 index 000000000..9ced55e26 --- /dev/null +++ b/test/unit/s4noc_channel_test.c @@ -0,0 +1,89 @@ +#include "reactor-uc/platform/patmos/s4noc_channel.h" +#include "reactor-uc/environments/federated_environment.h" +#include "unity.h" +#include "test_util.h" +#include + +#define MESSAGE_CONTENT "Hello S4NOC" +#define MESSAGE_CONNECTION_ID 42 +#define DESTINATION_CORE 1 +#define SOURCE_CORE 0 + +Reactor parent; +FederatedEnvironment fed_env; +Environment *_lf_environment = &fed_env.super; +FederatedConnectionBundle sender_bundle; +FederatedConnectionBundle receiver_bundle; +FederatedConnectionBundle *net_bundles[] = {&sender_bundle, &receiver_bundle}; + +S4NOCPollChannel sender_channel; +S4NOCPollChannel receiver_channel; +NetworkChannel *sender = (NetworkChannel *)&sender_channel.super; +NetworkChannel *receiver = (NetworkChannel *)&receiver_channel.super; + +bool receiver_callback_called = false; + +void setUp(void) { + FederatedEnvironment_ctor(&fed_env, &parent, NULL, false, net_bundles, 2, NULL, NULL); + + S4NOCPollChannel_ctor(&sender_channel, &fed_env.super, DESTINATION_CORE); + S4NOCPollChannel_ctor(&receiver_channel, &fed_env.super, SOURCE_CORE); + + FederatedConnectionBundle_ctor(&sender_bundle, &parent, sender, NULL, NULL, 0, NULL, NULL, 0, 0); + FederatedConnectionBundle_ctor(&receiver_bundle, &parent, receiver, NULL, NULL, 0, NULL, NULL, 0, 0); + + s4noc_global_state.core_channels[SOURCE_CORE][DESTINATION_CORE] = &receiver_channel; +} + +void tearDown(void) { + sender->free(sender); + receiver->free(receiver); +} + +void test_open_connection(void) { + TEST_ASSERT_OK(sender->open_connection(sender)); + TEST_ASSERT_OK(receiver->open_connection(receiver)); + + TEST_ASSERT_TRUE(sender->is_connected(sender)); + TEST_ASSERT_TRUE(receiver->is_connected(receiver)); +} + +void receiver_callback_handler(FederatedConnectionBundle *self, const FederateMessage *_msg) { + (void)self; + const TaggedMessage *msg = &_msg->message.tagged_message; + printf("\nReceiver: Received message with connection number %i and content %s\n", msg->conn_id, + (char *)msg->payload.bytes); + TEST_ASSERT_EQUAL_STRING(MESSAGE_CONTENT, (char *)msg->payload.bytes); + TEST_ASSERT_EQUAL(MESSAGE_CONNECTION_ID, msg->conn_id); + + receiver_callback_called = true; +} + +void test_sender_send_and_receiver_recv(void) { + TEST_ASSERT_OK(sender->open_connection(sender)); + TEST_ASSERT_OK(receiver->open_connection(receiver)); + + receiver->register_receive_callback(receiver, receiver_callback_handler, NULL); + + FederateMessage msg; + msg.which_message = FederateMessage_tagged_message_tag; + + TaggedMessage *port_message = &msg.message.tagged_message; + port_message->conn_id = MESSAGE_CONNECTION_ID; + const char *message = MESSAGE_CONTENT; + memcpy(port_message->payload.bytes, message, sizeof(MESSAGE_CONTENT)); // NOLINT + port_message->payload.size = sizeof(MESSAGE_CONTENT); + + TEST_ASSERT_OK(sender->send_blocking(sender, &msg)); + + ((PolledNetworkChannel *)&receiver_channel.super)->poll((PolledNetworkChannel *)&receiver_channel.super); + + TEST_ASSERT_TRUE(receiver_callback_called); +} + +int main(void) { + UNITY_BEGIN(); + RUN_TEST(test_open_connection); + RUN_TEST(test_sender_send_and_receiver_recv); + return UNITY_END(); +} \ No newline at end of file From de6bb6d8c9f44505d45eefe492990657d6ca8e07 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 13 May 2025 16:19:55 +0200 Subject: [PATCH 02/28] Patmos and S4NoC support: 2nd commit --- CMakeLists.txt | 26 +++++++++- README.md | 12 +++++ examples/fed-template/buildAll.sh | 13 +++-- examples/flexpret/buildAll.sh | 12 +++-- examples/patmos/buildAll.sh | 27 ++++++++++ examples/patmos/hello/Makefile | 27 ++++++++++ examples/patmos/hello/build.sh | 4 ++ examples/patmos/hello/hello.c | 5 ++ examples/patmos/hello_lf/Makefile | 36 +++++++++++++ examples/patmos/hello_lf/build.sh | 5 ++ examples/patmos/hello_lf/src/HelloLF.lf | 9 ++++ .../uc/UcFederatedProjectTemplateGenerator.kt | 35 +++++++++++++ .../lflang/generator/uc/UcMakeGenerator.kt | 1 + .../lflang/generator/uc/UcNetworkChannel.kt | 50 ++++++++++++++++++- src/platform/patmos/patmos.c | 11 ++-- test/lf/src/HelloPatmos.lf | 31 ------------ test/platform/patmos/HelloPatmos.c | 3 -- test/platform/patmos/Makefile | 9 ++-- test/platform/patmos/hello.c | 5 ++ test/platform/patmos/runAll.sh | 2 + test/unit/s4noc_channel_test.c | 3 +- 21 files changed, 269 insertions(+), 57 deletions(-) create mode 100755 examples/patmos/buildAll.sh create mode 100644 examples/patmos/hello/Makefile create mode 100755 examples/patmos/hello/build.sh create mode 100644 examples/patmos/hello/hello.c create mode 100755 examples/patmos/hello_lf/Makefile create mode 100755 examples/patmos/hello_lf/build.sh create mode 100644 examples/patmos/hello_lf/src/HelloLF.lf delete mode 100644 test/lf/src/HelloPatmos.lf delete mode 100644 test/platform/patmos/HelloPatmos.c create mode 100644 test/platform/patmos/hello.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e74e53ad..48f3b416f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ set(ASAN OFF CACHE BOOL "Compile with AddressSanitizer") set(PLATFORM "POSIX" CACHE STRING "Platform to target") set(SCHEDULER "DYNAMIC" CACHE STRING "Scheduler to use") set(NETWORK_CHANNEL_TCP_POSIX OFF CACHE BOOL "Use POSIX TCP NetworkChannel") +set(NETWORK_CHANNEL_S4NOC OFF CACHE BOOL "Use S4NOC NetworkChannel") set(FEDERATED OFF CACHE BOOL "Compile with federated sources") message("PLATFORM is set to: ${PLATFORM}") @@ -33,6 +34,7 @@ if(BUILD_TESTS) set(BUILD_LF_TESTS ON) set(BUILD_UNIT_TESTS ON) set(NETWORK_CHANNEL_TCP_POSIX ON) # TODO: This is currently needed because one of the tests uses this stack, we need a nicer way of selecting build options for tests and apps. + set(NETWORK_CHANNEL_S4NOC ON) # TODO: This is currently needed because one of the tests uses this stack, we need a nicer way of selecting build options for tests and apps. set(FEDERATED ON) set(CMAKE_BUILD_TYPE "Debug") find_program(CLANG_TIDY clang-tidy) @@ -69,12 +71,12 @@ elseif (PLATFORM STREQUAL "PICO") elseif (PLATFORM STREQUAL "PATMOS") find_program(CLANG_EXECUTABLE NAMES patmos-clang REQUIRED DOC \"Path to the clang" + " front-end.\") set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE}) + set(CMAKE_C_COMPILER_ID ${CLANG_EXECUTABLE}) message("Using compiler: ${CMAKE_C_COMPILER}") set(CMAKE_C_FLAGS_RELEASE \"-O2 -DNDEBUG\") # target_compile_options(reactor-uc PRIVATE -Wno-zero-length-bounds) file(GLOB PATMOS_SOURCES "src/platform/patmos/*.c") - list(APPEND SOURCES ${PATMOS_SOURCES}) - add_library(reactor-uc STATIC ${SOURCES}) + add_library(reactor-uc PRIVATE ${PATMOS_SOURCES}) else () message(FATAL_ERROR "No valid platform specified") endif () @@ -96,6 +98,26 @@ if(NETWORK_CHANNEL_TCP_POSIX) target_compile_definitions(reactor-uc PRIVATE NETWORK_CHANNEL_TCP_POSIX) endif() +if(NETWORK_CHANNEL_S4NOC) + find_program(CLANG_EXECUTABLE NAMES patmos-clang REQUIRED DOC \"Path to the clang" + " front-end.\") + # set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE}) + set(CMAKE_C_COMPILER_ID ${CLANG_EXECUTABLE}) + # message("Using compiler: ${CMAKE_C_COMPILER}") + set(CMAKE_C_FLAGS_RELEASE \"-O2 -DNDEBUG\") + + # target_compile_definitions(reactor-uc PRIVATE NETWORK_CHANNEL_S4NOC) + # target_include_directories(reactor-uc PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/reactor-uc/platform/patmos) + # file(GLOB PATMOS_SOURCES "src/platform/patmos/*.c") + # list(APPEND SOURCES ${PATMOS_SOURCES}) + # message("Sources: ${SOURCES}") + # target_link_libraries(reactor-uc PRIVATE ${SOURCES}) + + target_compile_definitions(reactor-uc PRIVATE NETWORK_CHANNEL_S4NOC) + # target_include_directories(reactor-uc PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/reactor-uc/platform/patmos) + file(GLOB S4NOC_SOURCES "src/platform/patmos/*.c") + target_sources(reactor-uc PRIVATE ${S4NOC_SOURCES}) +endif() + if(FEDERATED) target_compile_definitions(reactor-uc PUBLIC FEDERATED) endif() diff --git a/README.md b/README.md index 51ad3ea9e..813c5a438 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,18 @@ cd build make ``` +### Patmos + +To install Patmos, follow instructions in [https://github.com/t-crest/patmos/](https://github.com/t-crest/patmos) readme file. For now, use the previous version of compiler by running `./misc/build.sh toolchain1`. + +Compile and run a Hello World example by running these lines: + +```shell +cd examples/patmos/hello +make all +pasim build/hello.elf +``` + ## Contributing ### Code organization diff --git a/examples/fed-template/buildAll.sh b/examples/fed-template/buildAll.sh index bfe78ea93..3c463274e 100755 --- a/examples/fed-template/buildAll.sh +++ b/examples/fed-template/buildAll.sh @@ -10,8 +10,11 @@ cmake -Bbuild cmake --build build popd -pushd MyFed/dest -./run_lfc.sh -west build -popd - +if ! command -v west &> /dev/null; then + echo "Error: 'west' is not installed." +else + pushd MyFed/dest + ./run_lfc.sh + west build + popd +fi diff --git a/examples/flexpret/buildAll.sh b/examples/flexpret/buildAll.sh index 98299bb5d..f8d98d9df 100755 --- a/examples/flexpret/buildAll.sh +++ b/examples/flexpret/buildAll.sh @@ -1,5 +1,9 @@ set -e -${REACTOR_UC_PATH}/lfc/bin/lfc-dev src/Smoke.lf -cmake -Bbuild -make -C build -bin/fp-smoke \ No newline at end of file +if [ -z "$FP_SDK_PATH" ]; then + echo "Error: FP_SDK_PATH is not defined. Please set it before running this script." +else + ${REACTOR_UC_PATH}/lfc/bin/lfc-dev src/Smoke.lf + cmake -Bbuild + make -C build + bin/fp-smoke +fi \ No newline at end of file diff --git a/examples/patmos/buildAll.sh b/examples/patmos/buildAll.sh new file mode 100755 index 000000000..74226ffd2 --- /dev/null +++ b/examples/patmos/buildAll.sh @@ -0,0 +1,27 @@ +# set -e +# echo "Building Patmos example" +# ${REACTOR_UC_PATH}/lfc/bin/lfc-dev hello_lf/src/HelloLF.lf +# cmake -Bbuild -DPLATFORM=PATMOS +# make -C build + +# echo "Running Patmos example" +# pasim ./bin/hello_lf.elf + + +#!/bin/bash + +set -e + +if ! command -v pasim &> /dev/null; then + echo "Error: pasim command not found. Please ensure it is installed and available in your PATH." +else + # Iterate over each folder and execute the command + for dir in ./*; do + if [ -d $dir ]; then + echo "Entering $dir" + pushd $dir + ./build.sh + popd + fi + done +fi \ No newline at end of file diff --git a/examples/patmos/hello/Makefile b/examples/patmos/hello/Makefile new file mode 100644 index 000000000..947fb3485 --- /dev/null +++ b/examples/patmos/hello/Makefile @@ -0,0 +1,27 @@ +# Makefile for building a simple Hello World program for the Patmos platform + +# Compiler and tools for PATMOS +CC = patmos-clang + +# Paths +SRC_DIR = $(CURDIR) +BUILD_DIR = $(CURDIR)/build + +# Source files +SOURCES = $(SRC_DIR)/hello.c + +# Compiler flags +CFLAGS = -O2 -Wall -Wextra -Werror + +# Output binary +OUTPUT = $(BUILD_DIR)/hello.elf +all : $(OUTPUT) +# Build rule +$(OUTPUT): $(SOURCES) + mkdir -p $(BUILD_DIR) + $(CC) $(CFLAGS) $(SOURCES) -o $(OUTPUT) + +clean: + rm -rf $(BUILD_DIR) + +.PHONY: all clean diff --git a/examples/patmos/hello/build.sh b/examples/patmos/hello/build.sh new file mode 100755 index 000000000..ff973f880 --- /dev/null +++ b/examples/patmos/hello/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +rm -rf build +make all +pasim ./build/hello.elf \ No newline at end of file diff --git a/examples/patmos/hello/hello.c b/examples/patmos/hello/hello.c new file mode 100644 index 000000000..a5bafc3f2 --- /dev/null +++ b/examples/patmos/hello/hello.c @@ -0,0 +1,5 @@ +#include +int main () { + printf("Hello Patmos!\n"); + return 0; +} \ No newline at end of file diff --git a/examples/patmos/hello_lf/Makefile b/examples/patmos/hello_lf/Makefile new file mode 100755 index 000000000..7356bd930 --- /dev/null +++ b/examples/patmos/hello_lf/Makefile @@ -0,0 +1,36 @@ +REACTOR_UC_PATH ?= $(CURDIR)/../../../ +LF_MAIN ?= HelloLF + +# The name of the LF application inside "./src" to build/run/flash etc. +SRC_GEN_PATH ?= ./src-gen/$(LF_MAIN) + +# Execute the LF compiler if build target is "all" +ifeq ($(firstword $(MAKECMDGOALS)),all) + _ := $(shell $(REACTOR_UC_PATH)/lfc/bin/lfc-dev src/$(LF_MAIN).lf) +endif + +# ---- Patmos specific configuration ---- +include ./src-gen/$(LF_MAIN)/Makefile + +SRC = $(REACTOR_UC_PATH)/src/*.c +SRC += $(patsubst %, $(SRC_GEN_PATH)/%, $(LFC_GEN_SOURCES) $(LFC_GEN_MAIN)) + +INC = -I$(REACTOR_UC_PATH)/include -I$(REACTOR_UC_PATH)/external -I$(SRC_GEN_PATH) +FLG = -DPLATFORM_PATMOS -DSCHEDULER_DYNAMIC -DEVENT_QUEUE_SIZE=$(EVENT_QUEUE_SIZE) -DREACTION_QUEUE_SIZE=$(REACTION_QUEUE_SIZE) -O2 + +# Output directory +BIN_DIR = $(CURDIR)/bin +OUTPUT = $(BIN_DIR)/$(LF_MAIN) + +all: $(OUTPUT) + +# Build rule +$(OUTPUT): $(SRC) + mkdir -p $(BIN_DIR) + patmos-clang $(SRC) $(INC) $(FLG) -o $(OUTPUT) -Wno-everything + +clean: + rm -rf $(BIN_DIR) ./src-gen + +.PHONY: all clean + diff --git a/examples/patmos/hello_lf/build.sh b/examples/patmos/hello_lf/build.sh new file mode 100755 index 000000000..8fef4bd05 --- /dev/null +++ b/examples/patmos/hello_lf/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +rm -rf bin src-gen +make all +pasim ./bin/HelloLF \ No newline at end of file diff --git a/examples/patmos/hello_lf/src/HelloLF.lf b/examples/patmos/hello_lf/src/HelloLF.lf new file mode 100644 index 000000000..1d165ba9d --- /dev/null +++ b/examples/patmos/hello_lf/src/HelloLF.lf @@ -0,0 +1,9 @@ +target uC { + platform: Patmos +} + +main reactor { + reaction(startup) {= + printf("Hello LF on PATMOS!\n"); + =} +} \ No newline at end of file diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt index 96fec14d7..b5d95b727 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt @@ -132,6 +132,40 @@ class UcFederatedTemplateGenerator( FileUtil.writeToFile(cmake, projectRoot.resolve("CMakeLists.txt")) } + private fun generateFilesPatmos() { + val make = + """ + |# Compiler and tools for PATMOS + |CC = patmos-clang + | + |# Paths + |SRC_DIR = src-gen/${mainDef.name}/${federate.name} + |BUILD_DIR = build + | + |# Source files + |SOURCES = $S(SRC_DIR)/*.c + | + |# Compiler flags + |CFLAGS = -O2 -Wall -Wextra -Werror + | + |# Output binary + |OUTPUT = $S(BUILD_DIR)/${federate.name}.elf + | + |all: $S(OUTPUT) + | + |$S(OUTPUT): $S(SOURCES) + | mkdir -p $S(BUILD_DIR) + | $S(CC) $S(CFLAGS) $S(SOURCES) -o $S(OUTPUT) + | + |clean: + | rm -rf $S(BUILD_DIR) + | + |.PHONY: all clean + """ + .trimMargin() + FileUtil.writeToFile(make, projectRoot.resolve("Makefile")) + } + fun generateFiles() { if (Files.exists(projectRoot)) { // Skipping since project template already exists @@ -151,6 +185,7 @@ class UcFederatedTemplateGenerator( PlatformType.Platform.NATIVE -> generateFilesNative() PlatformType.Platform.ZEPHYR -> generateFilesZephyr() PlatformType.Platform.RIOT -> generateFilesRiot() + PlatformType.Platform.PATMOS -> generateFilesPatmos() else -> messageReporter .nowhere() diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcMakeGenerator.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcMakeGenerator.kt index 53e921003..1376e1c8f 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcMakeGenerator.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcMakeGenerator.kt @@ -54,6 +54,7 @@ class UcMakeGeneratorFederated( NetworkChannelType.TCP_IP -> "CFLAGS += -DNETWORK_CHANNEL_TCP" NetworkChannelType.COAP_UDP_IP -> "CFLAGS += -DNETWORK_CHANNEL_COAP" NetworkChannelType.UART -> "CFLAGS += -DNETWORK_CHANNEL_UART" + NetworkChannelType.S4NOC -> "CFLAGS += -DNETWORK_CHANNEL_S4NOC" NetworkChannelType.NONE -> "" NetworkChannelType.CUSTOM -> "" } diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt index ec6db3c73..f0034df43 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt @@ -10,6 +10,7 @@ enum class NetworkChannelType { TCP_IP, CUSTOM, COAP_UDP_IP, + S4NOC, UART, NONE } @@ -43,6 +44,7 @@ object UcNetworkInterfaceFactory { "tcp" -> creators.get(TCP_IP)!!.invoke(federate, attr) "uart" -> creators.get(UART)!!.invoke(federate, attr) "coap" -> creators.get(COAP_UDP_IP)!!.invoke(federate, attr) + "s4noc" -> creators.get(S4NOC)!!.invoke(federate, attr) "custom" -> creators.get(CUSTOM)!!.invoke(federate, attr) else -> throw IllegalArgumentException("Unrecognized interface attribute $attr") } @@ -72,6 +74,9 @@ class UcUARTEndpoint( class UcCoapUdpIpEndpoint(val ipAddress: IPAddress, iface: UcCoapUdpIpInterface) : UcNetworkEndpoint(iface) {} +class UcS4NocEndpoint(val s4nocId: Int, val port: Int, iface: UcS4NocInterface) : + UcNetworkEndpoint(iface) {} + class UcCustomEndpoint(iface: UcCustomInterface) : UcNetworkEndpoint(iface) {} // A federate can have several NetworkInterfaces, which are specified using attributes in the LF @@ -195,6 +200,27 @@ class UcCoapUdpIpInterface(private val ipAddress: IPAddress, name: String? = nul } } +class UcS4NocInterface(val s4nocId: Int, val port: Int, name: String? = null) : + UcNetworkInterface(S4NOC, name ?: "s4noc") { + override val includeHeaders: String = "" + override val compileDefs: String = "NETWORK_CHANNEL_S4NOC" + + fun createEndpoint(): UcS4NocEndpoint { + val ep = UcS4NocEndpoint(s4nocId, port, this) + endpoints.add(ep) + return ep + } + + companion object { + fun fromAttribute(federate: UcFederate, attr: Attribute): UcS4NocInterface { + val s4nocId = attr.getParamInt("s4noc_id") ?: 0 + val port = attr.getParamInt("port") ?: 0 + val name = attr.getParamString("name") + return UcS4NocInterface(s4nocId, port, name) + } + } +} + class UcCustomInterface(name: String, val include: String, val args: String? = null) : UcNetworkInterface(CUSTOM, name) { override val compileDefs = "" @@ -288,7 +314,11 @@ abstract class UcNetworkChannel( val destEp = (destIf as UcCoapUdpIpInterface).createEndpoint() channel = UcCoapUdpIpChannel(srcEp, destEp) } - + S4NOC -> { + val srcEp = (srcIf as UcS4NocInterface).createEndpoint() + val destEp = (destIf as UcS4NocInterface).createEndpoint() + channel = UcS4NocChannel(srcEp, destEp) + } CUSTOM -> { val srcEp = (srcIf as UcCustomInterface).createEndpoint() val destEp = (destIf as UcCustomInterface).createEndpoint() @@ -362,6 +392,24 @@ class UcCoapUdpIpChannel( get() = "CoapUdpIpChannel" } +class UcS4NocChannel( + src: UcS4NocEndpoint, + dest: UcS4NocEndpoint, + serverLhs: Boolean = true, +) : UcNetworkChannel(S4NOC, src, dest, serverLhs) { + private val srcS4Noc = src + private val destS4Noc = dest + + override fun generateChannelCtorSrc() = + "S4NocChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.s4nocId else destS4Noc.s4nocId}, ${if (serverLhs) srcS4Noc.port else destS4Noc.port});" + + override fun generateChannelCtorDest() = + "S4NocChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.s4nocId else destS4Noc.s4nocId}, ${if (serverLhs) srcS4Noc.port else destS4Noc.port});" + + override val codeType: String + get() = "S4NocChannel" +} + class UcCustomChannel( src: UcCustomEndpoint, dest: UcCustomEndpoint, diff --git a/src/platform/patmos/patmos.c b/src/platform/patmos/patmos.c index 0ae35c732..7fbe7ac27 100644 --- a/src/platform/patmos/patmos.c +++ b/src/platform/patmos/patmos.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -20,7 +21,7 @@ instant_t PlatformPatmos_get_physical_time(Platform *super) { lf_ret_t PlatformPatmos_wait_until_interruptible(Platform *super, instant_t wakeup_time) { PlatformPatmos *self = (PlatformPatmos *)super; self->async_event = false; - super->leave_critical_section(super); // turing on interrupts + //super->leave_critical_section(super); // turing on interrupts instant_t now = super->get_physical_time(super); @@ -29,7 +30,7 @@ lf_ret_t PlatformPatmos_wait_until_interruptible(Platform *super, instant_t wake now = super->get_physical_time(super); } while ((now < wakeup_time) && !self->async_event); - super->enter_critical_section(super); + //super->enter_critical_section(super); if (self->async_event) { self->async_event = false; @@ -43,7 +44,7 @@ lf_ret_t PlatformPatmos_wait_until_interruptible(Platform *super, instant_t wake return LF_OK; } - super->leave_critical_section(super); + //super->leave_critical_section(super); return LF_OK; } @@ -97,7 +98,7 @@ void Platform_ctor(Platform *super) { super->get_physical_time = PlatformPatmos_get_physical_time; super->wait_until = PlatformPatmos_wait_until; super->wait_for = PlatformPatmos_wait_for; - super->wait_until_interruptible_locked = PlatformPatmos_wait_until_interruptible; + super->wait_until_interruptible = PlatformPatmos_wait_until_interruptible; super->notify = PlatformPatmos_notify; self->num_nested_critical_sections = 0; } @@ -130,5 +131,5 @@ void Mutex_ctor(Mutex *super) { MutexPatmos *self = (MutexPatmos *)super; super->lock = MutexPatmos_lock; super->unlock = MutexPatmos_unlock; - critical_section_init(&self->crit_sec); + //critical_section_init(&self->crit_sec); } \ No newline at end of file diff --git a/test/lf/src/HelloPatmos.lf b/test/lf/src/HelloPatmos.lf deleted file mode 100644 index 37aa76248..000000000 --- a/test/lf/src/HelloPatmos.lf +++ /dev/null @@ -1,31 +0,0 @@ -target uC { - platform: Patmos, - logging:debug -} - -reactor R1 { - output out: int - - reaction(startup) -> out {= - lf_set(out, 42); - =} -} - -reactor R2 { - input in: int - - reaction(startup) {= - printf("Hello from R2, Patmos!\n"); - =} - - reaction(in) {= - printf("Received: %d\n", in->value); - validate(in->value == 42); - =} -} - -main reactor { - r1 = new R1() - r2 = new R2() - r1.out -> r2.in -} diff --git a/test/platform/patmos/HelloPatmos.c b/test/platform/patmos/HelloPatmos.c deleted file mode 100644 index 75073ca5a..000000000 --- a/test/platform/patmos/HelloPatmos.c +++ /dev/null @@ -1,3 +0,0 @@ -void main () { - printf("Hello Patmos!\n"); -} \ No newline at end of file diff --git a/test/platform/patmos/Makefile b/test/platform/patmos/Makefile index 6956d946c..947fb3485 100644 --- a/test/platform/patmos/Makefile +++ b/test/platform/patmos/Makefile @@ -1,5 +1,4 @@ -# Rules -all: build/HelloPatmos.elf +# Makefile for building a simple Hello World program for the Patmos platform # Compiler and tools for PATMOS CC = patmos-clang @@ -9,14 +8,14 @@ SRC_DIR = $(CURDIR) BUILD_DIR = $(CURDIR)/build # Source files -SOURCES = $(SRC_DIR)/HelloPatmos.c +SOURCES = $(SRC_DIR)/hello.c # Compiler flags CFLAGS = -O2 -Wall -Wextra -Werror # Output binary -OUTPUT = $(BUILD_DIR)/HelloPatmos.elf - +OUTPUT = $(BUILD_DIR)/hello.elf +all : $(OUTPUT) # Build rule $(OUTPUT): $(SOURCES) mkdir -p $(BUILD_DIR) diff --git a/test/platform/patmos/hello.c b/test/platform/patmos/hello.c new file mode 100644 index 000000000..a5bafc3f2 --- /dev/null +++ b/test/platform/patmos/hello.c @@ -0,0 +1,5 @@ +#include +int main () { + printf("Hello Patmos!\n"); + return 0; +} \ No newline at end of file diff --git a/test/platform/patmos/runAll.sh b/test/platform/patmos/runAll.sh index 61d0f2d01..443f36ec7 100755 --- a/test/platform/patmos/runAll.sh +++ b/test/platform/patmos/runAll.sh @@ -1,4 +1,6 @@ #!/bin/bash # Make test +rm -r build make all +pasim ./build/*.elf diff --git a/test/unit/s4noc_channel_test.c b/test/unit/s4noc_channel_test.c index 9ced55e26..212287b6e 100644 --- a/test/unit/s4noc_channel_test.c +++ b/test/unit/s4noc_channel_test.c @@ -1,4 +1,5 @@ -#include "reactor-uc/platform/patmos/s4noc_channel.h" +#include "reactor-uc/platform/patmos/s4noc_channel.h" +#include "reactor-uc/reactor-uc.h" #include "reactor-uc/environments/federated_environment.h" #include "unity.h" #include "test_util.h" From 5450bbb7ee74c3237cf6ed0e6141a131b56d7a2c Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 22 May 2025 14:53:25 +0200 Subject: [PATCH 03/28] Patmos and S4NoC: 3rd Commit --- CMakeLists.txt | 33 +----------- .../platform/patmos/s4noc_channel.h | 6 +-- make/patmos/patmos-lfc.mk | 52 +++++++++++++++++++ make/patmos/patmos.mk | 28 ++++++++++ src/platform/patmos/s4noc_channel.c | 31 +++++++---- test/platform/patmos/{ => hello}/Makefile | 0 test/platform/patmos/{ => hello}/hello.c | 0 test/platform/patmos/hello/run.sh | 6 +++ test/platform/patmos/runAll.sh | 15 ++++-- .../patmos/s4noc_channel_test/Makefile | 32 ++++++++++++ .../patmos/s4noc_channel_test/main.c} | 19 ++++--- .../platform/patmos/s4noc_channel_test/run.sh | 7 +++ 12 files changed, 171 insertions(+), 58 deletions(-) create mode 100644 make/patmos/patmos-lfc.mk create mode 100644 make/patmos/patmos.mk rename test/platform/patmos/{ => hello}/Makefile (100%) rename test/platform/patmos/{ => hello}/hello.c (100%) create mode 100755 test/platform/patmos/hello/run.sh create mode 100644 test/platform/patmos/s4noc_channel_test/Makefile rename test/{unit/s4noc_channel_test.c => platform/patmos/s4noc_channel_test/main.c} (86%) create mode 100755 test/platform/patmos/s4noc_channel_test/run.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 48f3b416f..66b128bc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,11 +10,8 @@ set(ASAN OFF CACHE BOOL "Compile with AddressSanitizer") set(PLATFORM "POSIX" CACHE STRING "Platform to target") set(SCHEDULER "DYNAMIC" CACHE STRING "Scheduler to use") set(NETWORK_CHANNEL_TCP_POSIX OFF CACHE BOOL "Use POSIX TCP NetworkChannel") -set(NETWORK_CHANNEL_S4NOC OFF CACHE BOOL "Use S4NOC NetworkChannel") set(FEDERATED OFF CACHE BOOL "Compile with federated sources") -message("PLATFORM is set to: ${PLATFORM}") - # Code coverage setup if(TEST_COVERAGE) set(CMAKE_BUILD_TYPE "Debug") @@ -34,7 +31,6 @@ if(BUILD_TESTS) set(BUILD_LF_TESTS ON) set(BUILD_UNIT_TESTS ON) set(NETWORK_CHANNEL_TCP_POSIX ON) # TODO: This is currently needed because one of the tests uses this stack, we need a nicer way of selecting build options for tests and apps. - set(NETWORK_CHANNEL_S4NOC ON) # TODO: This is currently needed because one of the tests uses this stack, we need a nicer way of selecting build options for tests and apps. set(FEDERATED ON) set(CMAKE_BUILD_TYPE "Debug") find_program(CLANG_TIDY clang-tidy) @@ -69,14 +65,7 @@ elseif (PLATFORM STREQUAL "PICO") target_link_libraries(reactor-uc PUBLIC pico_stdlib pico_sync) elseif (PLATFORM STREQUAL "PATMOS") - find_program(CLANG_EXECUTABLE NAMES patmos-clang REQUIRED DOC \"Path to the clang" + " front-end.\") - set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE}) - set(CMAKE_C_COMPILER_ID ${CLANG_EXECUTABLE}) - message("Using compiler: ${CMAKE_C_COMPILER}") - set(CMAKE_C_FLAGS_RELEASE \"-O2 -DNDEBUG\") - # target_compile_options(reactor-uc PRIVATE -Wno-zero-length-bounds) - file(GLOB PATMOS_SOURCES "src/platform/patmos/*.c") - add_library(reactor-uc PRIVATE ${PATMOS_SOURCES}) + add_library(reactor-uc STATIC ${SOURCES}) else () message(FATAL_ERROR "No valid platform specified") endif () @@ -98,26 +87,6 @@ if(NETWORK_CHANNEL_TCP_POSIX) target_compile_definitions(reactor-uc PRIVATE NETWORK_CHANNEL_TCP_POSIX) endif() -if(NETWORK_CHANNEL_S4NOC) - find_program(CLANG_EXECUTABLE NAMES patmos-clang REQUIRED DOC \"Path to the clang" + " front-end.\") - # set(CMAKE_C_COMPILER ${CLANG_EXECUTABLE}) - set(CMAKE_C_COMPILER_ID ${CLANG_EXECUTABLE}) - # message("Using compiler: ${CMAKE_C_COMPILER}") - set(CMAKE_C_FLAGS_RELEASE \"-O2 -DNDEBUG\") - - # target_compile_definitions(reactor-uc PRIVATE NETWORK_CHANNEL_S4NOC) - # target_include_directories(reactor-uc PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/reactor-uc/platform/patmos) - # file(GLOB PATMOS_SOURCES "src/platform/patmos/*.c") - # list(APPEND SOURCES ${PATMOS_SOURCES}) - # message("Sources: ${SOURCES}") - # target_link_libraries(reactor-uc PRIVATE ${SOURCES}) - - target_compile_definitions(reactor-uc PRIVATE NETWORK_CHANNEL_S4NOC) - # target_include_directories(reactor-uc PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/reactor-uc/platform/patmos) - file(GLOB S4NOC_SOURCES "src/platform/patmos/*.c") - target_sources(reactor-uc PRIVATE ${S4NOC_SOURCES}) -endif() - if(FEDERATED) target_compile_definitions(reactor-uc PUBLIC FEDERATED) endif() diff --git a/include/reactor-uc/platform/patmos/s4noc_channel.h b/include/reactor-uc/platform/patmos/s4noc_channel.h index 2963d13aa..686d5061d 100644 --- a/include/reactor-uc/platform/patmos/s4noc_channel.h +++ b/include/reactor-uc/platform/patmos/s4noc_channel.h @@ -18,10 +18,10 @@ struct S4NOCGlobalState { S4NOCPollChannel *core_channels[S4NOC_CORE_COUNT][S4NOC_CORE_COUNT]; }; -S4NOCGlobalState s4noc_global_state; +extern S4NOCGlobalState s4noc_global_state; struct S4NOCPollChannel { - NetworkChannel super; + PolledNetworkChannel super; NetworkChannelState state; FederateMessage output; @@ -34,6 +34,6 @@ struct S4NOCPollChannel { void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *message); }; -extern void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned int destination_core); +void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned int destination_core); #endif diff --git a/make/patmos/patmos-lfc.mk b/make/patmos/patmos-lfc.mk new file mode 100644 index 000000000..00a352ed0 --- /dev/null +++ b/make/patmos/patmos-lfc.mk @@ -0,0 +1,52 @@ +PATMOS_MK_DIR := $(dir $(lastword $(MAKEFILE_LIST))) + +# Check if required environment variables exist +ifndef LF_MAIN + $(error LF_MAIN is not defined. Please define it!) +endif + +# ifndef RIOTBASE +# $(error RIOTBASE is not defined. Please define it!) +# endif + +# Check if this is a federated program +ifdef LF_FED + # Name of your application + APPLICATION ?= $(LF_MAIN)-$(LF_FED) + + # Path of generated lf c-code + LF_SRC_GEN_PATH ?= $(CURDIR)/src-gen/$(LF_MAIN)/$(LF_FED) +else + # Name of your application + APPLICATION ?= $(LF_MAIN) + + # Path of generated lf c-code + LF_SRC_GEN_PATH ?= $(CURDIR)/src-gen/$(LF_MAIN) +endif + +# Only include generated files if build target is not "clean" +# In this case the src-gen folder was deleted +ifeq ($(firstword $(MAKECMDGOALS)),clean) + # Delete src-gen folder if build target is "clean" + _ := $(shell rm -rf $(LF_SRC_GEN_PATH)) + +# include $(RIOTBASE)/Makefile.include +else + # Include the Makefile of the generated target application + include $(LF_SRC_GEN_PATH)/Makefile + + # Include generated c files + SRC += $(patsubst %, $(LF_SRC_GEN_PATH)/%, $(LFC_GEN_SOURCES)) + + # Include generated main file + SRC += $(LF_SRC_GEN_PATH)/${LFC_GEN_MAIN} + + # Include generated h files + CFLAGS += -I$(LF_SRC_GEN_PATH) + + # Add compile definitions produced by the LF compiler + CFLAGS += $(patsubst %, -D%, $(LFC_GEN_COMPILE_DEFS)) + + include $(PATMOS_MK_DIR)/patmos.mk +endif + diff --git a/make/patmos/patmos.mk b/make/patmos/patmos.mk new file mode 100644 index 000000000..24c70b204 --- /dev/null +++ b/make/patmos/patmos.mk @@ -0,0 +1,28 @@ + +# This Makefile is used to build the Patmos platform for the Reactor-UC project. +# It includes the necessary paths, sources, and compiler flags for the Patmos architecture. + +# Includes +CFLAGS += -I$(REACTOR_UC_PATH)/ +CFLAGS += -I$(REACTOR_UC_PATH)/include +CFLAGS += -I$(REACTOR_UC_PATH)/include/reactor-uc +CFLAGS += -I$(REACTOR_UC_PATH)/include/reactor-uc/platform +CFLAGS += -I$(REACTOR_UC_PATH)/include/reactor-uc/platform/patmos +CFLAGS += -I$(REACTOR_UC_PATH)/external + +CFLAGS += -I$(REACTOR_UC_PATH)/external/nanopb +CFLAGS += -I$(REACTOR_UC_PATH)/external/nanopb/pb + +CFLAGS += -I$(REACTOR_UC_PATH)/external/proto + + +CFLAGS += -I$(REACTOR_UC_PATH)/external/Unity/src +CFLAGS += -I$(REACTOR_UC_PATH)/test/unit + +UNITY_DIR = $(REACTOR_UC_PATH)/external/Unity +SOURCES += $(UNITY_DIR)/src/unity.c + +SOURCES += $(wildcard $(REACTOR_UC_PATH)/src/*.c) + +SOURCES += $(wildcard $(REACTOR_UC_PATH)/external/nanopb/*.c) +SOURCES += $(REACTOR_UC_PATH)/external/proto/message.pb.c diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 967c29a20..1fcc572db 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -1,14 +1,15 @@ -#include "reactor-uc/platform/patmos/s4noc_channel.h" #include "reactor-uc/logging.h" #include "reactor-uc/serialization.h" -#include "machine/patmos.h" -#include +#include +#include #define S4NOC_CHANNEL_ERR(fmt, ...) LF_ERR(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) #define S4NOC_CHANNEL_WARN(fmt, ...) LF_WARN(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) #define S4NOC_CHANNEL_INFO(fmt, ...) LF_INFO(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) #define S4NOC_CHANNEL_DEBUG(fmt, ...) LF_DEBUG(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) +S4NOCGlobalState s4noc_global_state; + static lf_ret_t S4NOCPollChannel_open_connection(NetworkChannel *untyped_self) { S4NOC_CHANNEL_DEBUG("Open connection"); (void)untyped_self; @@ -38,16 +39,16 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); if (self->state == NETWORK_CHANNEL_STATE_CONNECTED) { - int message_size = serialize_message(message, self->write_buffer, S4NOC_CHANNEL_BUFFERSIZE); - S4NOC_CHANNEL_DEBUG("Sending Message of Size: %i", message_size); - + int message_size = serialize_to_protobuf(message, self->write_buffer, S4NOC_CHANNEL_BUFFERSIZE); + *s4noc_dest = self->destination_core; + S4NOC_CHANNEL_DEBUG("Sending Message of Size: %i to %i", message_size, *s4noc_dest); int bytes_send = 0; while (bytes_send < message_size) { *s4noc_data = ((int *)self->write_buffer)[bytes_send / 4]; bytes_send += 4; } - + S4NOC_CHANNEL_DEBUG("Sent %d bytes", bytes_send); return LF_OK; } else { return LF_ERR; @@ -65,33 +66,41 @@ static void S4NOCPollChannel_register_receive_callback(NetworkChannel *untyped_s self->federated_connection = conn; } +uint32_t ntohl(uint32_t netlong) { + return ((netlong & 0xFF000000) >> 24) | + ((netlong & 0x00FF0000) >> 8) | + ((netlong & 0x0000FF00) << 8) | + ((netlong & 0x000000FF) << 24); +} + void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; + LF_INFO(NET, "S4NOCPollChannel_poll called"); volatile _IODEV int *s4noc_status = (volatile _IODEV int *)PATMOS_IO_S4NOC; volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_source = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); if (((*s4noc_status) & 0x02) == 0) { + LF_INFO(NET, "S4NOCPollChannel_poll: No data available"); return; } int value = *s4noc_data; int source = *s4noc_source; - + LF_INFO(NET, "S4NOCPollChannel_poll: Received value %d from source %d", value, source); S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[get_cpuid()][source]; ((int *)receive_channel->receive_buffer)[receive_channel->receive_buffer_index / 4] = value; receive_channel->receive_buffer_index += 4; - int expected_message_size = ntohl(*((int *)receive_channel->receive_buffer)); + unsigned int expected_message_size = ntohl(*((int *)receive_channel->receive_buffer)); if (expected_message_size + 4 > receive_channel->receive_buffer_index) { int bytes_left = deserialize_from_protobuf(&receive_channel->output, receive_channel->receive_buffer + 1, self->receive_buffer_index - 4); S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize %d", bytes_left); if (bytes_left >= 0) { - int receive_buffer_index = receive_channel->receive_buffer_index; receive_channel->receive_buffer_index = bytes_left; if (receive_channel->receive_callback != NULL) { @@ -106,7 +115,7 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned in assert(self != NULL); assert(env != NULL); - self->super.super.mode = NETWORK_CHANNEL_MODE_POLL; + self->super.super.mode = NETWORK_CHANNEL_MODE_POLLED; self->super.super.expected_connect_duration = SEC(0); self->super.super.type = NETWORK_CHANNEL_TYPE_S4NOC; self->super.super.is_connected = S4NOCPollChannel_is_connected; diff --git a/test/platform/patmos/Makefile b/test/platform/patmos/hello/Makefile similarity index 100% rename from test/platform/patmos/Makefile rename to test/platform/patmos/hello/Makefile diff --git a/test/platform/patmos/hello.c b/test/platform/patmos/hello/hello.c similarity index 100% rename from test/platform/patmos/hello.c rename to test/platform/patmos/hello/hello.c diff --git a/test/platform/patmos/hello/run.sh b/test/platform/patmos/hello/run.sh new file mode 100755 index 000000000..443f36ec7 --- /dev/null +++ b/test/platform/patmos/hello/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# Make test +rm -r build +make all +pasim ./build/*.elf diff --git a/test/platform/patmos/runAll.sh b/test/platform/patmos/runAll.sh index 443f36ec7..0c8050bca 100755 --- a/test/platform/patmos/runAll.sh +++ b/test/platform/patmos/runAll.sh @@ -1,6 +1,13 @@ #!/bin/bash -# Make test -rm -r build -make all -pasim ./build/*.elf +set -e + +# Iterate over each folder and execute the command +for dir in ./*; do + if [ -d $dir ]; then + echo "Entering $dir" + pushd $dir + ./run.sh + popd + fi +done diff --git a/test/platform/patmos/s4noc_channel_test/Makefile b/test/platform/patmos/s4noc_channel_test/Makefile new file mode 100644 index 000000000..36c229d30 --- /dev/null +++ b/test/platform/patmos/s4noc_channel_test/Makefile @@ -0,0 +1,32 @@ +# Makefile for building a simple Hello World program for the Patmos platform +APP = main +# Compiler and tools for PATMOS +CC = patmos-clang + +include $(CURDIR)/../../../../make/patmos/patmos.mk +# Paths +SRC_DIR = $(CURDIR) +BUILD_DIR = $(CURDIR)/build + +# Source files +SOURCES += $(SRC_DIR)/$(APP).c + +CFLAGS += -O2 +CFLAGS += -DPLATFORM_PATMOS +CFLAGS += -DNETWORK_CHANNEL_S4NOC +CFLAGS += -DSCHEDULER_DYNAMIC +CFLAGS += -DFEDERATED + +# Output binary +OUTPUT = $(BUILD_DIR)/$(APP).elf +all : $(OUTPUT) + +# Build rule +$(OUTPUT): $(SOURCES) + mkdir -p $(BUILD_DIR) + $(CC) $(CFLAGS) $(SOURCES) -o $(OUTPUT) + +clean: + rm -rf $(BUILD_DIR) + +.PHONY: all clean diff --git a/test/unit/s4noc_channel_test.c b/test/platform/patmos/s4noc_channel_test/main.c similarity index 86% rename from test/unit/s4noc_channel_test.c rename to test/platform/patmos/s4noc_channel_test/main.c index 212287b6e..82283981a 100644 --- a/test/unit/s4noc_channel_test.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -1,14 +1,14 @@ -#include "reactor-uc/platform/patmos/s4noc_channel.h" #include "reactor-uc/reactor-uc.h" #include "reactor-uc/environments/federated_environment.h" #include "unity.h" #include "test_util.h" #include +#include #define MESSAGE_CONTENT "Hello S4NOC" #define MESSAGE_CONNECTION_ID 42 -#define DESTINATION_CORE 1 -#define SOURCE_CORE 0 +#define SOURCE_CORE 1 +#define DESTINATION_CORE 2 Reactor parent; FederatedEnvironment fed_env; @@ -16,6 +16,7 @@ Environment *_lf_environment = &fed_env.super; FederatedConnectionBundle sender_bundle; FederatedConnectionBundle receiver_bundle; FederatedConnectionBundle *net_bundles[] = {&sender_bundle, &receiver_bundle}; +StartupCoordinator startup_coordinator; S4NOCPollChannel sender_channel; S4NOCPollChannel receiver_channel; @@ -25,7 +26,7 @@ NetworkChannel *receiver = (NetworkChannel *)&receiver_channel.super; bool receiver_callback_called = false; void setUp(void) { - FederatedEnvironment_ctor(&fed_env, &parent, NULL, false, net_bundles, 2, NULL, NULL); + FederatedEnvironment_ctor(&fed_env, &parent, NULL, false, net_bundles, 2, &startup_coordinator, NULL); S4NOCPollChannel_ctor(&sender_channel, &fed_env.super, DESTINATION_CORE); S4NOCPollChannel_ctor(&receiver_channel, &fed_env.super, SOURCE_CORE); @@ -50,6 +51,7 @@ void test_open_connection(void) { } void receiver_callback_handler(FederatedConnectionBundle *self, const FederateMessage *_msg) { + LF_INFO(NET, "Receiver callback handler called"); (void)self; const TaggedMessage *msg = &_msg->message.tagged_message; printf("\nReceiver: Received message with connection number %i and content %s\n", msg->conn_id, @@ -74,17 +76,18 @@ void test_sender_send_and_receiver_recv(void) { const char *message = MESSAGE_CONTENT; memcpy(port_message->payload.bytes, message, sizeof(MESSAGE_CONTENT)); // NOLINT port_message->payload.size = sizeof(MESSAGE_CONTENT); - + LF_INFO(NET, "Sender: Sending message with connection number %i and content %s\n", port_message->conn_id, + (char *)port_message->payload.bytes); TEST_ASSERT_OK(sender->send_blocking(sender, &msg)); - + LF_INFO(NET, "Sender: Message sent\n"); ((PolledNetworkChannel *)&receiver_channel.super)->poll((PolledNetworkChannel *)&receiver_channel.super); - + LF_INFO(NET, "Receiver: Message polled\n"); TEST_ASSERT_TRUE(receiver_callback_called); } int main(void) { UNITY_BEGIN(); - RUN_TEST(test_open_connection); + //RUN_TEST(test_open_connection); RUN_TEST(test_sender_send_and_receiver_recv); return UNITY_END(); } \ No newline at end of file diff --git a/test/platform/patmos/s4noc_channel_test/run.sh b/test/platform/patmos/s4noc_channel_test/run.sh new file mode 100755 index 000000000..876570ec8 --- /dev/null +++ b/test/platform/patmos/s4noc_channel_test/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Make test +make clean +make all +patemu ./build/*.elf + From 0e3c7238b4deee5ab23bcca725f5f9b92f555ace Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 27 May 2025 16:27:28 +0200 Subject: [PATCH 04/28] Patmos and s4noc: 4th Commit: s4noc_channel passed the test --- .../platform/patmos/s4noc_channel.h | 3 +- src/platform/patmos/s4noc_channel.c | 54 ++++---- .../platform/patmos/s4noc_channel_test/main.c | 47 +++---- test/platform/patmos/s4noc_test/Makefile | 32 +++++ test/platform/patmos/s4noc_test/main.c | 119 ++++++++++++++++++ test/platform/patmos/s4noc_test/run.sh | 7 ++ 6 files changed, 213 insertions(+), 49 deletions(-) create mode 100644 test/platform/patmos/s4noc_test/Makefile create mode 100644 test/platform/patmos/s4noc_test/main.c create mode 100755 test/platform/patmos/s4noc_test/run.sh diff --git a/include/reactor-uc/platform/patmos/s4noc_channel.h b/include/reactor-uc/platform/patmos/s4noc_channel.h index 686d5061d..423e34cd7 100644 --- a/include/reactor-uc/platform/patmos/s4noc_channel.h +++ b/include/reactor-uc/platform/patmos/s4noc_channel.h @@ -3,7 +3,7 @@ #include "reactor-uc/network_channel.h" #include "reactor-uc/environment.h" - +#include typedef struct FederatedConnectionBundle FederatedConnectionBundle; typedef struct S4NOCPollChannel S4NOCPollChannel; typedef struct S4NOCGlobalState S4NOCGlobalState; @@ -32,6 +32,7 @@ struct S4NOCPollChannel { FederatedConnectionBundle *federated_connection; void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *message); + pthread_t worker_thread; }; void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned int destination_core); diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 1fcc572db..28799f182 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -39,12 +39,13 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); if (self->state == NETWORK_CHANNEL_STATE_CONNECTED) { - int message_size = serialize_to_protobuf(message, self->write_buffer, S4NOC_CHANNEL_BUFFERSIZE); + int message_size = serialize_to_protobuf(message, self->write_buffer + 4, S4NOC_CHANNEL_BUFFERSIZE - 4); - *s4noc_dest = self->destination_core; - S4NOC_CHANNEL_DEBUG("Sending Message of Size: %i to %i", message_size, *s4noc_dest); + *((int *)self->write_buffer) = message_size; + + int total_size = message_size + 4; int bytes_send = 0; - while (bytes_send < message_size) { + while (bytes_send < total_size) { *s4noc_data = ((int *)self->write_buffer)[bytes_send / 4]; bytes_send += 4; } @@ -59,20 +60,13 @@ static void S4NOCPollChannel_register_receive_callback(NetworkChannel *untyped_s void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *msg), FederatedConnectionBundle *conn) { - S4NOC_CHANNEL_INFO("Register receive callback"); + S4NOC_CHANNEL_INFO("Register receive callback at %p", receive_callback); S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; self->receive_callback = receive_callback; self->federated_connection = conn; } -uint32_t ntohl(uint32_t netlong) { - return ((netlong & 0xFF000000) >> 24) | - ((netlong & 0x00FF0000) >> 8) | - ((netlong & 0x0000FF00) << 8) | - ((netlong & 0x000000FF) << 24); -} - void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; LF_INFO(NET, "S4NOCPollChannel_poll called"); @@ -88,25 +82,31 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { int value = *s4noc_data; int source = *s4noc_source; - LF_INFO(NET, "S4NOCPollChannel_poll: Received value %d from source %d", value, source); - S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[get_cpuid()][source]; + LF_INFO(NET, "S4NOCPollChannel_poll: Received value 0x%08x (%c%c%c%c) from source %d", value, + ((char *)&value)[0], ((char *)&value)[1], ((char *)&value)[2], ((char *)&value)[3], source); + S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[source][get_cpuid()]; // Get the receive channel for the source core ((int *)receive_channel->receive_buffer)[receive_channel->receive_buffer_index / 4] = value; receive_channel->receive_buffer_index += 4; - - unsigned int expected_message_size = ntohl(*((int *)receive_channel->receive_buffer)); - if (expected_message_size + 4 > receive_channel->receive_buffer_index) { - int bytes_left = deserialize_from_protobuf(&receive_channel->output, receive_channel->receive_buffer + 1, - self->receive_buffer_index - 4); - S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize %d", bytes_left); + S4NOC_CHANNEL_DEBUG("receive_buffer_index %d", receive_channel->receive_buffer_index); + unsigned int expected_message_size = *((int *)receive_channel->receive_buffer); + S4NOC_CHANNEL_DEBUG("Expected message size: %d", expected_message_size); + if (receive_channel->receive_buffer_index >= expected_message_size + 4) { + int bytes_left = deserialize_from_protobuf( + &receive_channel->output, + receive_channel->receive_buffer + 4, // skip the 4-byte size header + expected_message_size // only the message payload + ); + S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize: %d", bytes_left); if (bytes_left >= 0) { - receive_channel->receive_buffer_index = bytes_left; - - if (receive_channel->receive_callback != NULL) { - S4NOC_CHANNEL_DEBUG("calling user callback!"); - receive_channel->receive_callback(self->federated_connection, &self->output); - } + receive_channel->receive_buffer_index = bytes_left; + if (receive_channel->receive_callback != NULL) { + S4NOC_CHANNEL_DEBUG("calling user callback at %p!", receive_channel->receive_callback); + receive_channel->receive_callback(self->federated_connection, &receive_channel->output); + } else { + S4NOC_CHANNEL_WARN("No receive callback registered, dropping message"); + } } } } @@ -131,5 +131,5 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned in self->receive_callback = NULL; self->federated_connection = NULL; self->state = NETWORK_CHANNEL_STATE_CONNECTED; - self->destination_core = destination_core; + self->destination_core = destination_core; } diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index 82283981a..81d129598 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -3,12 +3,11 @@ #include "unity.h" #include "test_util.h" #include -#include #define MESSAGE_CONTENT "Hello S4NOC" #define MESSAGE_CONNECTION_ID 42 #define SOURCE_CORE 1 -#define DESTINATION_CORE 2 +#define DESTINATION_CORE 0 Reactor parent; FederatedEnvironment fed_env; @@ -35,6 +34,7 @@ void setUp(void) { FederatedConnectionBundle_ctor(&receiver_bundle, &parent, receiver, NULL, NULL, 0, NULL, NULL, 0, 0); s4noc_global_state.core_channels[SOURCE_CORE][DESTINATION_CORE] = &receiver_channel; + } void tearDown(void) { @@ -42,19 +42,11 @@ void tearDown(void) { receiver->free(receiver); } -void test_open_connection(void) { - TEST_ASSERT_OK(sender->open_connection(sender)); - TEST_ASSERT_OK(receiver->open_connection(receiver)); - - TEST_ASSERT_TRUE(sender->is_connected(sender)); - TEST_ASSERT_TRUE(receiver->is_connected(receiver)); -} - void receiver_callback_handler(FederatedConnectionBundle *self, const FederateMessage *_msg) { LF_INFO(NET, "Receiver callback handler called"); (void)self; const TaggedMessage *msg = &_msg->message.tagged_message; - printf("\nReceiver: Received message with connection number %i and content %s\n", msg->conn_id, + LF_INFO(NET,"Receiver: Received message with connection number %i and content %s\n", msg->conn_id, (char *)msg->payload.bytes); TEST_ASSERT_EQUAL_STRING(MESSAGE_CONTENT, (char *)msg->payload.bytes); TEST_ASSERT_EQUAL(MESSAGE_CONNECTION_ID, msg->conn_id); @@ -62,12 +54,7 @@ void receiver_callback_handler(FederatedConnectionBundle *self, const FederateMe receiver_callback_called = true; } -void test_sender_send_and_receiver_recv(void) { - TEST_ASSERT_OK(sender->open_connection(sender)); - TEST_ASSERT_OK(receiver->open_connection(receiver)); - - receiver->register_receive_callback(receiver, receiver_callback_handler, NULL); - +void send_message(void) { FederateMessage msg; msg.which_message = FederateMessage_tagged_message_tag; @@ -79,15 +66,33 @@ void test_sender_send_and_receiver_recv(void) { LF_INFO(NET, "Sender: Sending message with connection number %i and content %s\n", port_message->conn_id, (char *)port_message->payload.bytes); TEST_ASSERT_OK(sender->send_blocking(sender, &msg)); - LF_INFO(NET, "Sender: Message sent\n"); - ((PolledNetworkChannel *)&receiver_channel.super)->poll((PolledNetworkChannel *)&receiver_channel.super); - LF_INFO(NET, "Receiver: Message polled\n"); +} + +void test_sender_send_and_receiver_recv(void) { + TEST_ASSERT_OK(sender->open_connection(sender)); + TEST_ASSERT_OK(receiver->open_connection(receiver)); + + receiver->register_receive_callback(receiver, receiver_callback_handler, NULL); + + if(pthread_create(&sender_channel.worker_thread, NULL, send_message, NULL)) { + LF_INFO(NET,"Error creating thread\n"); + return; + } + if (pthread_join(sender_channel.worker_thread, NULL)) { + LF_INFO(NET,"Error joining thread\n"); + return; + } + + do { + LF_INFO(NET, "Receiver: Waiting for callback to be called\n"); + ((PolledNetworkChannel *)&receiver_channel.super)->poll((PolledNetworkChannel *)&receiver_channel.super); + } while(!receiver_callback_called); + TEST_ASSERT_TRUE(receiver_callback_called); } int main(void) { UNITY_BEGIN(); - //RUN_TEST(test_open_connection); RUN_TEST(test_sender_send_and_receiver_recv); return UNITY_END(); } \ No newline at end of file diff --git a/test/platform/patmos/s4noc_test/Makefile b/test/platform/patmos/s4noc_test/Makefile new file mode 100644 index 000000000..36c229d30 --- /dev/null +++ b/test/platform/patmos/s4noc_test/Makefile @@ -0,0 +1,32 @@ +# Makefile for building a simple Hello World program for the Patmos platform +APP = main +# Compiler and tools for PATMOS +CC = patmos-clang + +include $(CURDIR)/../../../../make/patmos/patmos.mk +# Paths +SRC_DIR = $(CURDIR) +BUILD_DIR = $(CURDIR)/build + +# Source files +SOURCES += $(SRC_DIR)/$(APP).c + +CFLAGS += -O2 +CFLAGS += -DPLATFORM_PATMOS +CFLAGS += -DNETWORK_CHANNEL_S4NOC +CFLAGS += -DSCHEDULER_DYNAMIC +CFLAGS += -DFEDERATED + +# Output binary +OUTPUT = $(BUILD_DIR)/$(APP).elf +all : $(OUTPUT) + +# Build rule +$(OUTPUT): $(SOURCES) + mkdir -p $(BUILD_DIR) + $(CC) $(CFLAGS) $(SOURCES) -o $(OUTPUT) + +clean: + rm -rf $(BUILD_DIR) + +.PHONY: all clean diff --git a/test/platform/patmos/s4noc_test/main.c b/test/platform/patmos/s4noc_test/main.c new file mode 100644 index 000000000..155a09cfa --- /dev/null +++ b/test/platform/patmos/s4noc_test/main.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include + +typedef int64_t instant_t; +typedef int64_t interval_t; + +int _lf_clock_gettime(instant_t* t) { + if (t != NULL) { + *t = get_cpu_usecs() * 1000; + } + + return 0; +} + +int lf_sleep(interval_t sleep_duration) { + instant_t now; + _lf_clock_gettime(&now); + instant_t wakeup = now + sleep_duration; + + // Do busy sleep + do { + _lf_clock_gettime(&now); + } while ((now < wakeup)); + return 0; +} + +// Data structure for Source reactor +typedef struct { + int (*generate_value)(); // Function pointer to generate values + void (*sender_function)(); + int value; // The value to send + pthread_t thread; +} Source; + +// Data structure for Sink reactor +typedef struct { + void (*receiver_function)(); // Function pointer to handle received values + pthread_t thread; +} Sink; + +// Function for the Source reactor to generate a value +int generate_value() { + static int counter = 42; + return counter++; // Incremental values +} + +#define MAX_ITER 5 +void sender_function() { + volatile _IODEV int *s4noc_status = (volatile _IODEV int *) PATMOS_IO_S4NOC; + volatile _IODEV int *s4noc_data = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 4); + volatile _IODEV int *s4noc_dest = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 8); + + *s4noc_dest = 2; + for (int i = 0; i < MAX_ITER; i++) { + int status = (*s4noc_status) & 0x01; + while (status == 0) { + status = (*s4noc_status) & 0x01; + } + *s4noc_data = generate_value(); + lf_sleep(1000000); + } + +} + + +// Function for the Sink reactor to handle received values +void receiver_function() { + volatile _IODEV int *s4noc_status = (volatile _IODEV int *) PATMOS_IO_S4NOC; + volatile _IODEV int *s4noc_data = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 4); + volatile _IODEV int *s4noc_source = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 8); + + for (int i = 0; i < MAX_ITER; i++) { + int status = (*s4noc_status) & 0x02; + while (status == 0) { + status = (*s4noc_status) & 0x02; + } + int value = *s4noc_data; + int source = *s4noc_source; + printf("Received: %d from core %d\n", value, source); + } +} + +// Main function +int main() { + + // Initialize the Source reactor + Source source; + source.generate_value = generate_value; + source.sender_function = sender_function; + source.value = 0; + + // Initialize the Sink reactor + Sink sink; + sink.receiver_function = receiver_function; + + if (pthread_create(&source.thread, NULL, source.sender_function, NULL)) { + fprintf(stderr, "Error creating thread\n"); + return 1; + } + + if (pthread_create(&sink.thread, NULL, sink.receiver_function, NULL)) { + fprintf(stderr, "Error creating thread\n"); + return 1; + } + + if (pthread_join(source.thread, NULL)) { + fprintf(stderr, "Error joining thread\n"); + return 2; + } + if (pthread_join(sink.thread, NULL)) { + fprintf(stderr, "Error joining thread\n"); + return 2; + } + return 0; +} \ No newline at end of file diff --git a/test/platform/patmos/s4noc_test/run.sh b/test/platform/patmos/s4noc_test/run.sh new file mode 100755 index 000000000..876570ec8 --- /dev/null +++ b/test/platform/patmos/s4noc_test/run.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Make test +make clean +make all +patemu ./build/*.elf + From c2436f67d17502033978a84596256c8401f3e417 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 5 Jun 2025 17:57:56 +0200 Subject: [PATCH 05/28] Patmos and s4noc support --- src/platform/patmos/s4noc_channel.c | 7 ++-- .../platform/patmos/s4noc_channel_test/main.c | 35 +++++++++++++------ test/platform/patmos/s4noc_test/main.c | 5 ++- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 28799f182..4b63946db 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -44,6 +44,7 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con *((int *)self->write_buffer) = message_size; int total_size = message_size + 4; + *s4noc_dest = self->destination_core; int bytes_send = 0; while (bytes_send < total_size) { *s4noc_data = ((int *)self->write_buffer)[bytes_send / 4]; @@ -69,20 +70,20 @@ static void S4NOCPollChannel_register_receive_callback(NetworkChannel *untyped_s void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; - LF_INFO(NET, "S4NOCPollChannel_poll called"); + S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll called"); volatile _IODEV int *s4noc_status = (volatile _IODEV int *)PATMOS_IO_S4NOC; volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_source = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); if (((*s4noc_status) & 0x02) == 0) { - LF_INFO(NET, "S4NOCPollChannel_poll: No data available"); + S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: No data available"); return; } int value = *s4noc_data; int source = *s4noc_source; - LF_INFO(NET, "S4NOCPollChannel_poll: Received value 0x%08x (%c%c%c%c) from source %d", value, + S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: Received value 0x%08x (%c%c%c%c) from source %d", value, ((char *)&value)[0], ((char *)&value)[1], ((char *)&value)[2], ((char *)&value)[3], source); S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[source][get_cpuid()]; // Get the receive channel for the source core diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index 81d129598..dc1874870 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -7,7 +7,8 @@ #define MESSAGE_CONTENT "Hello S4NOC" #define MESSAGE_CONNECTION_ID 42 #define SOURCE_CORE 1 -#define DESTINATION_CORE 0 +#define DESTINATION_CORE 2 +#define MAX_TRIES 10 Reactor parent; FederatedEnvironment fed_env; @@ -34,6 +35,7 @@ void setUp(void) { FederatedConnectionBundle_ctor(&receiver_bundle, &parent, receiver, NULL, NULL, 0, NULL, NULL, 0, 0); s4noc_global_state.core_channels[SOURCE_CORE][DESTINATION_CORE] = &receiver_channel; + s4noc_global_state.core_channels[DESTINATION_CORE][SOURCE_CORE] = &sender_channel; } @@ -63,11 +65,19 @@ void send_message(void) { const char *message = MESSAGE_CONTENT; memcpy(port_message->payload.bytes, message, sizeof(MESSAGE_CONTENT)); // NOLINT port_message->payload.size = sizeof(MESSAGE_CONTENT); - LF_INFO(NET, "Sender: Sending message with connection number %i and content %s\n", port_message->conn_id, - (char *)port_message->payload.bytes); + LF_INFO(NET, "Sender: Sending message with connection number %i and content %s\n", port_message->conn_id, (char *)port_message->payload.bytes); TEST_ASSERT_OK(sender->send_blocking(sender, &msg)); } +void receive_message(void) { + int tries = 0; + do { + LF_WARN(NET, "Receiver: Polling for messages, tries: %i\n", tries); + tries++; + ((PolledNetworkChannel *)&receiver_channel.super)->poll((PolledNetworkChannel *)&receiver_channel.super); + } while (receiver_callback_called == false && tries < MAX_TRIES); +} + void test_sender_send_and_receiver_recv(void) { TEST_ASSERT_OK(sender->open_connection(sender)); TEST_ASSERT_OK(receiver->open_connection(receiver)); @@ -75,18 +85,21 @@ void test_sender_send_and_receiver_recv(void) { receiver->register_receive_callback(receiver, receiver_callback_handler, NULL); if(pthread_create(&sender_channel.worker_thread, NULL, send_message, NULL)) { - LF_INFO(NET,"Error creating thread\n"); + LF_ERR(NET,"Error creating thread\n"); + return; + } + if(pthread_create(&receiver_channel.worker_thread, NULL, receive_message, NULL)) { + LF_ERR(NET,"Error creating thread\n"); return; } if (pthread_join(sender_channel.worker_thread, NULL)) { - LF_INFO(NET,"Error joining thread\n"); + LF_ERR(NET,"Error joining thread\n"); + return; + } + if (pthread_join(receiver_channel.worker_thread, NULL)) { + LF_ERR(NET,"Error joining thread\n"); return; } - - do { - LF_INFO(NET, "Receiver: Waiting for callback to be called\n"); - ((PolledNetworkChannel *)&receiver_channel.super)->poll((PolledNetworkChannel *)&receiver_channel.super); - } while(!receiver_callback_called); TEST_ASSERT_TRUE(receiver_callback_called); } @@ -95,4 +108,4 @@ int main(void) { UNITY_BEGIN(); RUN_TEST(test_sender_send_and_receiver_recv); return UNITY_END(); -} \ No newline at end of file +} diff --git a/test/platform/patmos/s4noc_test/main.c b/test/platform/patmos/s4noc_test/main.c index 155a09cfa..3f695ae16 100644 --- a/test/platform/patmos/s4noc_test/main.c +++ b/test/platform/patmos/s4noc_test/main.c @@ -5,6 +5,9 @@ #include #include +#define SOURCE_CORE 1 +#define DESTINATION_CORE 2 + typedef int64_t instant_t; typedef int64_t interval_t; @@ -54,7 +57,7 @@ void sender_function() { volatile _IODEV int *s4noc_data = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_dest = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 8); - *s4noc_dest = 2; + *s4noc_dest = DESTINATION_CORE; for (int i = 0; i < MAX_ITER; i++) { int status = (*s4noc_status) & 0x01; while (status == 0) { From ad9a2e4a93ef2a4f078acacc2bf22468c8586328 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 10 Jun 2025 15:48:13 +0200 Subject: [PATCH 06/28] Patmos and s4noc support: 6 --- examples/patmos/hello_lf/Makefile | 13 +- include/reactor-uc/event.h | 4 +- .../platform/patmos/s4noc_channel.h | 2 +- include/reactor-uc/tag.h | 11 +- .../uc/UcFederatedProjectTemplateGenerator.kt | 11 +- make/patmos/patmos-lfc.mk | 6 - make/patmos/patmos.mk | 8 ++ src/platform/patmos/patmos.c | 9 +- src/platform/patmos/s4noc_channel.c | 32 ++--- src/platform/pico/uart_channel.c | 12 +- test/platform/patmos/hello/Makefile | 27 ---- test/platform/patmos/hello/hello.c | 5 - test/platform/patmos/hello/run.sh | 6 - .../patmos/s4noc_channel_test/Makefile | 5 +- .../platform/patmos/s4noc_channel_test/main.c | 3 +- test/platform/patmos/s4noc_test/Makefile | 32 ----- test/platform/patmos/s4noc_test/main.c | 122 ------------------ test/platform/patmos/s4noc_test/run.sh | 7 - 18 files changed, 57 insertions(+), 258 deletions(-) delete mode 100644 test/platform/patmos/hello/Makefile delete mode 100644 test/platform/patmos/hello/hello.c delete mode 100755 test/platform/patmos/hello/run.sh delete mode 100644 test/platform/patmos/s4noc_test/Makefile delete mode 100644 test/platform/patmos/s4noc_test/main.c delete mode 100755 test/platform/patmos/s4noc_test/run.sh diff --git a/examples/patmos/hello_lf/Makefile b/examples/patmos/hello_lf/Makefile index 7356bd930..7accbf178 100755 --- a/examples/patmos/hello_lf/Makefile +++ b/examples/patmos/hello_lf/Makefile @@ -11,12 +11,13 @@ endif # ---- Patmos specific configuration ---- include ./src-gen/$(LF_MAIN)/Makefile +include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk -SRC = $(REACTOR_UC_PATH)/src/*.c -SRC += $(patsubst %, $(SRC_GEN_PATH)/%, $(LFC_GEN_SOURCES) $(LFC_GEN_MAIN)) +SOURCES += $(patsubst %, $(SRC_GEN_PATH)/%, $(LFC_GEN_SOURCES) $(LFC_GEN_MAIN)) -INC = -I$(REACTOR_UC_PATH)/include -I$(REACTOR_UC_PATH)/external -I$(SRC_GEN_PATH) -FLG = -DPLATFORM_PATMOS -DSCHEDULER_DYNAMIC -DEVENT_QUEUE_SIZE=$(EVENT_QUEUE_SIZE) -DREACTION_QUEUE_SIZE=$(REACTION_QUEUE_SIZE) -O2 +CFLAGS += -DSCHEDULER_DYNAMIC +CFLAGS += -DEVENT_QUEUE_SIZE=$(EVENT_QUEUE_SIZE) +CFLAGS += -DREACTION_QUEUE_SIZE=$(REACTION_QUEUE_SIZE) # Output directory BIN_DIR = $(CURDIR)/bin @@ -25,9 +26,9 @@ OUTPUT = $(BIN_DIR)/$(LF_MAIN) all: $(OUTPUT) # Build rule -$(OUTPUT): $(SRC) +$(OUTPUT): $(SOURCES) mkdir -p $(BIN_DIR) - patmos-clang $(SRC) $(INC) $(FLG) -o $(OUTPUT) -Wno-everything + $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) clean: rm -rf $(BIN_DIR) ./src-gen diff --git a/include/reactor-uc/event.h b/include/reactor-uc/event.h index b734525e2..7437126a8 100644 --- a/include/reactor-uc/event.h +++ b/include/reactor-uc/event.h @@ -7,10 +7,10 @@ #include #define EVENT_INIT(Tag, Trigger, Payload) \ - {.super.type = EVENT, .super.tag = Tag, .intended_tag = Tag, .trigger = Trigger, .super.payload = Payload} + { .super.type = EVENT, .super.tag = Tag, .intended_tag = Tag, .trigger = Trigger, .super.payload = Payload } #define SYSTEM_EVENT_INIT(Tag, Handler, Payload) \ - {.super.type = SYSTEM_EVENT, .super.tag = Tag, .super.payload = Payload, .handler = Handler} + { .super.type = SYSTEM_EVENT, .super.tag = Tag, .super.payload = Payload, .handler = Handler } typedef struct Trigger Trigger; typedef struct SystemEventHandler SystemEventHandler; diff --git a/include/reactor-uc/platform/patmos/s4noc_channel.h b/include/reactor-uc/platform/patmos/s4noc_channel.h index 423e34cd7..f11fb225b 100644 --- a/include/reactor-uc/platform/patmos/s4noc_channel.h +++ b/include/reactor-uc/platform/patmos/s4noc_channel.h @@ -32,7 +32,7 @@ struct S4NOCPollChannel { FederatedConnectionBundle *federated_connection; void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *message); - pthread_t worker_thread; + pthread_t worker_thread; }; void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned int destination_core); diff --git a/include/reactor-uc/tag.h b/include/reactor-uc/tag.h index 3e52188b9..fb514912d 100644 --- a/include/reactor-uc/tag.h +++ b/include/reactor-uc/tag.h @@ -40,14 +40,19 @@ .time = NEVER, .microstep = NEVER_MICROSTEP \ } // Need a separate initializer expression to comply with some C compilers -#define NEVER_TAG_INITIALIZER {NEVER, NEVER_MICROSTEP} +#define NEVER_TAG_INITIALIZER \ + { NEVER, NEVER_MICROSTEP } #define FOREVER_TAG \ (tag_t) { \ .time = FOREVER, .microstep = FOREVER_MICROSTEP \ } // Need a separate initializer expression to comply with some C compilers -#define FOREVER_TAG_INITIALIZER {FOREVER, FOREVER_MICROSTEP} -#define ZERO_TAG (tag_t){.time = 0LL, .microstep = 0u} +#define FOREVER_TAG_INITIALIZER \ + { FOREVER, FOREVER_MICROSTEP } +#define ZERO_TAG \ + (tag_t) { \ + .time = 0LL, .microstep = 0u \ + } // Returns true if timeout has elapsed. #define CHECK_TIMEOUT(start, duration) (lf_time_physical() > ((start) + (duration))) diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt index b5d95b727..b323fdf57 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt @@ -135,8 +135,8 @@ class UcFederatedTemplateGenerator( private fun generateFilesPatmos() { val make = """ - |# Compiler and tools for PATMOS - |CC = patmos-clang + |LF_MAIN ?= ${mainDef.name} + |LF_FED ?= ${federate.name} | |# Paths |SRC_DIR = src-gen/${mainDef.name}/${federate.name} @@ -145,9 +145,6 @@ class UcFederatedTemplateGenerator( |# Source files |SOURCES = $S(SRC_DIR)/*.c | - |# Compiler flags - |CFLAGS = -O2 -Wall -Wextra -Werror - | |# Output binary |OUTPUT = $S(BUILD_DIR)/${federate.name}.elf | @@ -157,10 +154,8 @@ class UcFederatedTemplateGenerator( | mkdir -p $S(BUILD_DIR) | $S(CC) $S(CFLAGS) $S(SOURCES) -o $S(OUTPUT) | - |clean: - | rm -rf $S(BUILD_DIR) - | |.PHONY: all clean + |include $S(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk """ .trimMargin() FileUtil.writeToFile(make, projectRoot.resolve("Makefile")) diff --git a/make/patmos/patmos-lfc.mk b/make/patmos/patmos-lfc.mk index 00a352ed0..29fa902b5 100644 --- a/make/patmos/patmos-lfc.mk +++ b/make/patmos/patmos-lfc.mk @@ -5,10 +5,6 @@ ifndef LF_MAIN $(error LF_MAIN is not defined. Please define it!) endif -# ifndef RIOTBASE -# $(error RIOTBASE is not defined. Please define it!) -# endif - # Check if this is a federated program ifdef LF_FED # Name of your application @@ -29,8 +25,6 @@ endif ifeq ($(firstword $(MAKECMDGOALS)),clean) # Delete src-gen folder if build target is "clean" _ := $(shell rm -rf $(LF_SRC_GEN_PATH)) - -# include $(RIOTBASE)/Makefile.include else # Include the Makefile of the generated target application include $(LF_SRC_GEN_PATH)/Makefile diff --git a/make/patmos/patmos.mk b/make/patmos/patmos.mk index 24c70b204..b4530dcb9 100644 --- a/make/patmos/patmos.mk +++ b/make/patmos/patmos.mk @@ -2,6 +2,9 @@ # This Makefile is used to build the Patmos platform for the Reactor-UC project. # It includes the necessary paths, sources, and compiler flags for the Patmos architecture. +# Compiler and tools for PATMOS +CC = patmos-clang + # Includes CFLAGS += -I$(REACTOR_UC_PATH)/ CFLAGS += -I$(REACTOR_UC_PATH)/include @@ -26,3 +29,8 @@ SOURCES += $(wildcard $(REACTOR_UC_PATH)/src/*.c) SOURCES += $(wildcard $(REACTOR_UC_PATH)/external/nanopb/*.c) SOURCES += $(REACTOR_UC_PATH)/external/proto/message.pb.c + +CFLAGS += -O2 +CFLAGS += -Wall -Wextra +CFLAGS += -DPLATFORM_PATMOS + \ No newline at end of file diff --git a/src/platform/patmos/patmos.c b/src/platform/patmos/patmos.c index 7fbe7ac27..523c3e2f6 100644 --- a/src/platform/patmos/patmos.c +++ b/src/platform/patmos/patmos.c @@ -21,7 +21,6 @@ instant_t PlatformPatmos_get_physical_time(Platform *super) { lf_ret_t PlatformPatmos_wait_until_interruptible(Platform *super, instant_t wakeup_time) { PlatformPatmos *self = (PlatformPatmos *)super; self->async_event = false; - //super->leave_critical_section(super); // turing on interrupts instant_t now = super->get_physical_time(super); @@ -30,8 +29,6 @@ lf_ret_t PlatformPatmos_wait_until_interruptible(Platform *super, instant_t wake now = super->get_physical_time(super); } while ((now < wakeup_time) && !self->async_event); - //super->enter_critical_section(super); - if (self->async_event) { self->async_event = false; return LF_ERR; @@ -44,8 +41,6 @@ lf_ret_t PlatformPatmos_wait_until_interruptible(Platform *super, instant_t wake return LF_OK; } - //super->leave_critical_section(super); - return LF_OK; } @@ -131,5 +126,5 @@ void Mutex_ctor(Mutex *super) { MutexPatmos *self = (MutexPatmos *)super; super->lock = MutexPatmos_lock; super->unlock = MutexPatmos_unlock; - //critical_section_init(&self->crit_sec); -} \ No newline at end of file + // critical_section_init(&self->crit_sec); +} diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 4b63946db..c59a492ad 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -40,7 +40,7 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con if (self->state == NETWORK_CHANNEL_STATE_CONNECTED) { int message_size = serialize_to_protobuf(message, self->write_buffer + 4, S4NOC_CHANNEL_BUFFERSIZE - 4); - + *((int *)self->write_buffer) = message_size; int total_size = message_size + 4; @@ -83,9 +83,10 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { int value = *s4noc_data; int source = *s4noc_source; - S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: Received value 0x%08x (%c%c%c%c) from source %d", value, - ((char *)&value)[0], ((char *)&value)[1], ((char *)&value)[2], ((char *)&value)[3], source); - S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[source][get_cpuid()]; // Get the receive channel for the source core + S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: Received value 0x%08x (%c%c%c%c) from source %d", value, + ((char *)&value)[0], ((char *)&value)[1], ((char *)&value)[2], ((char *)&value)[3], source); + S4NOCPollChannel *receive_channel = + s4noc_global_state.core_channels[source][get_cpuid()]; // Get the receive channel for the source core ((int *)receive_channel->receive_buffer)[receive_channel->receive_buffer_index / 4] = value; receive_channel->receive_buffer_index += 4; @@ -93,21 +94,20 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { unsigned int expected_message_size = *((int *)receive_channel->receive_buffer); S4NOC_CHANNEL_DEBUG("Expected message size: %d", expected_message_size); if (receive_channel->receive_buffer_index >= expected_message_size + 4) { - int bytes_left = deserialize_from_protobuf( - &receive_channel->output, - receive_channel->receive_buffer + 4, // skip the 4-byte size header - expected_message_size // only the message payload + int bytes_left = deserialize_from_protobuf(&receive_channel->output, + receive_channel->receive_buffer + 4, // skip the 4-byte size header + expected_message_size // only the message payload ); S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize: %d", bytes_left); if (bytes_left >= 0) { - receive_channel->receive_buffer_index = bytes_left; - if (receive_channel->receive_callback != NULL) { - S4NOC_CHANNEL_DEBUG("calling user callback at %p!", receive_channel->receive_callback); - receive_channel->receive_callback(self->federated_connection, &receive_channel->output); - } else { - S4NOC_CHANNEL_WARN("No receive callback registered, dropping message"); - } + receive_channel->receive_buffer_index = bytes_left; + if (receive_channel->receive_callback != NULL) { + S4NOC_CHANNEL_DEBUG("calling user callback at %p!", receive_channel->receive_callback); + receive_channel->receive_callback(self->federated_connection, &receive_channel->output); + } else { + S4NOC_CHANNEL_WARN("No receive callback registered, dropping message"); + } } } } @@ -132,5 +132,5 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned in self->receive_callback = NULL; self->federated_connection = NULL; self->state = NETWORK_CHANNEL_STATE_CONNECTED; - self->destination_core = destination_core; + self->destination_core = destination_core; } diff --git a/src/platform/pico/uart_channel.c b/src/platform/pico/uart_channel.c index f0a77b88c..ab865742c 100644 --- a/src/platform/pico/uart_channel.c +++ b/src/platform/pico/uart_channel.c @@ -9,10 +9,14 @@ #define UART_CHANNEL_INFO(fmt, ...) LF_INFO(NET, "UartPolledChannel: " fmt, ##__VA_ARGS__) #define UART_CHANNEL_DEBUG(fmt, ...) LF_DEBUG(NET, "UartPolledChannel: " fmt, ##__VA_ARGS__) -#define UART_OPEN_MESSAGE_REQUEST {0xC0, 0x18, 0x11, 0xC0, 0xDD} -#define UART_OPEN_MESSAGE_RESPONSE {0xC0, 0xFF, 0x31, 0xC0, 0xDD} -#define UART_MESSAGE_PREFIX {0xAA, 0xAA, 0xAA, 0xAA, 0xAA} -#define UART_MESSAGE_POSTFIX {0xBB, 0xBB, 0xBB, 0xBB, 0xBD} +#define UART_OPEN_MESSAGE_REQUEST \ + { 0xC0, 0x18, 0x11, 0xC0, 0xDD } +#define UART_OPEN_MESSAGE_RESPONSE \ + { 0xC0, 0xFF, 0x31, 0xC0, 0xDD } +#define UART_MESSAGE_PREFIX \ + { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA } +#define UART_MESSAGE_POSTFIX \ + { 0xBB, 0xBB, 0xBB, 0xBB, 0xBD } #define UART_CLOSE_MESSAGE {0x2, 0xF, 0x6, 0xC, 0x2}; #define MINIMUM_MESSAGE_SIZE 10 #define UART_CHANNEL_EXPECTED_CONNECT_DURATION MSEC(2500) diff --git a/test/platform/patmos/hello/Makefile b/test/platform/patmos/hello/Makefile deleted file mode 100644 index 947fb3485..000000000 --- a/test/platform/patmos/hello/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# Makefile for building a simple Hello World program for the Patmos platform - -# Compiler and tools for PATMOS -CC = patmos-clang - -# Paths -SRC_DIR = $(CURDIR) -BUILD_DIR = $(CURDIR)/build - -# Source files -SOURCES = $(SRC_DIR)/hello.c - -# Compiler flags -CFLAGS = -O2 -Wall -Wextra -Werror - -# Output binary -OUTPUT = $(BUILD_DIR)/hello.elf -all : $(OUTPUT) -# Build rule -$(OUTPUT): $(SOURCES) - mkdir -p $(BUILD_DIR) - $(CC) $(CFLAGS) $(SOURCES) -o $(OUTPUT) - -clean: - rm -rf $(BUILD_DIR) - -.PHONY: all clean diff --git a/test/platform/patmos/hello/hello.c b/test/platform/patmos/hello/hello.c deleted file mode 100644 index a5bafc3f2..000000000 --- a/test/platform/patmos/hello/hello.c +++ /dev/null @@ -1,5 +0,0 @@ -#include -int main () { - printf("Hello Patmos!\n"); - return 0; -} \ No newline at end of file diff --git a/test/platform/patmos/hello/run.sh b/test/platform/patmos/hello/run.sh deleted file mode 100755 index 443f36ec7..000000000 --- a/test/platform/patmos/hello/run.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -# Make test -rm -r build -make all -pasim ./build/*.elf diff --git a/test/platform/patmos/s4noc_channel_test/Makefile b/test/platform/patmos/s4noc_channel_test/Makefile index 36c229d30..7e1da898f 100644 --- a/test/platform/patmos/s4noc_channel_test/Makefile +++ b/test/platform/patmos/s4noc_channel_test/Makefile @@ -1,7 +1,5 @@ # Makefile for building a simple Hello World program for the Patmos platform APP = main -# Compiler and tools for PATMOS -CC = patmos-clang include $(CURDIR)/../../../../make/patmos/patmos.mk # Paths @@ -11,11 +9,10 @@ BUILD_DIR = $(CURDIR)/build # Source files SOURCES += $(SRC_DIR)/$(APP).c -CFLAGS += -O2 -CFLAGS += -DPLATFORM_PATMOS CFLAGS += -DNETWORK_CHANNEL_S4NOC CFLAGS += -DSCHEDULER_DYNAMIC CFLAGS += -DFEDERATED +CFLAGS += -DLF_LOG_LEVEL_ALL=LF_LOG_LEVEL_INFO # Output binary OUTPUT = $(BUILD_DIR)/$(APP).elf diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index dc1874870..74d0bd818 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -45,7 +45,6 @@ void tearDown(void) { } void receiver_callback_handler(FederatedConnectionBundle *self, const FederateMessage *_msg) { - LF_INFO(NET, "Receiver callback handler called"); (void)self; const TaggedMessage *msg = &_msg->message.tagged_message; LF_INFO(NET,"Receiver: Received message with connection number %i and content %s\n", msg->conn_id, @@ -72,7 +71,7 @@ void send_message(void) { void receive_message(void) { int tries = 0; do { - LF_WARN(NET, "Receiver: Polling for messages, tries: %i\n", tries); + LF_DEBUG(NET, "Receiver: Polling for messages, tries: %i\n", tries); tries++; ((PolledNetworkChannel *)&receiver_channel.super)->poll((PolledNetworkChannel *)&receiver_channel.super); } while (receiver_callback_called == false && tries < MAX_TRIES); diff --git a/test/platform/patmos/s4noc_test/Makefile b/test/platform/patmos/s4noc_test/Makefile deleted file mode 100644 index 36c229d30..000000000 --- a/test/platform/patmos/s4noc_test/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# Makefile for building a simple Hello World program for the Patmos platform -APP = main -# Compiler and tools for PATMOS -CC = patmos-clang - -include $(CURDIR)/../../../../make/patmos/patmos.mk -# Paths -SRC_DIR = $(CURDIR) -BUILD_DIR = $(CURDIR)/build - -# Source files -SOURCES += $(SRC_DIR)/$(APP).c - -CFLAGS += -O2 -CFLAGS += -DPLATFORM_PATMOS -CFLAGS += -DNETWORK_CHANNEL_S4NOC -CFLAGS += -DSCHEDULER_DYNAMIC -CFLAGS += -DFEDERATED - -# Output binary -OUTPUT = $(BUILD_DIR)/$(APP).elf -all : $(OUTPUT) - -# Build rule -$(OUTPUT): $(SOURCES) - mkdir -p $(BUILD_DIR) - $(CC) $(CFLAGS) $(SOURCES) -o $(OUTPUT) - -clean: - rm -rf $(BUILD_DIR) - -.PHONY: all clean diff --git a/test/platform/patmos/s4noc_test/main.c b/test/platform/patmos/s4noc_test/main.c deleted file mode 100644 index 3f695ae16..000000000 --- a/test/platform/patmos/s4noc_test/main.c +++ /dev/null @@ -1,122 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define SOURCE_CORE 1 -#define DESTINATION_CORE 2 - -typedef int64_t instant_t; -typedef int64_t interval_t; - -int _lf_clock_gettime(instant_t* t) { - if (t != NULL) { - *t = get_cpu_usecs() * 1000; - } - - return 0; -} - -int lf_sleep(interval_t sleep_duration) { - instant_t now; - _lf_clock_gettime(&now); - instant_t wakeup = now + sleep_duration; - - // Do busy sleep - do { - _lf_clock_gettime(&now); - } while ((now < wakeup)); - return 0; -} - -// Data structure for Source reactor -typedef struct { - int (*generate_value)(); // Function pointer to generate values - void (*sender_function)(); - int value; // The value to send - pthread_t thread; -} Source; - -// Data structure for Sink reactor -typedef struct { - void (*receiver_function)(); // Function pointer to handle received values - pthread_t thread; -} Sink; - -// Function for the Source reactor to generate a value -int generate_value() { - static int counter = 42; - return counter++; // Incremental values -} - -#define MAX_ITER 5 -void sender_function() { - volatile _IODEV int *s4noc_status = (volatile _IODEV int *) PATMOS_IO_S4NOC; - volatile _IODEV int *s4noc_data = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 4); - volatile _IODEV int *s4noc_dest = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 8); - - *s4noc_dest = DESTINATION_CORE; - for (int i = 0; i < MAX_ITER; i++) { - int status = (*s4noc_status) & 0x01; - while (status == 0) { - status = (*s4noc_status) & 0x01; - } - *s4noc_data = generate_value(); - lf_sleep(1000000); - } - -} - - -// Function for the Sink reactor to handle received values -void receiver_function() { - volatile _IODEV int *s4noc_status = (volatile _IODEV int *) PATMOS_IO_S4NOC; - volatile _IODEV int *s4noc_data = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 4); - volatile _IODEV int *s4noc_source = (volatile _IODEV int *) (PATMOS_IO_S4NOC + 8); - - for (int i = 0; i < MAX_ITER; i++) { - int status = (*s4noc_status) & 0x02; - while (status == 0) { - status = (*s4noc_status) & 0x02; - } - int value = *s4noc_data; - int source = *s4noc_source; - printf("Received: %d from core %d\n", value, source); - } -} - -// Main function -int main() { - - // Initialize the Source reactor - Source source; - source.generate_value = generate_value; - source.sender_function = sender_function; - source.value = 0; - - // Initialize the Sink reactor - Sink sink; - sink.receiver_function = receiver_function; - - if (pthread_create(&source.thread, NULL, source.sender_function, NULL)) { - fprintf(stderr, "Error creating thread\n"); - return 1; - } - - if (pthread_create(&sink.thread, NULL, sink.receiver_function, NULL)) { - fprintf(stderr, "Error creating thread\n"); - return 1; - } - - if (pthread_join(source.thread, NULL)) { - fprintf(stderr, "Error joining thread\n"); - return 2; - } - if (pthread_join(sink.thread, NULL)) { - fprintf(stderr, "Error joining thread\n"); - return 2; - } - return 0; -} \ No newline at end of file diff --git a/test/platform/patmos/s4noc_test/run.sh b/test/platform/patmos/s4noc_test/run.sh deleted file mode 100755 index 876570ec8..000000000 --- a/test/platform/patmos/s4noc_test/run.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -# Make test -make clean -make all -patemu ./build/*.elf - From 843c316c86c68e4edafcc66f428772e417791a95 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 12 Jun 2025 11:43:28 +0200 Subject: [PATCH 07/28] Patmos and s4noc : 7 --- examples/patmos/buildAll.sh | 16 ++----- examples/patmos/hello_lf/Makefile | 4 +- examples/patmos/s4noc_lf/Makefile | 35 +++++++++++++++ examples/patmos/s4noc_lf/build.sh | 5 +++ examples/patmos/s4noc_lf/src/s4noc.lf | 44 +++++++++++++++++++ examples/riot/buildAll.sh | 6 +-- .../org/lflang/validation/AttributeSpec.java | 5 +++ .../uc/UcFederatedProjectTemplateGenerator.kt | 29 +----------- .../lflang/generator/uc/UcNetworkChannel.kt | 23 +++++----- make/patmos/patmos-lfc.mk | 4 +- src/platform/patmos/patmos.c | 1 - 11 files changed, 112 insertions(+), 60 deletions(-) create mode 100755 examples/patmos/s4noc_lf/Makefile create mode 100755 examples/patmos/s4noc_lf/build.sh create mode 100644 examples/patmos/s4noc_lf/src/s4noc.lf diff --git a/examples/patmos/buildAll.sh b/examples/patmos/buildAll.sh index 74226ffd2..32d050244 100755 --- a/examples/patmos/buildAll.sh +++ b/examples/patmos/buildAll.sh @@ -1,13 +1,3 @@ -# set -e -# echo "Building Patmos example" -# ${REACTOR_UC_PATH}/lfc/bin/lfc-dev hello_lf/src/HelloLF.lf -# cmake -Bbuild -DPLATFORM=PATMOS -# make -C build - -# echo "Running Patmos example" -# pasim ./bin/hello_lf.elf - - #!/bin/bash set -e @@ -19,9 +9,9 @@ else for dir in ./*; do if [ -d $dir ]; then echo "Entering $dir" - pushd $dir - ./build.sh - popd + pushd $dir + ./build.sh + popd fi done fi \ No newline at end of file diff --git a/examples/patmos/hello_lf/Makefile b/examples/patmos/hello_lf/Makefile index 7accbf178..e66313c78 100755 --- a/examples/patmos/hello_lf/Makefile +++ b/examples/patmos/hello_lf/Makefile @@ -11,9 +11,7 @@ endif # ---- Patmos specific configuration ---- include ./src-gen/$(LF_MAIN)/Makefile -include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk - -SOURCES += $(patsubst %, $(SRC_GEN_PATH)/%, $(LFC_GEN_SOURCES) $(LFC_GEN_MAIN)) +include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk CFLAGS += -DSCHEDULER_DYNAMIC CFLAGS += -DEVENT_QUEUE_SIZE=$(EVENT_QUEUE_SIZE) diff --git a/examples/patmos/s4noc_lf/Makefile b/examples/patmos/s4noc_lf/Makefile new file mode 100755 index 000000000..8ad91cf77 --- /dev/null +++ b/examples/patmos/s4noc_lf/Makefile @@ -0,0 +1,35 @@ +REACTOR_UC_PATH ?= $(CURDIR)/../../../ +LF_MAIN ?= s4noc + +# The name of the LF application inside "./src" to build/run/flash etc. +SRC_GEN_PATH ?= ./src-gen/$(LF_MAIN) + +# Execute the LF compiler if build target is "all" +ifeq ($(firstword $(MAKECMDGOALS)),all) + _ := $(shell $(REACTOR_UC_PATH)/lfc/bin/lfc-dev src/$(LF_MAIN).lf) +endif + +# ---- Patmos specific configuration ---- +include ./src-gen/$(LF_MAIN)/Makefile +include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk + +CFLAGS += -DSCHEDULER_DYNAMIC +CFLAGS += -DEVENT_QUEUE_SIZE=$(EVENT_QUEUE_SIZE) +CFLAGS += -DREACTION_QUEUE_SIZE=$(REACTION_QUEUE_SIZE) + +# Output directory +BIN_DIR = $(CURDIR)/bin +OUTPUT = $(BIN_DIR)/$(LF_MAIN) + +all: $(OUTPUT) + +# Build rule +$(OUTPUT): $(SOURCES) + mkdir -p $(BIN_DIR) + $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) + +clean: + rm -rf $(BIN_DIR) ./src-gen + +.PHONY: all clean + diff --git a/examples/patmos/s4noc_lf/build.sh b/examples/patmos/s4noc_lf/build.sh new file mode 100755 index 000000000..2cd703911 --- /dev/null +++ b/examples/patmos/s4noc_lf/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +rm -rf bin src-gen +make all +patemu ./bin/s4noc \ No newline at end of file diff --git a/examples/patmos/s4noc_lf/src/s4noc.lf b/examples/patmos/s4noc_lf/src/s4noc.lf new file mode 100644 index 000000000..8931cb968 --- /dev/null +++ b/examples/patmos/s4noc_lf/src/s4noc.lf @@ -0,0 +1,44 @@ +target uC { + platform: PATMOS, + timeout: 1sec +} + +reactor Src(id: int = 0) { + output out: int + + reaction(startup) -> out{= + printf("Hello from Src!\n"); + lf_set(out, self->id); + =} +} + +reactor Dst { + input in: int + state check: bool = false + + reaction(startup) {= + printf("Hello from Dst!\n"); + =} + + reaction(in) {= + printf("Received %d from Src\n", in->value); + validate(in->value == 42); + self->check = true; + env->request_shutdown(env); + =} + + reaction(shutdown) {= + validate(self->check); + =} +} + +main reactor { + @interface_s4noc(core=0) + r1 = new Src(id=42) + + @interface_s4noc(core=1) + r2 = new Dst() + + @link(left="0", right="1") + r1.out -> r2.in +} diff --git a/examples/riot/buildAll.sh b/examples/riot/buildAll.sh index 3f0cb33e2..3d75f8f56 100755 --- a/examples/riot/buildAll.sh +++ b/examples/riot/buildAll.sh @@ -6,8 +6,8 @@ set -e for dir in ./*; do if [ -d $dir ]; then echo "Entering $dir" - pushd $dir - ./build.sh - popd + pushd $dir + ./build.sh + popd fi done diff --git a/lfc/core/src/main/java/org/lflang/validation/AttributeSpec.java b/lfc/core/src/main/java/org/lflang/validation/AttributeSpec.java index 908f0f500..1056ef832 100644 --- a/lfc/core/src/main/java/org/lflang/validation/AttributeSpec.java +++ b/lfc/core/src/main/java/org/lflang/validation/AttributeSpec.java @@ -303,6 +303,9 @@ enum AttrParamType { List.of( new AttrParamSpec("name", AttrParamType.STRING, true), new AttrParamSpec("address", AttrParamType.STRING, true)))); + ATTRIBUTE_SPECS_BY_NAME.put( + "interface_s4noc", + new AttributeSpec(List.of(new AttrParamSpec("core", AttrParamType.INT, false)))); ATTRIBUTE_SPECS_BY_NAME.put( "interface_custom", new AttributeSpec( @@ -327,6 +330,8 @@ enum AttrParamType { ATTRIBUTE_SPECS_BY_NAME.put("platform_riot", new AttributeSpec(null)); // @platform_zephyr ATTRIBUTE_SPECS_BY_NAME.put("platform_zephyr", new AttributeSpec(null)); + // @platform_patmos + ATTRIBUTE_SPECS_BY_NAME.put("platform_patmos", new AttributeSpec(null)); // @platform_native ATTRIBUTE_SPECS_BY_NAME.put("platform_native", new AttributeSpec(null)); // @clock_sync(grandmaster=true, server_port=1042) diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt index b323fdf57..495577087 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt @@ -132,34 +132,7 @@ class UcFederatedTemplateGenerator( FileUtil.writeToFile(cmake, projectRoot.resolve("CMakeLists.txt")) } - private fun generateFilesPatmos() { - val make = - """ - |LF_MAIN ?= ${mainDef.name} - |LF_FED ?= ${federate.name} - | - |# Paths - |SRC_DIR = src-gen/${mainDef.name}/${federate.name} - |BUILD_DIR = build - | - |# Source files - |SOURCES = $S(SRC_DIR)/*.c - | - |# Output binary - |OUTPUT = $S(BUILD_DIR)/${federate.name}.elf - | - |all: $S(OUTPUT) - | - |$S(OUTPUT): $S(SOURCES) - | mkdir -p $S(BUILD_DIR) - | $S(CC) $S(CFLAGS) $S(SOURCES) -o $S(OUTPUT) - | - |.PHONY: all clean - |include $S(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk - """ - .trimMargin() - FileUtil.writeToFile(make, projectRoot.resolve("Makefile")) - } + private fun generateFilesPatmos() {} fun generateFiles() { if (Files.exists(projectRoot)) { diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt index f0034df43..2f773e309 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt @@ -24,7 +24,8 @@ object UcNetworkInterfaceFactory { UcCoapUdpIpInterface.fromAttribute(federate, attr) }, Pair(CUSTOM) { federate, attr -> UcCustomInterface.fromAttribute(federate, attr) }, - Pair(UART) { federate, attr -> UcUARTInterface.fromAttribute(federate, attr) }) + Pair(UART) { federate, attr -> UcUARTInterface.fromAttribute(federate, attr) }, + Pair(S4NOC) { federate, attr -> UcS4NocInterface.fromAttribute(federate, attr) }) fun createInterfaces(federate: UcFederate): List { val attrs: List = getInterfaceAttributes(federate.inst) @@ -74,8 +75,7 @@ class UcUARTEndpoint( class UcCoapUdpIpEndpoint(val ipAddress: IPAddress, iface: UcCoapUdpIpInterface) : UcNetworkEndpoint(iface) {} -class UcS4NocEndpoint(val s4nocId: Int, val port: Int, iface: UcS4NocInterface) : - UcNetworkEndpoint(iface) {} +class UcS4NocEndpoint(val core: Int, iface: UcS4NocInterface) : UcNetworkEndpoint(iface) {} class UcCustomEndpoint(iface: UcCustomInterface) : UcNetworkEndpoint(iface) {} @@ -200,23 +200,26 @@ class UcCoapUdpIpInterface(private val ipAddress: IPAddress, name: String? = nul } } -class UcS4NocInterface(val s4nocId: Int, val port: Int, name: String? = null) : +class UcS4NocInterface(val core: Int, name: String? = null) : UcNetworkInterface(S4NOC, name ?: "s4noc") { override val includeHeaders: String = "" override val compileDefs: String = "NETWORK_CHANNEL_S4NOC" + init { + println("UcS4NocInterface created with core=$core and name=${name ?: "s4noc"}") + } + fun createEndpoint(): UcS4NocEndpoint { - val ep = UcS4NocEndpoint(s4nocId, port, this) + val ep = UcS4NocEndpoint(core, this) endpoints.add(ep) return ep } companion object { fun fromAttribute(federate: UcFederate, attr: Attribute): UcS4NocInterface { - val s4nocId = attr.getParamInt("s4noc_id") ?: 0 - val port = attr.getParamInt("port") ?: 0 + val core = attr.getParamInt("core") ?: 0 val name = attr.getParamString("name") - return UcS4NocInterface(s4nocId, port, name) + return UcS4NocInterface(core, name) } } } @@ -401,10 +404,10 @@ class UcS4NocChannel( private val destS4Noc = dest override fun generateChannelCtorSrc() = - "S4NocChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.s4nocId else destS4Noc.s4nocId}, ${if (serverLhs) srcS4Noc.port else destS4Noc.port});" + "S4NocChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.core else destS4Noc.core});" override fun generateChannelCtorDest() = - "S4NocChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.s4nocId else destS4Noc.s4nocId}, ${if (serverLhs) srcS4Noc.port else destS4Noc.port});" + "S4NocChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.core else destS4Noc.core});" override val codeType: String get() = "S4NocChannel" diff --git a/make/patmos/patmos-lfc.mk b/make/patmos/patmos-lfc.mk index 29fa902b5..b95336ce1 100644 --- a/make/patmos/patmos-lfc.mk +++ b/make/patmos/patmos-lfc.mk @@ -30,10 +30,10 @@ else include $(LF_SRC_GEN_PATH)/Makefile # Include generated c files - SRC += $(patsubst %, $(LF_SRC_GEN_PATH)/%, $(LFC_GEN_SOURCES)) + SOURCES += $(patsubst %, $(LF_SRC_GEN_PATH)/%, $(LFC_GEN_SOURCES)) # Include generated main file - SRC += $(LF_SRC_GEN_PATH)/${LFC_GEN_MAIN} + SOURCES += $(LF_SRC_GEN_PATH)/${LFC_GEN_MAIN} # Include generated h files CFLAGS += -I$(LF_SRC_GEN_PATH) diff --git a/src/platform/patmos/patmos.c b/src/platform/patmos/patmos.c index 523c3e2f6..0b6b48e87 100644 --- a/src/platform/patmos/patmos.c +++ b/src/platform/patmos/patmos.c @@ -126,5 +126,4 @@ void Mutex_ctor(Mutex *super) { MutexPatmos *self = (MutexPatmos *)super; super->lock = MutexPatmos_lock; super->unlock = MutexPatmos_unlock; - // critical_section_init(&self->crit_sec); } From a9286192fa509507e183c53e94c8954eaf4a22f3 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 19 Jun 2025 14:37:17 +0200 Subject: [PATCH 08/28] Patmos and S4NoC: 8 --- examples/patmos/hello_lf/Makefile | 2 -- .../s4noc_fed_lf/S4NoCFedLF/r1/Makefile | 21 +++++++++++ .../s4noc_fed_lf/S4NoCFedLF/r1/run_lfc.sh | 5 +++ .../s4noc_fed_lf/S4NoCFedLF/r2/Makefile | 21 +++++++++++ .../s4noc_fed_lf/S4NoCFedLF/r2/run_lfc.sh | 5 +++ examples/patmos/s4noc_fed_lf/build.sh | 22 ++++++++++++ .../src/S4NoCFedLF.lf} | 4 +-- examples/patmos/s4noc_lf/Makefile | 35 ------------------- examples/patmos/s4noc_lf/build.sh | 5 --- examples/pico/buildAll.sh | 9 +++-- examples/riot/blinky/Makefile | 21 ----------- examples/riot/blinky/build.sh | 2 -- examples/riot/blinky/main.c | 17 --------- .../platform/patmos/s4noc_channel.h | 2 +- .../uc/UcFederatedProjectTemplateGenerator.kt | 31 +++++++++++++++- .../lflang/generator/uc/UcNetworkChannel.kt | 6 ++-- make/patmos/patmos-lfc.mk | 2 ++ make/patmos/patmos.mk | 4 ++- src/platform/patmos/s4noc_channel.c | 5 ++- .../patmos/s4noc_channel_test/Makefile | 3 -- .../platform/patmos/s4noc_channel_test/main.c | 7 ++-- 21 files changed, 129 insertions(+), 100 deletions(-) create mode 100644 examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile create mode 100755 examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/run_lfc.sh create mode 100644 examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile create mode 100755 examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/run_lfc.sh create mode 100755 examples/patmos/s4noc_fed_lf/build.sh rename examples/patmos/{s4noc_lf/src/s4noc.lf => s4noc_fed_lf/src/S4NoCFedLF.lf} (92%) delete mode 100755 examples/patmos/s4noc_lf/Makefile delete mode 100755 examples/patmos/s4noc_lf/build.sh delete mode 100755 examples/riot/blinky/Makefile delete mode 100755 examples/riot/blinky/build.sh delete mode 100755 examples/riot/blinky/main.c diff --git a/examples/patmos/hello_lf/Makefile b/examples/patmos/hello_lf/Makefile index e66313c78..f8b7eb1f3 100755 --- a/examples/patmos/hello_lf/Makefile +++ b/examples/patmos/hello_lf/Makefile @@ -10,10 +10,8 @@ ifeq ($(firstword $(MAKECMDGOALS)),all) endif # ---- Patmos specific configuration ---- -include ./src-gen/$(LF_MAIN)/Makefile include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk -CFLAGS += -DSCHEDULER_DYNAMIC CFLAGS += -DEVENT_QUEUE_SIZE=$(EVENT_QUEUE_SIZE) CFLAGS += -DREACTION_QUEUE_SIZE=$(REACTION_QUEUE_SIZE) diff --git a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile new file mode 100644 index 000000000..b76828b6e --- /dev/null +++ b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile @@ -0,0 +1,21 @@ +LF_MAIN ?= S4NoCFedLF +LF_FED ?= r1 + +include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk + +# ---- Patmos specific configuration ---- +# Output directory +BIN_DIR = $(CURDIR)/bin +OUTPUT = $(BIN_DIR)/$(LF_MAIN) +all: $(OUTPUT) + $(info Building $(LF_MAIN) federate $(LF_FED)) + $(info Output directory: $(BIN_DIR)) + $(info Output binary: $(OUTPUT)) + +# Build rule +$(OUTPUT): $(SOURCES) + mkdir -p $(BIN_DIR) + $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) +# Clean rule +clean: + rm -rf $(BIN_DIR) \ No newline at end of file diff --git a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/run_lfc.sh b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/run_lfc.sh new file mode 100755 index 000000000..8af94a3b1 --- /dev/null +++ b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/run_lfc.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +LF_MAIN=S4NoCFedLF + +$REACTOR_UC_PATH/lfc/bin/lfc-dev ../../src/$LF_MAIN.lf -n -o . \ No newline at end of file diff --git a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile new file mode 100644 index 000000000..8a361917c --- /dev/null +++ b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile @@ -0,0 +1,21 @@ +LF_MAIN ?= S4NoCFedLF +LF_FED ?= r2 + +include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk + +# ---- Patmos specific configuration ---- +# Output directory +BIN_DIR = $(CURDIR)/bin +OUTPUT = $(BIN_DIR)/$(LF_MAIN) +all: $(OUTPUT) + $(info Building $(LF_MAIN) federate $(LF_FED)) + $(info Output directory: $(BIN_DIR)) + $(info Output binary: $(OUTPUT)) + +# Build rule +$(OUTPUT): $(SOURCES) + mkdir -p $(BIN_DIR) + $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) +# Clean rule +clean: + rm -rf $(BIN_DIR) \ No newline at end of file diff --git a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/run_lfc.sh b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/run_lfc.sh new file mode 100755 index 000000000..8af94a3b1 --- /dev/null +++ b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/run_lfc.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +LF_MAIN=S4NoCFedLF + +$REACTOR_UC_PATH/lfc/bin/lfc-dev ../../src/$LF_MAIN.lf -n -o . \ No newline at end of file diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh new file mode 100755 index 000000000..d378b7a77 --- /dev/null +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -0,0 +1,22 @@ +#!/bin/bash +LF_MAIN=S4NoCFedLF + +# Generate configuration templates +rm -rf $LF_MAIN +$REACTOR_UC_PATH/lfc/bin/lfc-dev --gen-fed-templates src/$LF_MAIN.lf + + +# Generate and build r1 sources +pushd ./$LF_MAIN/r1 + ./run_lfc.sh + make clean + make all +popd + +# Generate and build r2 sources +pushd ./$LF_MAIN/r2 + ./run_lfc.sh + make clean + make all +popd + diff --git a/examples/patmos/s4noc_lf/src/s4noc.lf b/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf similarity index 92% rename from examples/patmos/s4noc_lf/src/s4noc.lf rename to examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf index 8931cb968..98fdd40f1 100644 --- a/examples/patmos/s4noc_lf/src/s4noc.lf +++ b/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf @@ -32,13 +32,13 @@ reactor Dst { =} } -main reactor { +federated reactor { @interface_s4noc(core=0) r1 = new Src(id=42) @interface_s4noc(core=1) r2 = new Dst() - @link(left="0", right="1") + // @link(left="0", right="1") r1.out -> r2.in } diff --git a/examples/patmos/s4noc_lf/Makefile b/examples/patmos/s4noc_lf/Makefile deleted file mode 100755 index 8ad91cf77..000000000 --- a/examples/patmos/s4noc_lf/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -REACTOR_UC_PATH ?= $(CURDIR)/../../../ -LF_MAIN ?= s4noc - -# The name of the LF application inside "./src" to build/run/flash etc. -SRC_GEN_PATH ?= ./src-gen/$(LF_MAIN) - -# Execute the LF compiler if build target is "all" -ifeq ($(firstword $(MAKECMDGOALS)),all) - _ := $(shell $(REACTOR_UC_PATH)/lfc/bin/lfc-dev src/$(LF_MAIN).lf) -endif - -# ---- Patmos specific configuration ---- -include ./src-gen/$(LF_MAIN)/Makefile -include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk - -CFLAGS += -DSCHEDULER_DYNAMIC -CFLAGS += -DEVENT_QUEUE_SIZE=$(EVENT_QUEUE_SIZE) -CFLAGS += -DREACTION_QUEUE_SIZE=$(REACTION_QUEUE_SIZE) - -# Output directory -BIN_DIR = $(CURDIR)/bin -OUTPUT = $(BIN_DIR)/$(LF_MAIN) - -all: $(OUTPUT) - -# Build rule -$(OUTPUT): $(SOURCES) - mkdir -p $(BIN_DIR) - $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) - -clean: - rm -rf $(BIN_DIR) ./src-gen - -.PHONY: all clean - diff --git a/examples/patmos/s4noc_lf/build.sh b/examples/patmos/s4noc_lf/build.sh deleted file mode 100755 index 2cd703911..000000000 --- a/examples/patmos/s4noc_lf/build.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -rm -rf bin src-gen -make all -patemu ./bin/s4noc \ No newline at end of file diff --git a/examples/pico/buildAll.sh b/examples/pico/buildAll.sh index 1c84511f7..319fe8ad9 100755 --- a/examples/pico/buildAll.sh +++ b/examples/pico/buildAll.sh @@ -1,4 +1,9 @@ #!/bin/env bash set -e -cmake -Bbuild -cmake --build build + +if [ -z "$PICO_SDK_PATH" ]; then + echo "Error: PICO_SDK_PATH is not defined. Please set it before running this script." +else + cmake -Bbuild + cmake --build build +fi diff --git a/examples/riot/blinky/Makefile b/examples/riot/blinky/Makefile deleted file mode 100755 index b36e971dd..000000000 --- a/examples/riot/blinky/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# name of your application -APPLICATION = lf-test - -# This has to be the absolute path to the RIOT base directory: -RIOTBASE ?= $(CURDIR)/../../../../RIOT - -# If no BOARD is found in the environment, use this default: -BOARD ?= native - -# Comment this out to disable code in RIOT that does safety checking -# which is not needed in a production environment but helps in the -# development process: -DEVELHELP ?= 1 - -# Change this to 0 show compiler invocation lines by default: -QUIET ?= 1 - -# Enable reactor-uc features -# CFLAGS += -DNETWORK_CHANNEL_TCP_POSIX - -include $(CURDIR)/../../../make/riot/riot.mk diff --git a/examples/riot/blinky/build.sh b/examples/riot/blinky/build.sh deleted file mode 100755 index fe9a489ef..000000000 --- a/examples/riot/blinky/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -make all \ No newline at end of file diff --git a/examples/riot/blinky/main.c b/examples/riot/blinky/main.c deleted file mode 100755 index 1ccce8497..000000000 --- a/examples/riot/blinky/main.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "board.h" -#include "reactor-uc/reactor-uc.h" -#include -#include "../../common/timer_source.h" - - -LF_DEFINE_REACTION_BODY(TimerSource, r) { - LF_SCOPE_SELF(TimerSource); - LF_SCOPE_ENV(); - printf("Hello World @ %lld\n", env->get_elapsed_logical_time(env)); - LED0_TOGGLE; -} - -int main() { - lf_start(); - return 0; -} diff --git a/include/reactor-uc/platform/patmos/s4noc_channel.h b/include/reactor-uc/platform/patmos/s4noc_channel.h index f11fb225b..f3e173e7b 100644 --- a/include/reactor-uc/platform/patmos/s4noc_channel.h +++ b/include/reactor-uc/platform/patmos/s4noc_channel.h @@ -35,6 +35,6 @@ struct S4NOCPollChannel { pthread_t worker_thread; }; -void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned int destination_core); +void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core); #endif diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt index 495577087..f057b421a 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt @@ -132,7 +132,36 @@ class UcFederatedTemplateGenerator( FileUtil.writeToFile(cmake, projectRoot.resolve("CMakeLists.txt")) } - private fun generateFilesPatmos() {} + private fun generateFilesPatmos() { + val make = + """ + |LF_MAIN ?= ${mainDef.name} + |LF_FED ?= ${federate.name} + | + |include $S(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk + | + |# ---- Patmos specific configuration ---- + |# Output directory + |BIN_DIR = $(CURDIR)/bin + |OUTPUT = $(BIN_DIR)/$(LF_MAIN) + | + |all: $(OUTPUT) + | $(info Building $(LF_MAIN) federate $(LF_FED)) + | $(info Output directory: $(BIN_DIR)) + | $(info Output binary: $(OUTPUT)) + | + |# Build rule + |$(OUTPUT): $(SOURCES) + | mkdir -p $(BIN_DIR) + | $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) + | + |# Clean rule + |clean: + | rm -rf $(BIN_DIR) + """ + .trimMargin() + FileUtil.writeToFile(make, projectRoot.resolve("Makefile")) + } fun generateFiles() { if (Files.exists(projectRoot)) { diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt index 2f773e309..d9dcd0185 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt @@ -404,13 +404,13 @@ class UcS4NocChannel( private val destS4Noc = dest override fun generateChannelCtorSrc() = - "S4NocChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.core else destS4Noc.core});" + "S4NOCPollChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.core else destS4Noc.core});" override fun generateChannelCtorDest() = - "S4NocChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.core else destS4Noc.core});" + "S4NOCPollChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.core else destS4Noc.core});" override val codeType: String - get() = "S4NocChannel" + get() = "S4NOCPollChannel" } class UcCustomChannel( diff --git a/make/patmos/patmos-lfc.mk b/make/patmos/patmos-lfc.mk index b95336ce1..a3c1fe83d 100644 --- a/make/patmos/patmos-lfc.mk +++ b/make/patmos/patmos-lfc.mk @@ -7,12 +7,14 @@ endif # Check if this is a federated program ifdef LF_FED + $(info Building federated program: $(LF_MAIN) with federation: $(LF_FED)) # Name of your application APPLICATION ?= $(LF_MAIN)-$(LF_FED) # Path of generated lf c-code LF_SRC_GEN_PATH ?= $(CURDIR)/src-gen/$(LF_MAIN)/$(LF_FED) else + $(info Building non-federated program: $(LF_MAIN)) # Name of your application APPLICATION ?= $(LF_MAIN) diff --git a/make/patmos/patmos.mk b/make/patmos/patmos.mk index b4530dcb9..ed8c3d073 100644 --- a/make/patmos/patmos.mk +++ b/make/patmos/patmos.mk @@ -33,4 +33,6 @@ SOURCES += $(REACTOR_UC_PATH)/external/proto/message.pb.c CFLAGS += -O2 CFLAGS += -Wall -Wextra CFLAGS += -DPLATFORM_PATMOS - \ No newline at end of file +CFLAGS += -DNETWORK_CHANNEL_S4NOC +CFLAGS += -DSCHEDULER_DYNAMIC +CFLAGS += -DFEDERATED \ No newline at end of file diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index c59a492ad..003bdbe52 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -112,9 +112,8 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { } } -void S4NOCPollChannel_ctor(S4NOCPollChannel *self, Environment *env, unsigned int destination_core) { - assert(self != NULL); - assert(env != NULL); +void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core) { + assert(self != NULL); self->super.super.mode = NETWORK_CHANNEL_MODE_POLLED; self->super.super.expected_connect_duration = SEC(0); diff --git a/test/platform/patmos/s4noc_channel_test/Makefile b/test/platform/patmos/s4noc_channel_test/Makefile index 7e1da898f..aef25935d 100644 --- a/test/platform/patmos/s4noc_channel_test/Makefile +++ b/test/platform/patmos/s4noc_channel_test/Makefile @@ -9,9 +9,6 @@ BUILD_DIR = $(CURDIR)/build # Source files SOURCES += $(SRC_DIR)/$(APP).c -CFLAGS += -DNETWORK_CHANNEL_S4NOC -CFLAGS += -DSCHEDULER_DYNAMIC -CFLAGS += -DFEDERATED CFLAGS += -DLF_LOG_LEVEL_ALL=LF_LOG_LEVEL_INFO # Output binary diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index 74d0bd818..27ce42d3b 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -26,11 +26,14 @@ NetworkChannel *receiver = (NetworkChannel *)&receiver_channel.super; bool receiver_callback_called = false; void setUp(void) { + /* init environment */ FederatedEnvironment_ctor(&fed_env, &parent, NULL, false, net_bundles, 2, &startup_coordinator, NULL); - S4NOCPollChannel_ctor(&sender_channel, &fed_env.super, DESTINATION_CORE); - S4NOCPollChannel_ctor(&receiver_channel, &fed_env.super, SOURCE_CORE); + /* init channel */ + S4NOCPollChannel_ctor(&sender_channel, DESTINATION_CORE); + S4NOCPollChannel_ctor(&receiver_channel, SOURCE_CORE); + /* init bundles */ FederatedConnectionBundle_ctor(&sender_bundle, &parent, sender, NULL, NULL, 0, NULL, NULL, 0, 0); FederatedConnectionBundle_ctor(&receiver_bundle, &parent, receiver, NULL, NULL, 0, NULL, NULL, 0, 0); From 8a2e8423e73418c740910eaee34df5185e0d7163 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Wed, 25 Jun 2025 11:32:55 +0200 Subject: [PATCH 09/28] Patmos and S4NoC 9 --- .gitignore | 3 +++ .../s4noc_fed_lf/S4NoCFedLF/r1/Makefile | 27 ++++++++++++++----- .../s4noc_fed_lf/S4NoCFedLF/r2/Makefile | 27 ++++++++++++++----- examples/patmos/s4noc_fed_lf/build.sh | 10 ++++--- examples/patmos/s4noc_fed_lf/main.c | 3 +++ .../uc/UcFederatedProjectTemplateGenerator.kt | 25 ++++++++++++----- make/patmos/patmos-lfc.mk | 5 +++- make/patmos/patmos.mk | 1 - 8 files changed, 74 insertions(+), 27 deletions(-) create mode 100644 examples/patmos/s4noc_fed_lf/main.c diff --git a/.gitignore b/.gitignore index a6f61ddaf..b659baf7a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ cmake-build-release doc/html doc/latex doc/markdown/platform +*.o +*.bc +*.elf diff --git a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile index b76828b6e..18da38214 100644 --- a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile +++ b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile @@ -6,16 +6,29 @@ include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk # ---- Patmos specific configuration ---- # Output directory BIN_DIR = $(CURDIR)/bin -OUTPUT = $(BIN_DIR)/$(LF_MAIN) +OBJ_DIR = $(CURDIR)/obj +OUTPUT = $(BIN_DIR)/$(LF_MAIN).a +# OBJECTS = $(patsubst %.c,$(OBJ_DIR)/%.o,$(SOURCES)) +OBJECTS = $(SOURCES:.c=.bc) + all: $(OUTPUT) - $(info Building $(LF_MAIN) federate $(LF_FED)) - $(info Output directory: $(BIN_DIR)) - $(info Output binary: $(OUTPUT)) + $(info Building $(LF_MAIN) federate $(LF_FED)) + $(info Output directory: $(BIN_DIR)) + $(info Output binary: $(OUTPUT)) + $(info Sources: $(SOURCES)) + $(info Compiler: $(CC)) + $(info Compiler flags: $(CFLAGS)) # Build rule -$(OUTPUT): $(SOURCES) - mkdir -p $(BIN_DIR) - $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) +$(OUTPUT): $(OBJECTS) + mkdir -p $(BIN_DIR) + $(CC) -c $(SOURCES) $(CFLAGS) + llvm-ar rcs $@ $(OBJECTS) + +%.bc: %.c + mkdir -p $(OBJ_DIR) + $(CC) -emit-llvm -c $< -o $@ $(CFLAGS) + # Clean rule clean: rm -rf $(BIN_DIR) \ No newline at end of file diff --git a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile index 8a361917c..f1a605a38 100644 --- a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile +++ b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile @@ -6,16 +6,29 @@ include $(REACTOR_UC_PATH)/make/patmos/patmos-lfc.mk # ---- Patmos specific configuration ---- # Output directory BIN_DIR = $(CURDIR)/bin -OUTPUT = $(BIN_DIR)/$(LF_MAIN) +OBJ_DIR = $(CURDIR)/obj +OUTPUT = $(BIN_DIR)/$(LF_MAIN).a +# OBJECTS = $(patsubst %.c,$(OBJ_DIR)/%.o,$(SOURCES)) +OBJECTS = $(SOURCES:.c=.bc) + all: $(OUTPUT) - $(info Building $(LF_MAIN) federate $(LF_FED)) - $(info Output directory: $(BIN_DIR)) - $(info Output binary: $(OUTPUT)) + $(info Building $(LF_MAIN) federate $(LF_FED)) + $(info Output directory: $(BIN_DIR)) + $(info Output binary: $(OUTPUT)) + $(info Sources: $(SOURCES)) + $(info Compiler: $(CC)) + $(info Compiler flags: $(CFLAGS)) # Build rule -$(OUTPUT): $(SOURCES) - mkdir -p $(BIN_DIR) - $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) +$(OUTPUT): $(OBJECTS) + mkdir -p $(BIN_DIR) + $(CC) -c $(SOURCES) $(CFLAGS) + llvm-ar rcs $@ $(OBJECTS) + +%.bc: %.c + mkdir -p $(OBJ_DIR) + $(CC) -emit-llvm -c $< -o $@ $(CFLAGS) + # Clean rule clean: rm -rf $(BIN_DIR) \ No newline at end of file diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index d378b7a77..0a5c9387a 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -1,7 +1,7 @@ #!/bin/bash LF_MAIN=S4NoCFedLF - -# Generate configuration templates +BIN_DIR=bin +# Generate configuration templates rm -rf $LF_MAIN $REACTOR_UC_PATH/lfc/bin/lfc-dev --gen-fed-templates src/$LF_MAIN.lf @@ -9,14 +9,16 @@ $REACTOR_UC_PATH/lfc/bin/lfc-dev --gen-fed-templates src/$LF_MAIN.lf # Generate and build r1 sources pushd ./$LF_MAIN/r1 ./run_lfc.sh - make clean make all popd # Generate and build r2 sources pushd ./$LF_MAIN/r2 ./run_lfc.sh - make clean make all popd +mkdir -p $BIN_DIR +patmos-clang main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a \ + -o $BIN_DIR/$LF_MAIN +patemu $BIN_DIR/$LF_MAIN diff --git a/examples/patmos/s4noc_fed_lf/main.c b/examples/patmos/s4noc_fed_lf/main.c new file mode 100644 index 000000000..971f78904 --- /dev/null +++ b/examples/patmos/s4noc_fed_lf/main.c @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} \ No newline at end of file diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt index f057b421a..a82221cb8 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt @@ -143,17 +143,28 @@ class UcFederatedTemplateGenerator( |# ---- Patmos specific configuration ---- |# Output directory |BIN_DIR = $(CURDIR)/bin - |OUTPUT = $(BIN_DIR)/$(LF_MAIN) + |OBJ_DIR = $(CURDIR)/obj + |OUTPUT = $(BIN_DIR)/$(LF_MAIN).a + |# OBJECTS = $(patsubst %.c,$(OBJ_DIR)/%.o,$(SOURCES)) + |OBJECTS = $(SOURCES:.c=.bc) | |all: $(OUTPUT) - | $(info Building $(LF_MAIN) federate $(LF_FED)) - | $(info Output directory: $(BIN_DIR)) - | $(info Output binary: $(OUTPUT)) + | $(info Building $(LF_MAIN) federate $(LF_FED)) + | $(info Output directory: $(BIN_DIR)) + | $(info Output binary: $(OUTPUT)) + | $(info Sources: $(SOURCES)) + | $(info Compiler: $(CC)) + | $(info Compiler flags: $(CFLAGS)) | |# Build rule - |$(OUTPUT): $(SOURCES) - | mkdir -p $(BIN_DIR) - | $(CC) $(SOURCES) $(CFLAGS) -o $(OUTPUT) + |$(OUTPUT): $(OBJECTS) + | mkdir -p $(BIN_DIR) + | $(CC) -c $(SOURCES) $(CFLAGS) + | llvm-ar rcs $@ $(OBJECTS) + | + |%.bc: %.c + | mkdir -p $(OBJ_DIR) + | $(CC) -emit-llvm -c $< -o $@ $(CFLAGS) | |# Clean rule |clean: diff --git a/make/patmos/patmos-lfc.mk b/make/patmos/patmos-lfc.mk index a3c1fe83d..cd788d287 100644 --- a/make/patmos/patmos-lfc.mk +++ b/make/patmos/patmos-lfc.mk @@ -28,6 +28,7 @@ ifeq ($(firstword $(MAKECMDGOALS)),clean) # Delete src-gen folder if build target is "clean" _ := $(shell rm -rf $(LF_SRC_GEN_PATH)) else + # Include the Makefile of the generated target application include $(LF_SRC_GEN_PATH)/Makefile @@ -35,7 +36,9 @@ else SOURCES += $(patsubst %, $(LF_SRC_GEN_PATH)/%, $(LFC_GEN_SOURCES)) # Include generated main file - SOURCES += $(LF_SRC_GEN_PATH)/${LFC_GEN_MAIN} + ifndef LF_FED + SOURCES += $(LF_SRC_GEN_PATH)/${LFC_GEN_MAIN} + endif # Include generated h files CFLAGS += -I$(LF_SRC_GEN_PATH) diff --git a/make/patmos/patmos.mk b/make/patmos/patmos.mk index ed8c3d073..972dc63fc 100644 --- a/make/patmos/patmos.mk +++ b/make/patmos/patmos.mk @@ -18,7 +18,6 @@ CFLAGS += -I$(REACTOR_UC_PATH)/external/nanopb/pb CFLAGS += -I$(REACTOR_UC_PATH)/external/proto - CFLAGS += -I$(REACTOR_UC_PATH)/external/Unity/src CFLAGS += -I$(REACTOR_UC_PATH)/test/unit From 87f79d8a609133a6aa70b42e609a89d6b9083640 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 1 Jul 2025 16:01:33 +0200 Subject: [PATCH 10/28] Patmos and S4NoC 10: manipulator to the second-to-last reactors is added. --- .../patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile | 18 +++++++----------- .../patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile | 18 +++++++----------- examples/patmos/s4noc_fed_lf/build.sh | 7 ++++++- .../uc/UcFederatedProjectTemplateGenerator.kt | 18 +++++++----------- 4 files changed, 27 insertions(+), 34 deletions(-) diff --git a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile index 18da38214..3070347ab 100644 --- a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile +++ b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r1/Makefile @@ -9,25 +9,21 @@ BIN_DIR = $(CURDIR)/bin OBJ_DIR = $(CURDIR)/obj OUTPUT = $(BIN_DIR)/$(LF_MAIN).a # OBJECTS = $(patsubst %.c,$(OBJ_DIR)/%.o,$(SOURCES)) -OBJECTS = $(SOURCES:.c=.bc) +OBJECTS ?= $(SOURCES:.c=.bc) +FILTER_OUT ?= "" all: $(OUTPUT) - $(info Building $(LF_MAIN) federate $(LF_FED)) - $(info Output directory: $(BIN_DIR)) - $(info Output binary: $(OUTPUT)) - $(info Sources: $(SOURCES)) - $(info Compiler: $(CC)) - $(info Compiler flags: $(CFLAGS)) # Build rule $(OUTPUT): $(OBJECTS) - mkdir -p $(BIN_DIR) - $(CC) -c $(SOURCES) $(CFLAGS) - llvm-ar rcs $@ $(OBJECTS) + @echo "BUILDING $(notdir $@) from $^ except $(FILTER_OUT)" + mkdir -p $(BIN_DIR) + llvm-ar rcsv $@ $(filter-out $(FILTER_OUT), $(OBJECTS)); %.bc: %.c + @echo "$(notdir $^) COMPILED TO $(notdir $@)" mkdir -p $(OBJ_DIR) - $(CC) -emit-llvm -c $< -o $@ $(CFLAGS) + $(CC) -emit-llvm -c $^ -o $@ $(CFLAGS) # Clean rule clean: diff --git a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile index f1a605a38..3716cddda 100644 --- a/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile +++ b/examples/patmos/s4noc_fed_lf/S4NoCFedLF/r2/Makefile @@ -9,25 +9,21 @@ BIN_DIR = $(CURDIR)/bin OBJ_DIR = $(CURDIR)/obj OUTPUT = $(BIN_DIR)/$(LF_MAIN).a # OBJECTS = $(patsubst %.c,$(OBJ_DIR)/%.o,$(SOURCES)) -OBJECTS = $(SOURCES:.c=.bc) +OBJECTS ?= $(SOURCES:.c=.bc) +FILTER_OUT ?= "" all: $(OUTPUT) - $(info Building $(LF_MAIN) federate $(LF_FED)) - $(info Output directory: $(BIN_DIR)) - $(info Output binary: $(OUTPUT)) - $(info Sources: $(SOURCES)) - $(info Compiler: $(CC)) - $(info Compiler flags: $(CFLAGS)) # Build rule $(OUTPUT): $(OBJECTS) - mkdir -p $(BIN_DIR) - $(CC) -c $(SOURCES) $(CFLAGS) - llvm-ar rcs $@ $(OBJECTS) + @echo "BUILDING $(notdir $@) from $^ except $(FILTER_OUT)" + mkdir -p $(BIN_DIR) + llvm-ar rcsv $@ $(filter-out $(FILTER_OUT), $(OBJECTS)); %.bc: %.c + @echo "$(notdir $^) COMPILED TO $(notdir $@)" mkdir -p $(OBJ_DIR) - $(CC) -emit-llvm -c $< -o $@ $(CFLAGS) + $(CC) -emit-llvm -c $^ -o $@ $(CFLAGS) # Clean rule clean: diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index 0a5c9387a..4b334723a 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -14,11 +14,16 @@ popd # Generate and build r2 sources pushd ./$LF_MAIN/r2 + REACTOR_PATH=$(pwd)/src-gen/S4NoCFedLF/r2 ./run_lfc.sh - make all + sed -i 's/_lf_environment/_lf_environment_2/g' $REACTOR_PATH/lf_start.c + # make all FILTER_OUT="%unity.bc %action.bc %builtin_triggers.bc %clock_synchronization.bc %connection.bc %environment.bc %event.bc %federated.bc %logging.bc %network_channel.bc %physical_clock.bc %platform.bc %port.bc %queues.bc %reaction.bc %reactor.bc %scheduler.bc %serialization.bc %startup_coordinator.bc %tag.bc %timer.bc %trigger.bc %util.bc %pb_common.bc %pb_decode.bc %pb_encode.bc %message.pb.bc" + make all OBJECTS="$REACTOR_PATH/lf_federate.bc $REACTOR_PATH/$LF_MAIN/Dst.bc $REACTOR_PATH/lf_start.bc" popd mkdir -p $BIN_DIR + patmos-clang main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a \ -o $BIN_DIR/$LF_MAIN patemu $BIN_DIR/$LF_MAIN + diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt index a82221cb8..2804ddc39 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcFederatedProjectTemplateGenerator.kt @@ -146,25 +146,21 @@ class UcFederatedTemplateGenerator( |OBJ_DIR = $(CURDIR)/obj |OUTPUT = $(BIN_DIR)/$(LF_MAIN).a |# OBJECTS = $(patsubst %.c,$(OBJ_DIR)/%.o,$(SOURCES)) - |OBJECTS = $(SOURCES:.c=.bc) + |OBJECTS ?= $(SOURCES:.c=.bc) + |FILTER_OUT ?= "" | |all: $(OUTPUT) - | $(info Building $(LF_MAIN) federate $(LF_FED)) - | $(info Output directory: $(BIN_DIR)) - | $(info Output binary: $(OUTPUT)) - | $(info Sources: $(SOURCES)) - | $(info Compiler: $(CC)) - | $(info Compiler flags: $(CFLAGS)) | |# Build rule |$(OUTPUT): $(OBJECTS) - | mkdir -p $(BIN_DIR) - | $(CC) -c $(SOURCES) $(CFLAGS) - | llvm-ar rcs $@ $(OBJECTS) + | @echo "BUILDING $(notdir $@) from $^ except $(FILTER_OUT)" + | mkdir -p $(BIN_DIR) + | llvm-ar rcsv $@ $(filter-out $(FILTER_OUT), $(OBJECTS)); | |%.bc: %.c + | @echo "$(notdir $^) COMPILED TO $(notdir $@)" | mkdir -p $(OBJ_DIR) - | $(CC) -emit-llvm -c $< -o $@ $(CFLAGS) + | $(CC) -emit-llvm -c $^ -o $@ $(CFLAGS) | |# Clean rule |clean: From 00acbd5a469d353118c8342256953b006a581a2a Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Wed, 2 Jul 2025 13:32:51 +0200 Subject: [PATCH 11/28] Patmos and S4NoC 11: compiled --- examples/patmos/s4noc_fed_lf/build.sh | 16 +++++-- examples/patmos/s4noc_fed_lf/main.c | 44 ++++++++++++++++++- .../patmos/s4noc_fed_lf/src/S4NoCFedLF.lf | 2 +- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index 4b334723a..8baf60512 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -2,7 +2,7 @@ LF_MAIN=S4NoCFedLF BIN_DIR=bin # Generate configuration templates -rm -rf $LF_MAIN +rm -rf $LF_MAIN $BIN_DIR $REACTOR_UC_PATH/lfc/bin/lfc-dev --gen-fed-templates src/$LF_MAIN.lf @@ -14,16 +14,24 @@ popd # Generate and build r2 sources pushd ./$LF_MAIN/r2 - REACTOR_PATH=$(pwd)/src-gen/S4NoCFedLF/r2 + REACTOR_PATH=$(pwd)/src-gen/$LF_MAIN/r2 ./run_lfc.sh + sed -i 's/_lf_environment/_lf_environment_2/g' $REACTOR_PATH/lf_start.c - # make all FILTER_OUT="%unity.bc %action.bc %builtin_triggers.bc %clock_synchronization.bc %connection.bc %environment.bc %event.bc %federated.bc %logging.bc %network_channel.bc %physical_clock.bc %platform.bc %port.bc %queues.bc %reaction.bc %reactor.bc %scheduler.bc %serialization.bc %startup_coordinator.bc %tag.bc %timer.bc %trigger.bc %util.bc %pb_common.bc %pb_decode.bc %pb_encode.bc %message.pb.bc" + sed -i 's/lf_exit/lf_exit_2/g' $REACTOR_PATH/lf_start.c + sed -i 's/lf_start/lf_start_2/g' $REACTOR_PATH/lf_start.c + sed -i 's/(Federate/(Federate2/g' $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c + sed -i 's/FederateStartupCoordinator/Federate2StartupCoordinator/g' $REACTOR_PATH/lf_federate.h + sed -i 's/FederateClockSynchronization/Federate2ClockSynchronization/g' $REACTOR_PATH/lf_federate.h + sed -i 's/Reactor_S4NoCFedLF/Reactor_S4NoCFedLF_2/g' $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c + sed -i 's/S4NoCFedLF_r1/S4NoCFedLF_r1_2/g' $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c + make all OBJECTS="$REACTOR_PATH/lf_federate.bc $REACTOR_PATH/$LF_MAIN/Dst.bc $REACTOR_PATH/lf_start.bc" popd mkdir -p $BIN_DIR -patmos-clang main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a \ +patmos-clang -v -O1 main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a \ -o $BIN_DIR/$LF_MAIN patemu $BIN_DIR/$LF_MAIN diff --git a/examples/patmos/s4noc_fed_lf/main.c b/examples/patmos/s4noc_fed_lf/main.c index 971f78904..0952c1509 100644 --- a/examples/patmos/s4noc_fed_lf/main.c +++ b/examples/patmos/s4noc_fed_lf/main.c @@ -1,3 +1,43 @@ +#include +#include + +#include "S4NoCFedLF/r1/src-gen/S4NoCFedLF/r1/lf_start.h" +// #include "S4NoCFedLF/r1/src-gen/S4NoCFedLF/r2/lf_start.h" +// #include "S4NoCFedLF/r2/src-gen/S4NoCFedLF/r1/lf_start.h" +#include "S4NoCFedLF/r2/src-gen/S4NoCFedLF/r2/lf_start.h" + + +void* f1_thread(void* arg) { + printf("Starting federate 1 on core/thread 1\n"); + lf_start(); + return NULL; +} + +void* f2_thread(void* arg) { + printf("Starting federate 2 on core/thread 2\n"); + lf_start_2(); + return NULL; +} + int main(void) { - return 0; -} \ No newline at end of file + pthread_t thread1, thread2; + printf("Starting S4NOC Federated LF Example\n"); + + // Create threads for each federate + pthread_create(&thread1, NULL, f1_thread, NULL); + pthread_create(&thread2, NULL, f2_thread, NULL); + + printf("Threads created for federates.\n"); + + // Wait for both federates to finish + pthread_join(thread1, NULL); + pthread_join(thread2, NULL); + + printf("All federates finished.\n"); + return 0; +} + +// int main(void) { +// printf("Starting S4NOC Federated LF Example\n"); +// return 0; +// } \ No newline at end of file diff --git a/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf b/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf index 98fdd40f1..fe3978bca 100644 --- a/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf +++ b/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf @@ -1,6 +1,6 @@ target uC { platform: PATMOS, - timeout: 1sec + timeout: 10 sec } reactor Src(id: int = 0) { From 60fed357d2df35560ed02a55512415a1b960f13a Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 29 Jul 2025 13:20:30 +0200 Subject: [PATCH 12/28] stuck at receive --- examples/patmos/s4noc_fed_lf/build.sh | 15 +++--------- examples/patmos/s4noc_fed_lf/main.c | 9 +------ .../patmos/s4noc_fed_lf/src/S4NoCFedLF.lf | 5 ++-- src/platform/patmos/s4noc_channel.c | 24 +++++++++---------- .../patmos/s4noc_channel_test/Makefile | 2 +- .../platform/patmos/s4noc_channel_test/main.c | 2 +- 6 files changed, 20 insertions(+), 37 deletions(-) diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index 8baf60512..aa2b06b04 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -16,22 +16,13 @@ popd pushd ./$LF_MAIN/r2 REACTOR_PATH=$(pwd)/src-gen/$LF_MAIN/r2 ./run_lfc.sh - - sed -i 's/_lf_environment/_lf_environment_2/g' $REACTOR_PATH/lf_start.c - sed -i 's/lf_exit/lf_exit_2/g' $REACTOR_PATH/lf_start.c - sed -i 's/lf_start/lf_start_2/g' $REACTOR_PATH/lf_start.c - sed -i 's/(Federate/(Federate2/g' $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c - sed -i 's/FederateStartupCoordinator/Federate2StartupCoordinator/g' $REACTOR_PATH/lf_federate.h - sed -i 's/FederateClockSynchronization/Federate2ClockSynchronization/g' $REACTOR_PATH/lf_federate.h - sed -i 's/Reactor_S4NoCFedLF/Reactor_S4NoCFedLF_2/g' $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c - sed -i 's/S4NoCFedLF_r1/S4NoCFedLF_r1_2/g' $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c - + sed -i 's/_lf_environment/_lf_environment_2/g; s/lf_exit/lf_exit_2/g; s/lf_start/lf_start_2/g' $REACTOR_PATH/lf_start.c + sed -i 's/(Federate/(Federate2/g; s/FederateStartupCoordinator/Federate2StartupCoordinator/g; s/FederateClockSynchronization/Federate2ClockSynchronization/g; s/Reactor_S4NoCFedLF/Reactor_S4NoCFedLF_2/g; s/S4NoCFedLF_r1/S4NoCFedLF_r1_2/g' $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c make all OBJECTS="$REACTOR_PATH/lf_federate.bc $REACTOR_PATH/$LF_MAIN/Dst.bc $REACTOR_PATH/lf_start.bc" popd mkdir -p $BIN_DIR -patmos-clang -v -O1 main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a \ - -o $BIN_DIR/$LF_MAIN +patmos-clang -O2 -Wall -Wextra main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a -o $BIN_DIR/$LF_MAIN patemu $BIN_DIR/$LF_MAIN diff --git a/examples/patmos/s4noc_fed_lf/main.c b/examples/patmos/s4noc_fed_lf/main.c index 0952c1509..408c31b0f 100644 --- a/examples/patmos/s4noc_fed_lf/main.c +++ b/examples/patmos/s4noc_fed_lf/main.c @@ -2,8 +2,6 @@ #include #include "S4NoCFedLF/r1/src-gen/S4NoCFedLF/r1/lf_start.h" -// #include "S4NoCFedLF/r1/src-gen/S4NoCFedLF/r2/lf_start.h" -// #include "S4NoCFedLF/r2/src-gen/S4NoCFedLF/r1/lf_start.h" #include "S4NoCFedLF/r2/src-gen/S4NoCFedLF/r2/lf_start.h" @@ -35,9 +33,4 @@ int main(void) { printf("All federates finished.\n"); return 0; -} - -// int main(void) { -// printf("Starting S4NOC Federated LF Example\n"); -// return 0; -// } \ No newline at end of file +} \ No newline at end of file diff --git a/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf b/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf index fe3978bca..6d0218e03 100644 --- a/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf +++ b/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf @@ -1,6 +1,6 @@ target uC { platform: PATMOS, - timeout: 10 sec + timeout: 20 sec } reactor Src(id: int = 0) { @@ -33,12 +33,11 @@ reactor Dst { } federated reactor { - @interface_s4noc(core=0) + @interface_s4noc(core=2) r1 = new Src(id=42) @interface_s4noc(core=1) r2 = new Dst() - // @link(left="0", right="1") r1.out -> r2.in } diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 003bdbe52..91ae63e31 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -37,12 +37,13 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); + // S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking called with message: %p", message); if (self->state == NETWORK_CHANNEL_STATE_CONNECTED) { int message_size = serialize_to_protobuf(message, self->write_buffer + 4, S4NOC_CHANNEL_BUFFERSIZE - 4); *((int *)self->write_buffer) = message_size; - + S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking: message size: ((%d)).", message_size); int total_size = message_size + 4; *s4noc_dest = self->destination_core; int bytes_send = 0; @@ -50,7 +51,7 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con *s4noc_data = ((int *)self->write_buffer)[bytes_send / 4]; bytes_send += 4; } - S4NOC_CHANNEL_DEBUG("Sent %d bytes", bytes_send); + S4NOC_CHANNEL_DEBUG("Sent ((%d)) bytes", bytes_send); return LF_OK; } else { return LF_ERR; @@ -61,7 +62,7 @@ static void S4NOCPollChannel_register_receive_callback(NetworkChannel *untyped_s void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *msg), FederatedConnectionBundle *conn) { - S4NOC_CHANNEL_INFO("Register receive callback at %p", receive_callback); + // S4NOC_CHANNEL_INFO("Register receive callback at %p", receive_callback); S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; self->receive_callback = receive_callback; @@ -70,43 +71,42 @@ static void S4NOCPollChannel_register_receive_callback(NetworkChannel *untyped_s void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; - S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll called"); + // S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll called"); volatile _IODEV int *s4noc_status = (volatile _IODEV int *)PATMOS_IO_S4NOC; volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_source = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); if (((*s4noc_status) & 0x02) == 0) { - S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: No data available"); + S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: No data is available"); //if i remove it platform-test doesn't work return; } int value = *s4noc_data; int source = *s4noc_source; - S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: Received value 0x%08x (%c%c%c%c) from source %d", value, - ((char *)&value)[0], ((char *)&value)[1], ((char *)&value)[2], ((char *)&value)[3], source); + S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: Received data 0x%08x (%c%c%c%c) from source %d", value, ((char *)&value)[0], ((char *)&value)[1], ((char *)&value)[2], ((char *)&value)[3], source); S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[source][get_cpuid()]; // Get the receive channel for the source core ((int *)receive_channel->receive_buffer)[receive_channel->receive_buffer_index / 4] = value; receive_channel->receive_buffer_index += 4; - S4NOC_CHANNEL_DEBUG("receive_buffer_index %d", receive_channel->receive_buffer_index); + S4NOC_CHANNEL_DEBUG("receive_buffer_index ((%d))", receive_channel->receive_buffer_index); unsigned int expected_message_size = *((int *)receive_channel->receive_buffer); - S4NOC_CHANNEL_DEBUG("Expected message size: %d", expected_message_size); + S4NOC_CHANNEL_DEBUG("Expected message size: ((%d))", expected_message_size); if (receive_channel->receive_buffer_index >= expected_message_size + 4) { int bytes_left = deserialize_from_protobuf(&receive_channel->output, receive_channel->receive_buffer + 4, // skip the 4-byte size header expected_message_size // only the message payload ); - S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize: %d", bytes_left); + // S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize: %d", bytes_left); if (bytes_left >= 0) { receive_channel->receive_buffer_index = bytes_left; if (receive_channel->receive_callback != NULL) { - S4NOC_CHANNEL_DEBUG("calling user callback at %p!", receive_channel->receive_callback); + // S4NOC_CHANNEL_DEBUG("calling user callback at %p!", receive_channel->receive_callback); receive_channel->receive_callback(self->federated_connection, &receive_channel->output); } else { - S4NOC_CHANNEL_WARN("No receive callback registered, dropping message"); + // S4NOC_CHANNEL_WARN("No receive callback registered, dropping message"); } } } diff --git a/test/platform/patmos/s4noc_channel_test/Makefile b/test/platform/patmos/s4noc_channel_test/Makefile index aef25935d..30f214669 100644 --- a/test/platform/patmos/s4noc_channel_test/Makefile +++ b/test/platform/patmos/s4noc_channel_test/Makefile @@ -9,7 +9,7 @@ BUILD_DIR = $(CURDIR)/build # Source files SOURCES += $(SRC_DIR)/$(APP).c -CFLAGS += -DLF_LOG_LEVEL_ALL=LF_LOG_LEVEL_INFO +CFLAGS += -DLF_LOG_LEVEL_ALL=LF_LOG_LEVEL_DEBUG # Output binary OUTPUT = $(BUILD_DIR)/$(APP).elf diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index 27ce42d3b..4a20ba8be 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -67,7 +67,7 @@ void send_message(void) { const char *message = MESSAGE_CONTENT; memcpy(port_message->payload.bytes, message, sizeof(MESSAGE_CONTENT)); // NOLINT port_message->payload.size = sizeof(MESSAGE_CONTENT); - LF_INFO(NET, "Sender: Sending message with connection number %i and content %s\n", port_message->conn_id, (char *)port_message->payload.bytes); + // LF_INFO(NET, "Sender: Sending message with connection number %i and content %s\n", port_message->conn_id, (char *)port_message->payload.bytes); TEST_ASSERT_OK(sender->send_blocking(sender, &msg)); } From d2a973135c7ec39624ac8d8eedad90887e3cf3aa Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 14 Aug 2025 15:40:27 +0200 Subject: [PATCH 13/28] Recieves with long delay and lacks cb --- .../org/lflang/generator/uc/UcNetworkChannel.kt | 7 +++---- make/patmos/patmos.mk | 3 ++- src/platform/patmos/patmos.c | 12 +++--------- src/platform/patmos/s4noc_channel.c | 9 ++++++--- src/schedulers/dynamic/scheduler.c | 1 + test/platform/patmos/s4noc_channel_test/Makefile | 2 -- test/platform/patmos/s4noc_channel_test/main.c | 2 +- 7 files changed, 16 insertions(+), 20 deletions(-) diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt index d9dcd0185..08fed9414 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt @@ -398,16 +398,15 @@ class UcCoapUdpIpChannel( class UcS4NocChannel( src: UcS4NocEndpoint, dest: UcS4NocEndpoint, - serverLhs: Boolean = true, -) : UcNetworkChannel(S4NOC, src, dest, serverLhs) { +) : UcNetworkChannel(S4NOC, src, dest, false) { private val srcS4Noc = src private val destS4Noc = dest override fun generateChannelCtorSrc() = - "S4NOCPollChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.core else destS4Noc.core});" + "S4NOCPollChannel_ctor(&self->channel, ${srcS4Noc.core});" override fun generateChannelCtorDest() = - "S4NOCPollChannel_ctor(&self->channel, ${if (serverLhs) srcS4Noc.core else destS4Noc.core});" + "S4NOCPollChannel_ctor(&self->channel, ${destS4Noc.core});" override val codeType: String get() = "S4NOCPollChannel" diff --git a/make/patmos/patmos.mk b/make/patmos/patmos.mk index 972dc63fc..e4b646ad5 100644 --- a/make/patmos/patmos.mk +++ b/make/patmos/patmos.mk @@ -34,4 +34,5 @@ CFLAGS += -Wall -Wextra CFLAGS += -DPLATFORM_PATMOS CFLAGS += -DNETWORK_CHANNEL_S4NOC CFLAGS += -DSCHEDULER_DYNAMIC -CFLAGS += -DFEDERATED \ No newline at end of file +CFLAGS += -DFEDERATED +CFLAGS += -DLF_LOG_LEVEL_ALL=LF_LOG_LEVEL_DEBUG \ No newline at end of file diff --git a/src/platform/patmos/patmos.c b/src/platform/patmos/patmos.c index 0b6b48e87..77523506f 100644 --- a/src/platform/patmos/patmos.c +++ b/src/platform/patmos/patmos.c @@ -3,6 +3,7 @@ #include #include #include +#include "reactor-uc/logging.h" #include #include @@ -20,21 +21,13 @@ instant_t PlatformPatmos_get_physical_time(Platform *super) { lf_ret_t PlatformPatmos_wait_until_interruptible(Platform *super, instant_t wakeup_time) { PlatformPatmos *self = (PlatformPatmos *)super; - self->async_event = false; instant_t now = super->get_physical_time(super); // Do busy sleep do { now = super->get_physical_time(super); - } while ((now < wakeup_time) && !self->async_event); - - if (self->async_event) { - self->async_event = false; - return LF_ERR; - } else { - return LF_OK; - } + } while (now < wakeup_time); interval_t sleep_duration = wakeup_time - super->get_physical_time(super); if (sleep_duration < 0) { @@ -96,6 +89,7 @@ void Platform_ctor(Platform *super) { super->wait_until_interruptible = PlatformPatmos_wait_until_interruptible; super->notify = PlatformPatmos_notify; self->num_nested_critical_sections = 0; + LF_DEBUG(PLATFORM, "PlatformPatmos initialized"); } Platform *Platform_new(void) { diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 91ae63e31..40204cc59 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -45,6 +45,8 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con *((int *)self->write_buffer) = message_size; S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking: message size: ((%d)).", message_size); int total_size = message_size + 4; + S4NOC_CHANNEL_DEBUG("Total size to send: ((%d))", total_size); + *s4noc_dest = self->destination_core; int bytes_send = 0; while (bytes_send < total_size) { @@ -62,7 +64,7 @@ static void S4NOCPollChannel_register_receive_callback(NetworkChannel *untyped_s void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *msg), FederatedConnectionBundle *conn) { - // S4NOC_CHANNEL_INFO("Register receive callback at %p", receive_callback); + S4NOC_CHANNEL_INFO("Register receive callback at %p", receive_callback); S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; self->receive_callback = receive_callback; @@ -98,15 +100,16 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { receive_channel->receive_buffer + 4, // skip the 4-byte size header expected_message_size // only the message payload ); + // bytes_left = ((bytes_left / 4)+1) * 4; // S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize: %d", bytes_left); if (bytes_left >= 0) { receive_channel->receive_buffer_index = bytes_left; if (receive_channel->receive_callback != NULL) { - // S4NOC_CHANNEL_DEBUG("calling user callback at %p!", receive_channel->receive_callback); + S4NOC_CHANNEL_DEBUG("calling user callback at %p!", receive_channel->receive_callback); receive_channel->receive_callback(self->federated_connection, &receive_channel->output); } else { - // S4NOC_CHANNEL_WARN("No receive callback registered, dropping message"); + S4NOC_CHANNEL_WARN("No receive callback registered, dropping message"); } } } diff --git a/src/schedulers/dynamic/scheduler.c b/src/schedulers/dynamic/scheduler.c index fe7831802..dc50ea316 100644 --- a/src/schedulers/dynamic/scheduler.c +++ b/src/schedulers/dynamic/scheduler.c @@ -268,6 +268,7 @@ void Scheduler_run(Scheduler *untyped_self) { } if (env->poll_network_channels) { + LF_DEBUG(SCHED, "Polling network channels"); env->poll_network_channels(env); } diff --git a/test/platform/patmos/s4noc_channel_test/Makefile b/test/platform/patmos/s4noc_channel_test/Makefile index 30f214669..ea4ae5f34 100644 --- a/test/platform/patmos/s4noc_channel_test/Makefile +++ b/test/platform/patmos/s4noc_channel_test/Makefile @@ -9,8 +9,6 @@ BUILD_DIR = $(CURDIR)/build # Source files SOURCES += $(SRC_DIR)/$(APP).c -CFLAGS += -DLF_LOG_LEVEL_ALL=LF_LOG_LEVEL_DEBUG - # Output binary OUTPUT = $(BUILD_DIR)/$(APP).elf all : $(OUTPUT) diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index 4a20ba8be..744c56ec5 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -8,7 +8,7 @@ #define MESSAGE_CONNECTION_ID 42 #define SOURCE_CORE 1 #define DESTINATION_CORE 2 -#define MAX_TRIES 10 +#define MAX_TRIES 20 Reactor parent; FederatedEnvironment fed_env; From 481a419f3e0ca230cbf4e0062f1228a8af12512e Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 18 Aug 2025 15:13:59 +0200 Subject: [PATCH 14/28] fpga config and download --- examples/patmos/s4noc_fed_lf/build.sh | 15 ++++++++++++++- .../lflang/generator/uc/UcNetworkChannel.kt | 3 +-- src/platform/patmos/patmos.c | 5 ++++- src/platform/patmos/s4noc_channel.c | 12 ++++++++---- test/platform/patmos/s4noc_channel_test/run.sh | 18 ++++++++++++++++-- 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index aa2b06b04..8ec2922dc 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -24,5 +24,18 @@ popd mkdir -p $BIN_DIR patmos-clang -O2 -Wall -Wextra main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a -o $BIN_DIR/$LF_MAIN -patemu $BIN_DIR/$LF_MAIN +read -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action +action=${action:-e} +if [[ "$action" == "e" ]]; then + patemu $BIN_DIR/$LF_MAIN +elif [[ "$action" == "f" ]]; then + if jtagconfig | grep -q "USB-Blaster"; then + mv $BIN_DIR/$LF_MAIN ~/t-crest/patmos/tmp/$LF_MAIN.elf + make -C ~/t-crest/patmos APP=$LF_MAIN config download + else + echo "JTAG not connected. Please connect USB-Blaster." + fi +else + echo "Invalid option. Please choose 'e' for emulate or 'f' for fpga." +fi diff --git a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt index 08fed9414..64ae6c660 100644 --- a/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt +++ b/lfc/core/src/main/kotlin/org/lflang/generator/uc/UcNetworkChannel.kt @@ -402,8 +402,7 @@ class UcS4NocChannel( private val srcS4Noc = src private val destS4Noc = dest - override fun generateChannelCtorSrc() = - "S4NOCPollChannel_ctor(&self->channel, ${srcS4Noc.core});" + override fun generateChannelCtorSrc() = "S4NOCPollChannel_ctor(&self->channel, ${srcS4Noc.core});" override fun generateChannelCtorDest() = "S4NOCPollChannel_ctor(&self->channel, ${destS4Noc.core});" diff --git a/src/platform/patmos/patmos.c b/src/platform/patmos/patmos.c index 77523506f..e1ece6440 100644 --- a/src/platform/patmos/patmos.c +++ b/src/platform/patmos/patmos.c @@ -23,6 +23,7 @@ lf_ret_t PlatformPatmos_wait_until_interruptible(Platform *super, instant_t wake PlatformPatmos *self = (PlatformPatmos *)super; instant_t now = super->get_physical_time(super); + LF_DEBUG(PLATFORM, "PlatformPatmos_wait_until_interruptible: now: %llu sleeping until %llu", now, wakeup_time); // Do busy sleep do { @@ -44,6 +45,7 @@ lf_ret_t PlatformPatmos_wait_until(Platform *super, instant_t wakeup_time) { } instant_t now = super->get_physical_time(super); + LF_DEBUG(PLATFORM, "PlatformPatmos_wait_until: now: %llu sleeping until %llu", now, wakeup_time); // Do busy sleep do { @@ -59,11 +61,12 @@ lf_ret_t PlatformPatmos_wait_for(Platform *super, interval_t duration) { instant_t now = super->get_physical_time(super); instant_t wakeup = now + duration; + LF_DEBUG(PLATFORM, "PlatformPatmos_wait_for: now: %llu sleeping for %llu", now, duration); // Do busy sleep do { now = super->get_physical_time(super); - } while ((now < wakeup)); + } while (now < wakeup); return LF_OK; } diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 40204cc59..58ac6f8c6 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -86,9 +86,10 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { int value = *s4noc_data; int source = *s4noc_source; - S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: Received data 0x%08x (%c%c%c%c) from source %d", value, ((char *)&value)[0], ((char *)&value)[1], ((char *)&value)[2], ((char *)&value)[3], source); - S4NOCPollChannel *receive_channel = - s4noc_global_state.core_channels[source][get_cpuid()]; // Get the receive channel for the source core + S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: Received data 0x%08x (%c%c%c%c) from source %d", value, + ((char *)&value)[0], ((char *)&value)[1], ((char *)&value)[2], ((char *)&value)[3], source); + // Get the receive channel for the source core + S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[source][get_cpuid()]; ((int *)receive_channel->receive_buffer)[receive_channel->receive_buffer_index / 4] = value; receive_channel->receive_buffer_index += 4; @@ -116,7 +117,7 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { } void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core) { - assert(self != NULL); + assert(self != NULL); self->super.super.mode = NETWORK_CHANNEL_MODE_POLLED; self->super.super.expected_connect_duration = SEC(0); @@ -135,4 +136,7 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core self->federated_connection = NULL; self->state = NETWORK_CHANNEL_STATE_CONNECTED; self->destination_core = destination_core; + memset(self->receive_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); + memset(self->write_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); + } diff --git a/test/platform/patmos/s4noc_channel_test/run.sh b/test/platform/patmos/s4noc_channel_test/run.sh index 876570ec8..b1a4a6c30 100755 --- a/test/platform/patmos/s4noc_channel_test/run.sh +++ b/test/platform/patmos/s4noc_channel_test/run.sh @@ -1,7 +1,21 @@ #!/bin/bash - +LF_MAIN=main +BIN_DIR=./build # Make test make clean make all -patemu ./build/*.elf +read -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action +action=${action:-e} +if [[ "$action" == "e" ]]; then + patemu $BIN_DIR/$LF_MAIN.elf +elif [[ "$action" == "f" ]]; then + if jtagconfig | grep -q "USB-Blaster"; then + mv $BIN_DIR/$LF_MAIN.elf ~/t-crest/patmos/tmp/$LF_MAIN.elf + make -C ~/t-crest/patmos APP=$LF_MAIN config download + else + echo "JTAG not connected. Please connect USB-Blaster." + fi +else + echo "Invalid option. Please choose 'e' for emulate or 'f' for fpga." +fi From 7c460afbb7857d4007edbc1391f5bd00539043ce Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 26 Aug 2025 15:05:55 +0200 Subject: [PATCH 15/28] failed on fpga solved --- examples/patmos/s4noc_fed_lf/build.sh | 2 +- test/platform/patmos/s4noc_channel_test/main.c | 2 ++ test/platform/patmos/s4noc_channel_test/run.sh | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index 8ec2922dc..8e3d79014 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -24,7 +24,7 @@ popd mkdir -p $BIN_DIR patmos-clang -O2 -Wall -Wextra main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a -o $BIN_DIR/$LF_MAIN -read -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action +read -n 1 -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action action=${action:-e} if [[ "$action" == "e" ]]; then patemu $BIN_DIR/$LF_MAIN diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index 744c56ec5..15c8895d7 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -60,11 +60,13 @@ void receiver_callback_handler(FederatedConnectionBundle *self, const FederateMe void send_message(void) { FederateMessage msg; + memset(&msg, 0, sizeof(msg)); msg.which_message = FederateMessage_tagged_message_tag; TaggedMessage *port_message = &msg.message.tagged_message; port_message->conn_id = MESSAGE_CONNECTION_ID; const char *message = MESSAGE_CONTENT; + memset(port_message->payload.bytes, 0, sizeof(port_message->payload.bytes)); memcpy(port_message->payload.bytes, message, sizeof(MESSAGE_CONTENT)); // NOLINT port_message->payload.size = sizeof(MESSAGE_CONTENT); // LF_INFO(NET, "Sender: Sending message with connection number %i and content %s\n", port_message->conn_id, (char *)port_message->payload.bytes); diff --git a/test/platform/patmos/s4noc_channel_test/run.sh b/test/platform/patmos/s4noc_channel_test/run.sh index b1a4a6c30..c1c3e9990 100755 --- a/test/platform/patmos/s4noc_channel_test/run.sh +++ b/test/platform/patmos/s4noc_channel_test/run.sh @@ -4,7 +4,7 @@ BIN_DIR=./build # Make test make clean make all -read -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action +read -n 1 -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action action=${action:-e} if [[ "$action" == "e" ]]; then patemu $BIN_DIR/$LF_MAIN.elf From e39efaac64800e9e494df72a75d4e9ecf2aa09d5 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 28 Aug 2025 19:53:29 +0200 Subject: [PATCH 16/28] global state are set in channel --- src/platform/patmos/s4noc_channel.c | 3 ++- test/platform/patmos/s4noc_channel_test/main.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 58ac6f8c6..69e7cc860 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -138,5 +138,6 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core self->destination_core = destination_core; memset(self->receive_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); memset(self->write_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); - + unsigned int src_core = get_cpuid(); + s4noc_global_state.core_channels[destination_core][src_core] = self; } diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index 15c8895d7..36a2c81c3 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -30,13 +30,16 @@ void setUp(void) { FederatedEnvironment_ctor(&fed_env, &parent, NULL, false, net_bundles, 2, &startup_coordinator, NULL); /* init channel */ + LF_INFO(NET,"init channel"); S4NOCPollChannel_ctor(&sender_channel, DESTINATION_CORE); S4NOCPollChannel_ctor(&receiver_channel, SOURCE_CORE); /* init bundles */ + LF_INFO(NET,"init bundles"); FederatedConnectionBundle_ctor(&sender_bundle, &parent, sender, NULL, NULL, 0, NULL, NULL, 0, 0); FederatedConnectionBundle_ctor(&receiver_bundle, &parent, receiver, NULL, NULL, 0, NULL, NULL, 0, 0); + LF_INFO(NET,"init global state"); s4noc_global_state.core_channels[SOURCE_CORE][DESTINATION_CORE] = &receiver_channel; s4noc_global_state.core_channels[DESTINATION_CORE][SOURCE_CORE] = &sender_channel; From 68984ba58de39e70221ff656adf1844ceac3af13 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 1 Sep 2025 16:05:27 +0200 Subject: [PATCH 17/28] loop in build.sh --- examples/patmos/s4noc_fed_lf/build.sh | 28 +++++++++++++------ .../patmos/s4noc_fed_lf/src/S4NoCFedLF.lf | 9 +++--- src/platform/patmos/s4noc_channel.c | 2 +- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index 8e3d79014..91f99fed5 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -1,6 +1,7 @@ #!/bin/bash LF_MAIN=S4NoCFedLF BIN_DIR=bin +CC=patmos-clang # Generate configuration templates rm -rf $LF_MAIN $BIN_DIR $REACTOR_UC_PATH/lfc/bin/lfc-dev --gen-fed-templates src/$LF_MAIN.lf @@ -12,18 +13,27 @@ pushd ./$LF_MAIN/r1 make all popd -# Generate and build r2 sources -pushd ./$LF_MAIN/r2 - REACTOR_PATH=$(pwd)/src-gen/$LF_MAIN/r2 - ./run_lfc.sh - sed -i 's/_lf_environment/_lf_environment_2/g; s/lf_exit/lf_exit_2/g; s/lf_start/lf_start_2/g' $REACTOR_PATH/lf_start.c - sed -i 's/(Federate/(Federate2/g; s/FederateStartupCoordinator/Federate2StartupCoordinator/g; s/FederateClockSynchronization/Federate2ClockSynchronization/g; s/Reactor_S4NoCFedLF/Reactor_S4NoCFedLF_2/g; s/S4NoCFedLF_r1/S4NoCFedLF_r1_2/g' $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c - make all OBJECTS="$REACTOR_PATH/lf_federate.bc $REACTOR_PATH/$LF_MAIN/Dst.bc $REACTOR_PATH/lf_start.bc" -popd +N=2 +# Generate and build other sources +for i in $(seq 2 $N); do + pushd ./$LF_MAIN/r$i + REACTOR_PATH=$(pwd)/src-gen/$LF_MAIN/r$i + ./run_lfc.sh + sed -i "s/_lf_environment/_lf_environment_$i/g; s/lf_exit/lf_exit_$i/g; s/lf_start/lf_start_$i/g" $REACTOR_PATH/lf_start.c + sed -i "s/(Federate/(Federate$i/g; s/FederateStartup/Federate${i}Startup/g; s/FederateClock/Federate${i}Clock/g; s/Reactor_${LF_MAIN}/Reactor_${LF_MAIN}_$i/g; s/${LF_MAIN}_r1/${LF_MAIN}_r1_$i/g" $REACTOR_PATH/lf_federate.h $REACTOR_PATH/lf_federate.c + make all OBJECTS="$REACTOR_PATH/lf_federate.bc $REACTOR_PATH/$LF_MAIN/Dst.bc $REACTOR_PATH/lf_start.bc" + popd +done mkdir -p $BIN_DIR -patmos-clang -O2 -Wall -Wextra main.c ./$LF_MAIN/r1/bin/$LF_MAIN.a ./$LF_MAIN/r2/bin/$LF_MAIN.a -o $BIN_DIR/$LF_MAIN +A_FILES="" +for i in $(seq 1 $N); do + A_FILES="$A_FILES ./$LF_MAIN/r$i/bin/$LF_MAIN.a" +done + +$CC -O2 -Wall -Wextra main.c $A_FILES -o $BIN_DIR/$LF_MAIN + read -n 1 -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action action=${action:-e} if [[ "$action" == "e" ]]; then diff --git a/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf b/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf index 6d0218e03..9606eec89 100644 --- a/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf +++ b/examples/patmos/s4noc_fed_lf/src/S4NoCFedLF.lf @@ -1,13 +1,12 @@ target uC { - platform: PATMOS, - timeout: 20 sec + platform: PATMOS } reactor Src(id: int = 0) { output out: int reaction(startup) -> out{= - printf("Hello from Src!\n"); + printf("Hello Patmos from Src!\n"); lf_set(out, self->id); =} } @@ -17,11 +16,11 @@ reactor Dst { state check: bool = false reaction(startup) {= - printf("Hello from Dst!\n"); + printf("Hello Patmos from Dst!\n"); =} reaction(in) {= - printf("Received %d from Src\n", in->value); + printf("Patmos:Received %d from Src\n", in->value); validate(in->value == 42); self->check = true; env->request_shutdown(env); diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 69e7cc860..72b1f3f18 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -80,7 +80,7 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { volatile _IODEV int *s4noc_source = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); if (((*s4noc_status) & 0x02) == 0) { - S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: No data is available"); //if i remove it platform-test doesn't work + S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: No data is available"); // if i remove it platform-test doesn't work return; } From be2d86ee4672fa72be5b31f9fcfd5bcacbfea6b7 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 2 Sep 2025 15:05:25 +0200 Subject: [PATCH 18/28] main file generator --- examples/patmos/s4noc_fed_lf/build.sh | 4 ++ examples/patmos/s4noc_fed_lf/gen_main.sh | 72 ++++++++++++++++++++++++ examples/patmos/s4noc_fed_lf/main.c | 22 +++----- 3 files changed, 85 insertions(+), 13 deletions(-) create mode 100755 examples/patmos/s4noc_fed_lf/gen_main.sh diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index 91f99fed5..401fe507e 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -1,4 +1,5 @@ #!/bin/bash + LF_MAIN=S4NoCFedLF BIN_DIR=bin CC=patmos-clang @@ -32,6 +33,9 @@ for i in $(seq 1 $N); do A_FILES="$A_FILES ./$LF_MAIN/r$i/bin/$LF_MAIN.a" done +chmod +x ./gen_main.sh +./gen_main.sh N=$N + $CC -O2 -Wall -Wextra main.c $A_FILES -o $BIN_DIR/$LF_MAIN read -n 1 -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action diff --git a/examples/patmos/s4noc_fed_lf/gen_main.sh b/examples/patmos/s4noc_fed_lf/gen_main.sh new file mode 100755 index 000000000..e23326a83 --- /dev/null +++ b/examples/patmos/s4noc_fed_lf/gen_main.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Number of federates +N=2 +rm -rf main.c + +cat >> main.c < +#include + +EOF + +# Generate include headers for each federate +for i in $(seq 1 $N); do +cat >> main.c <> main.c <> main.c <> main.c <> main.c <> main.c <> main.c <> main.c < Date: Tue, 21 Oct 2025 16:45:23 +0200 Subject: [PATCH 19/28] unconnected handling --- examples/patmos/s4noc_fed_lf/build.sh | 3 +- examples/patmos/s4noc_fed_lf/gen_main.sh | 2 + examples/patmos/s4noc_fed_lf/main.c | 2 + .../patmos/s4noc_fed_lf/src/S4NoCFedLF.lf | 10 +- .../platform/patmos/s4noc_channel.h | 2 + src/platform/patmos/s4noc_channel.c | 183 ++++++++++++++++-- src/startup_coordinator.c | 1 + 7 files changed, 179 insertions(+), 24 deletions(-) diff --git a/examples/patmos/s4noc_fed_lf/build.sh b/examples/patmos/s4noc_fed_lf/build.sh index 401fe507e..86a1b741d 100755 --- a/examples/patmos/s4noc_fed_lf/build.sh +++ b/examples/patmos/s4noc_fed_lf/build.sh @@ -38,6 +38,8 @@ chmod +x ./gen_main.sh $CC -O2 -Wall -Wextra main.c $A_FILES -o $BIN_DIR/$LF_MAIN +rm -rf $REACTOR_UC_PATH/external/nanopb/pb_encode.bc $REACTOR_UC_PATH/external/nanopb/pb_decode.bc $REACTOR_UC_PATH/external/nanopb/pb_common.bc $REACTOR_UC_PATH/external/Unity/src/unity.bc + read -n 1 -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action action=${action:-e} if [[ "$action" == "e" ]]; then @@ -52,4 +54,3 @@ elif [[ "$action" == "f" ]]; then else echo "Invalid option. Please choose 'e' for emulate or 'f' for fpga." fi - diff --git a/examples/patmos/s4noc_fed_lf/gen_main.sh b/examples/patmos/s4noc_fed_lf/gen_main.sh index e23326a83..52bff7729 100755 --- a/examples/patmos/s4noc_fed_lf/gen_main.sh +++ b/examples/patmos/s4noc_fed_lf/gen_main.sh @@ -20,6 +20,7 @@ done cat >> main.c <> main.c < out{= - printf("Hello Patmos from Src!\n"); + printf("Hello Patmos from Src!\n"); lf_set(out, self->id); =} } @@ -16,11 +18,11 @@ reactor Dst { state check: bool = false reaction(startup) {= - printf("Hello Patmos from Dst!\n"); + printf("Hello Patmos from Dst!\n"); =} reaction(in) {= - printf("Patmos:Received %d from Src\n", in->value); + printf("Patmos:Received %d from Src\n", in->value); validate(in->value == 42); self->check = true; env->request_shutdown(env); diff --git a/include/reactor-uc/platform/patmos/s4noc_channel.h b/include/reactor-uc/platform/patmos/s4noc_channel.h index f3e173e7b..e460eed61 100644 --- a/include/reactor-uc/platform/patmos/s4noc_channel.h +++ b/include/reactor-uc/platform/patmos/s4noc_channel.h @@ -33,6 +33,8 @@ struct S4NOCPollChannel { FederatedConnectionBundle *federated_connection; void (*receive_callback)(FederatedConnectionBundle *conn, const FederateMessage *message); pthread_t worker_thread; + bool send_response; + bool received_response; }; void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core); diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 72b1f3f18..e348a8939 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -2,23 +2,27 @@ #include "reactor-uc/serialization.h" #include #include +#include +#include #define S4NOC_CHANNEL_ERR(fmt, ...) LF_ERR(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) #define S4NOC_CHANNEL_WARN(fmt, ...) LF_WARN(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) #define S4NOC_CHANNEL_INFO(fmt, ...) LF_INFO(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) #define S4NOC_CHANNEL_DEBUG(fmt, ...) LF_DEBUG(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) -S4NOCGlobalState s4noc_global_state; +#define S4NOC_OPEN_MESSAGE_REQUEST \ + { 0xC0, 0x18, 0x11, 0xC0 } +#define S4NOC_OPEN_MESSAGE_RESPONSE \ + { 0xC0, 0xFF, 0x31, 0xC0 } -static lf_ret_t S4NOCPollChannel_open_connection(NetworkChannel *untyped_self) { - S4NOC_CHANNEL_DEBUG("Open connection"); - (void)untyped_self; - return LF_OK; -} +S4NOCGlobalState s4noc_global_state = {0}; + +void S4NOCPollChannel_poll(NetworkChannel *untyped_self); static void S4NOCPollChannel_close_connection(NetworkChannel *untyped_self) { S4NOC_CHANNEL_DEBUG("Close connection"); - (void)untyped_self; + S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; + self->state = NETWORK_CHANNEL_STATE_CLOSED; } static void S4NOCPollChannel_free(NetworkChannel *untyped_self) { @@ -28,8 +32,111 @@ static void S4NOCPollChannel_free(NetworkChannel *untyped_self) { static bool S4NOCPollChannel_is_connected(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; + volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); + volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); + + if (!self->received_response) { + *s4noc_dest = self->destination_core; + uint8_t connect_message[] = S4NOC_OPEN_MESSAGE_REQUEST; + uint32_t w = 0; + memcpy(&w, connect_message, sizeof(w)); + S4NOC_CHANNEL_DEBUG("Open Connection - Sending ping"); + *s4noc_data = (int)w; + } + + // poll if your channel is disconnected + if (self->state != NETWORK_CHANNEL_STATE_CONNECTED) { + S4NOCPollChannel_poll(untyped_self); + S4NOC_CHANNEL_WARN("Channel is not connected (state=%d)", self->state); + } + + S4NOC_CHANNEL_DEBUG("Network is %s", NetworkChannel_state_to_string(self->state)); + return self->state == NETWORK_CHANNEL_STATE_CONNECTED && self->received_response && self->send_response; +} + +static lf_ret_t S4NOCPollChannel_open_connection(NetworkChannel *untyped_self) { + S4NOC_CHANNEL_DEBUG("Open connection"); + // S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; + // self->state = NETWORK_CHANNEL_STATE_CONNECTED;( + S4NOCPollChannel_is_connected(untyped_self); + return LF_OK; +} + +void printf_msg(char *header, const FederateMessage *message) { + S4NOC_CHANNEL_INFO("%s: FederateMessage type: %d", header, message->which_message); + + if (message->which_message == FederateMessage_clock_sync_msg_tag) { + S4NOC_CHANNEL_INFO("ClockSyncMessage:"); + // ClockSyncMessage + switch (message->message.clock_sync_msg.which_message) { + case ClockSyncMessage_priority_request_tag: + S4NOC_CHANNEL_INFO("ClockPriorityRequest"); + break; + case ClockSyncMessage_priority_tag: + S4NOC_CHANNEL_INFO("ClockPriority: priority = %" PRIu64, + message->message.clock_sync_msg.message.priority.priority); + break; + case ClockSyncMessage_request_sync_tag: + S4NOC_CHANNEL_INFO("RequestSync: seq = %d", message->message.clock_sync_msg.message.request_sync.sequence_number); + break; + case ClockSyncMessage_sync_response_tag: + S4NOC_CHANNEL_INFO("SyncResponse: seq = %d, time = %" PRIu64, + message->message.clock_sync_msg.message.sync_response.sequence_number, + message->message.clock_sync_msg.message.sync_response.time); + break; + case ClockSyncMessage_delay_request_tag: + S4NOC_CHANNEL_INFO("DelayRequest: seq = %d", + message->message.clock_sync_msg.message.delay_request.sequence_number); + break; + case ClockSyncMessage_delay_response_tag: + S4NOC_CHANNEL_INFO("DelayResponse: seq = %d, time = %" PRIu64, + message->message.clock_sync_msg.message.delay_response.sequence_number, + message->message.clock_sync_msg.message.delay_response.time); + break; + case ClockSyncMessage_priority_broadcast_request_tag: + S4NOC_CHANNEL_INFO("ClockPriorityBroadcastRequest"); + break; + default: + S4NOC_CHANNEL_WARN("Unknown ClockSyncMessage type: %d", message->message.clock_sync_msg.which_message); + break; + } + + } else if (message->which_message == FederateMessage_tagged_message_tag) { + // TaggedMessage + S4NOC_CHANNEL_INFO("TaggedMessage: tag = %" PRIu64 ", conn_id = %d", message->message.tagged_message.tag.time, + message->message.tagged_message.conn_id); - return self->state == NETWORK_CHANNEL_STATE_CONNECTED; + } else if (message->which_message == FederateMessage_startup_coordination_tag) { + // StartupCoordination + S4NOC_CHANNEL_INFO("StartupCoordination:"); + switch (message->message.startup_coordination.which_message) { + case StartupCoordination_startup_handshake_request_tag: + S4NOC_CHANNEL_INFO("StartupHandshakeRequest"); + break; + case StartupCoordination_startup_handshake_response_tag: + S4NOC_CHANNEL_INFO("StartupHandshakeResponse: state = %d", + message->message.startup_coordination.message.startup_handshake_response.state); + break; + case StartupCoordination_start_time_proposal_tag: + S4NOC_CHANNEL_INFO("StartTimeProposal: time = %" PRIu64 ", step = %" PRIu32, + message->message.startup_coordination.message.start_time_proposal.time, + message->message.startup_coordination.message.start_time_proposal.step); + break; + case StartupCoordination_start_time_response_tag: + S4NOC_CHANNEL_INFO("StartTimeResponse: time = %" PRIu64 ", federation_start_time = %" PRIu64, + message->message.startup_coordination.message.start_time_response.elapsed_logical_time, + message->message.startup_coordination.message.start_time_response.federation_start_time); + break; + case StartupCoordination_start_time_request_tag: + S4NOC_CHANNEL_INFO("StartTimeRequest"); + break; + default: + S4NOC_CHANNEL_WARN("Unknown StartupCoordination type: %d", message->message.startup_coordination.which_message); + break; + } + } else { + S4NOC_CHANNEL_WARN("Unknown FederateMessage type: %d", message->which_message); + } } static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, const FederateMessage *message) { @@ -37,15 +144,16 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); - // S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking called with message: %p", message); - + S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking from core %d to core %d", get_cpuid(), self->destination_core); if (self->state == NETWORK_CHANNEL_STATE_CONNECTED) { + // Print the FederateMessage type before sending + printf_msg("sending msg type:", message); int message_size = serialize_to_protobuf(message, self->write_buffer + 4, S4NOC_CHANNEL_BUFFERSIZE - 4); *((int *)self->write_buffer) = message_size; - S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking: message size: ((%d)).", message_size); + // S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking: message size: ((%d)).", message_size); int total_size = message_size + 4; - S4NOC_CHANNEL_DEBUG("Total size to send: ((%d))", total_size); + // S4NOC_CHANNEL_DEBUG("Total size to send: ((%d))", total_size); *s4noc_dest = self->destination_core; int bytes_send = 0; @@ -53,7 +161,7 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con *s4noc_data = ((int *)self->write_buffer)[bytes_send / 4]; bytes_send += 4; } - S4NOC_CHANNEL_DEBUG("Sent ((%d)) bytes", bytes_send); + // S4NOC_CHANNEL_DEBUG("Sent ((%d)) bytes", bytes_send); return LF_OK; } else { return LF_ERR; @@ -73,12 +181,36 @@ static void S4NOCPollChannel_register_receive_callback(NetworkChannel *untyped_s void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; - // S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll called"); - volatile _IODEV int *s4noc_status = (volatile _IODEV int *)PATMOS_IO_S4NOC; volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_source = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); + // if unconnected, and s4noc data available, respond. + if ((self->state != NETWORK_CHANNEL_STATE_CONNECTED) && (((*s4noc_status) & 0x02) != 0)) { + uint32_t word = (uint32_t)(*s4noc_data); + uint8_t req_bytes[] = S4NOC_OPEN_MESSAGE_REQUEST; + uint8_t resp_bytes[] = S4NOC_OPEN_MESSAGE_RESPONSE; + uint32_t req_word = 0; + uint32_t resp_word = 0; + memcpy(&req_word, req_bytes, sizeof(req_word)); + memcpy(&resp_word, resp_bytes, sizeof(resp_word)); + S4NOC_CHANNEL_DEBUG("Data available on S4NOC while channel is unconnected. word=0x%08x", word); + if (word == req_word) { + S4NOC_CHANNEL_INFO("Responding to S4NOC open message"); + *s4noc_data = (int)resp_word; + // set destination/source appropriately (hardware doc dependent) + *s4noc_source = self->destination_core; + self->send_response = true; + } else if (word == resp_word) { + S4NOC_CHANNEL_INFO("Received S4NOC open message response"); + self->state = NETWORK_CHANNEL_STATE_CONNECTED; + self->received_response = true; + } + + return; + } + + // Check if data is available on the S4NOC interface if (((*s4noc_status) & 0x02) == 0) { S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: No data is available"); // if i remove it platform-test doesn't work return; @@ -91,21 +223,34 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { // Get the receive channel for the source core S4NOCPollChannel *receive_channel = s4noc_global_state.core_channels[source][get_cpuid()]; + if (receive_channel == NULL) { + S4NOC_CHANNEL_WARN("No receive_channel for source=%d dest=%d - dropping word", source, get_cpuid()); + return; + } + + if (receive_channel->receive_buffer_index + 4 > S4NOC_CHANNEL_BUFFERSIZE) { + S4NOC_CHANNEL_WARN("Receive buffer overflow: dropping message"); + receive_channel->receive_buffer_index = 0; + return; + } + ((int *)receive_channel->receive_buffer)[receive_channel->receive_buffer_index / 4] = value; receive_channel->receive_buffer_index += 4; - S4NOC_CHANNEL_DEBUG("receive_buffer_index ((%d))", receive_channel->receive_buffer_index); + // S4NOC_CHANNEL_DEBUG("receive_buffer_index ((%d))", receive_channel->receive_buffer_index); unsigned int expected_message_size = *((int *)receive_channel->receive_buffer); - S4NOC_CHANNEL_DEBUG("Expected message size: ((%d))", expected_message_size); + // S4NOC_CHANNEL_DEBUG("Expected message size: ((%d))", expected_message_size); if (receive_channel->receive_buffer_index >= expected_message_size + 4) { int bytes_left = deserialize_from_protobuf(&receive_channel->output, receive_channel->receive_buffer + 4, // skip the 4-byte size header expected_message_size // only the message payload ); // bytes_left = ((bytes_left / 4)+1) * 4; - // S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize: %d", bytes_left); + S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize: %d", bytes_left); if (bytes_left >= 0) { receive_channel->receive_buffer_index = bytes_left; + S4NOC_CHANNEL_DEBUG("Message received at core %d from core %d", get_cpuid(), source); + printf_msg("received msg type:", &receive_channel->output); if (receive_channel->receive_callback != NULL) { S4NOC_CHANNEL_DEBUG("calling user callback at %p!", receive_channel->receive_callback); receive_channel->receive_callback(self->federated_connection, &receive_channel->output); @@ -134,7 +279,7 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core self->receive_buffer_index = 0; self->receive_callback = NULL; self->federated_connection = NULL; - self->state = NETWORK_CHANNEL_STATE_CONNECTED; + self->state = NETWORK_CHANNEL_STATE_UNINITIALIZED; self->destination_core = destination_core; memset(self->receive_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); memset(self->write_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); diff --git a/src/startup_coordinator.c b/src/startup_coordinator.c index 54e6eaad7..5773d856c 100644 --- a/src/startup_coordinator.c +++ b/src/startup_coordinator.c @@ -204,6 +204,7 @@ static void StartupCoordinator_handle_startup_handshake_response(StartupCoordina bool all_received = true; for (size_t i = 0; i < self->num_neighbours; i++) { if (!self->neighbor_state[i].handshake_response_received) { + LF_DEBUG(FED, "Handshake response not received from neighbor %zu", i); all_received = false; break; } From 787074405e898c044ca2a1770b9dcdba66e96665 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Wed, 22 Oct 2025 13:11:18 +0200 Subject: [PATCH 20/28] new connectin handling disabled for channel_test --- .../platform/patmos/s4noc_channel.h | 2 +- src/platform/patmos/s4noc_channel.c | 20 ++++++++++++++++--- .../platform/patmos/s4noc_channel_test/main.c | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/reactor-uc/platform/patmos/s4noc_channel.h b/include/reactor-uc/platform/patmos/s4noc_channel.h index e460eed61..1b0df7a89 100644 --- a/include/reactor-uc/platform/patmos/s4noc_channel.h +++ b/include/reactor-uc/platform/patmos/s4noc_channel.h @@ -38,5 +38,5 @@ struct S4NOCPollChannel { }; void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core); - +void S4NOC_set_handle_new_connections(bool enable); #endif diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index e348a8939..4347dd713 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -4,6 +4,7 @@ #include #include #include +#include #define S4NOC_CHANNEL_ERR(fmt, ...) LF_ERR(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) #define S4NOC_CHANNEL_WARN(fmt, ...) LF_WARN(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) @@ -16,6 +17,13 @@ { 0xC0, 0xFF, 0x31, 0xC0 } S4NOCGlobalState s4noc_global_state = {0}; +// Control whether the driver will handle S4NOC "new connection" open/response words +static bool s4noc_handle_new_connections = true; + +// API to enable/disable handling of new connection handshakes. +void S4NOC_set_handle_new_connections(bool enable) { + s4noc_handle_new_connections = enable; +} void S4NOCPollChannel_poll(NetworkChannel *untyped_self); @@ -34,6 +42,10 @@ static bool S4NOCPollChannel_is_connected(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); + if (!s4noc_handle_new_connections) { + S4NOC_CHANNEL_DEBUG("New connection handling disabled; assuming connected."); + return LF_OK; + } if (!self->received_response) { *s4noc_dest = self->destination_core; @@ -57,7 +69,7 @@ static bool S4NOCPollChannel_is_connected(NetworkChannel *untyped_self) { static lf_ret_t S4NOCPollChannel_open_connection(NetworkChannel *untyped_self) { S4NOC_CHANNEL_DEBUG("Open connection"); // S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; - // self->state = NETWORK_CHANNEL_STATE_CONNECTED;( + // self->state = NETWORK_CHANNEL_STATE_CONNECTED; S4NOCPollChannel_is_connected(untyped_self); return LF_OK; } @@ -164,6 +176,7 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con // S4NOC_CHANNEL_DEBUG("Sent ((%d)) bytes", bytes_send); return LF_OK; } else { + S4NOC_CHANNEL_ERR("Cannot send: Channel is not connected"); return LF_ERR; } } @@ -186,7 +199,8 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { volatile _IODEV int *s4noc_source = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); // if unconnected, and s4noc data available, respond. - if ((self->state != NETWORK_CHANNEL_STATE_CONNECTED) && (((*s4noc_status) & 0x02) != 0)) { + if ((s4noc_handle_new_connections == true) && (self->state != NETWORK_CHANNEL_STATE_CONNECTED) && + (((*s4noc_status) & 0x02) != 0)) { uint32_t word = (uint32_t)(*s4noc_data); uint8_t req_bytes[] = S4NOC_OPEN_MESSAGE_REQUEST; uint8_t resp_bytes[] = S4NOC_OPEN_MESSAGE_RESPONSE; @@ -279,7 +293,7 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core self->receive_buffer_index = 0; self->receive_callback = NULL; self->federated_connection = NULL; - self->state = NETWORK_CHANNEL_STATE_UNINITIALIZED; + self->state = s4noc_handle_new_connections ? NETWORK_CHANNEL_STATE_UNINITIALIZED : NETWORK_CHANNEL_STATE_CONNECTED; self->destination_core = destination_core; memset(self->receive_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); memset(self->write_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index 36a2c81c3..ec90acf72 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -31,6 +31,7 @@ void setUp(void) { /* init channel */ LF_INFO(NET,"init channel"); + S4NOC_set_handle_new_connections(false); S4NOCPollChannel_ctor(&sender_channel, DESTINATION_CORE); S4NOCPollChannel_ctor(&receiver_channel, SOURCE_CORE); @@ -88,7 +89,6 @@ void receive_message(void) { void test_sender_send_and_receiver_recv(void) { TEST_ASSERT_OK(sender->open_connection(sender)); TEST_ASSERT_OK(receiver->open_connection(receiver)); - receiver->register_receive_callback(receiver, receiver_callback_handler, NULL); if(pthread_create(&sender_channel.worker_thread, NULL, send_message, NULL)) { From 3a276f8e7bc8ae5203b1124a9b0f3ff573695fb1 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Wed, 22 Oct 2025 19:07:25 +0200 Subject: [PATCH 21/28] some modifications --- src/platform/patmos/s4noc_channel.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 4347dd713..270cd4671 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -38,7 +38,7 @@ static void S4NOCPollChannel_free(NetworkChannel *untyped_self) { (void)untyped_self; } -static bool S4NOCPollChannel_is_connected(NetworkChannel *untyped_self) { +static lf_ret_t S4NOCPollChannel_is_connected(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); @@ -162,7 +162,9 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con printf_msg("sending msg type:", message); int message_size = serialize_to_protobuf(message, self->write_buffer + 4, S4NOC_CHANNEL_BUFFERSIZE - 4); - *((int *)self->write_buffer) = message_size; + uint32_t sz32 = (uint32_t)message_size; + memcpy(self->write_buffer, &sz32, sizeof(sz32)); + // *((int *)self->write_buffer) = message_size; // S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking: message size: ((%d)).", message_size); int total_size = message_size + 4; // S4NOC_CHANNEL_DEBUG("Total size to send: ((%d))", total_size); @@ -262,7 +264,9 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { S4NOC_CHANNEL_DEBUG("Bytes Left after attempted to deserialize: %d", bytes_left); if (bytes_left >= 0) { - receive_channel->receive_buffer_index = bytes_left; + size_t remaining = (size_t)bytes_left; + receive_channel->receive_buffer_index = (remaining + 3) & ~3U; //rounded up to the next 4 + S4NOC_CHANNEL_DEBUG("Message received at core %d from core %d", get_cpuid(), source); printf_msg("received msg type:", &receive_channel->output); if (receive_channel->receive_callback != NULL) { @@ -298,5 +302,5 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core memset(self->receive_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); memset(self->write_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); unsigned int src_core = get_cpuid(); - s4noc_global_state.core_channels[destination_core][src_core] = self; + s4noc_global_state.core_channels[src_core][destination_core] = self; } From 5fd394286435cae84a46604dc19f0086150032f9 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Thu, 30 Oct 2025 12:43:40 +0100 Subject: [PATCH 22/28] s4noc_fed --- examples/patmos/buildAll.sh | 1 + examples/patmos/s4noc_fed/Makefile | 20 ++ examples/patmos/s4noc_fed/build.sh | 17 ++ examples/patmos/s4noc_fed/main.c | 34 ++++ examples/patmos/s4noc_fed/receiver/Makefile | 34 ++++ examples/patmos/s4noc_fed/receiver/receiver.c | 175 ++++++++++++++++++ examples/patmos/s4noc_fed/receiver/receiver.h | 1 + examples/patmos/s4noc_fed/sender/Makefile | 34 ++++ examples/patmos/s4noc_fed/sender/sender.c | 158 ++++++++++++++++ examples/patmos/s4noc_fed/sender/sender.h | 1 + src/platform/patmos/s4noc_channel.c | 2 +- 11 files changed, 476 insertions(+), 1 deletion(-) create mode 100644 examples/patmos/s4noc_fed/Makefile create mode 100755 examples/patmos/s4noc_fed/build.sh create mode 100644 examples/patmos/s4noc_fed/main.c create mode 100644 examples/patmos/s4noc_fed/receiver/Makefile create mode 100644 examples/patmos/s4noc_fed/receiver/receiver.c create mode 100644 examples/patmos/s4noc_fed/receiver/receiver.h create mode 100644 examples/patmos/s4noc_fed/sender/Makefile create mode 100644 examples/patmos/s4noc_fed/sender/sender.c create mode 100644 examples/patmos/s4noc_fed/sender/sender.h diff --git a/examples/patmos/buildAll.sh b/examples/patmos/buildAll.sh index 32d050244..b1c6b50bd 100755 --- a/examples/patmos/buildAll.sh +++ b/examples/patmos/buildAll.sh @@ -10,6 +10,7 @@ else if [ -d $dir ]; then echo "Entering $dir" pushd $dir + chmod +x build.sh ./build.sh popd fi diff --git a/examples/patmos/s4noc_fed/Makefile b/examples/patmos/s4noc_fed/Makefile new file mode 100644 index 000000000..46e2e9252 --- /dev/null +++ b/examples/patmos/s4noc_fed/Makefile @@ -0,0 +1,20 @@ +include $(REACTOR_UC_PATH)/make/patmos/patmos.mk + +OUTPUT = s4noc_fed.elf +BIN_DIR = $(CURDIR)/bin + +SOURCES += $(CURDIR)/main.c +SOURCES += $(CURDIR)/sender/build/sender.a +SOURCES += $(CURDIR)/receiver/build/receiver.a + +all: $(OUTPUT) + +$(OUTPUT): $(SOURCES) + @echo "BUILDING $(notdir $@) from $^" + mkdir -p $(BIN_DIR) + $(CC) $(CFLAGS) $(SOURCES) -o $(BIN_DIR)/$(OUTPUT) + +clean: + rm -rf $(BIN_DIR) + +.PHONY: all clean \ No newline at end of file diff --git a/examples/patmos/s4noc_fed/build.sh b/examples/patmos/s4noc_fed/build.sh new file mode 100755 index 000000000..0a5bdf46e --- /dev/null +++ b/examples/patmos/s4noc_fed/build.sh @@ -0,0 +1,17 @@ +# !/bin/bash + +LF_MAIN=s4noc_fed +BIN_DIR=bin +CC=patmos-clang +rm -rf $BIN_DIR + +make clean -C ./sender +make clean -C ./receiver + +make all -C ./sender +make all -C ./receiver + +echo "Linking sender and receiver to create executable" +make clean +make all +patemu $BIN_DIR/$LF_MAIN.elf diff --git a/examples/patmos/s4noc_fed/main.c b/examples/patmos/s4noc_fed/main.c new file mode 100644 index 000000000..3cabc57b1 --- /dev/null +++ b/examples/patmos/s4noc_fed/main.c @@ -0,0 +1,34 @@ +#include +#include +#include "sender/sender.h" +#include "receiver/receiver.h" + +static void* receiver_thread(void* arg) { + (void)arg; + // printf("Starting receiver federate on core/thread 1\n"); + lf_start_receiver(); + return NULL; +} + +static void* sender_thread(void* arg) { + (void)arg; + printf("Starting sender federate on core/thread 2\n"); + lf_start_sender(); + return NULL; +} + +int main(void) { + pthread_t threads[2]; + S4NOC_set_handle_new_connections(1); + printf("Starting S4NOC Federated Example\n"); + pthread_create(&threads[0], NULL, receiver_thread, NULL); + pthread_create(&threads[1], NULL, sender_thread, NULL); + + printf("Threads created for federates.\n"); + + pthread_join(threads[0], NULL); + pthread_join(threads[1], NULL); + + printf("All federates finished.\n"); + return 0; +} diff --git a/examples/patmos/s4noc_fed/receiver/Makefile b/examples/patmos/s4noc_fed/receiver/Makefile new file mode 100644 index 000000000..e585c9fc9 --- /dev/null +++ b/examples/patmos/s4noc_fed/receiver/Makefile @@ -0,0 +1,34 @@ +include $(REACTOR_UC_PATH)/make/patmos/patmos.mk + +FED = receiver + +# Paths +SRC_DIR = $(CURDIR) +BUILD_DIR = $(CURDIR)/build + +# Source files +SOURCES = $(FED).c + +OBJECTS ?= $(SOURCES:.c=.bc) + +# Output binary +OUTPUT = $(FED).a + +all: $(OUTPUT) + +# Build rule +$(OUTPUT): $(OBJECTS) + @echo "BUILDING $(notdir $@) from $^" + mkdir -p $(BUILD_DIR) + llvm-ar rcsv $(BUILD_DIR)/$(OUTPUT) $^; + +%.bc: %.c + @echo "$(notdir $^) COMPILED TO $(notdir $@)" + mkdir -p $(BUILD_DIR) + $(CC) $(CFLAGS) -emit-llvm -c $^ -o $@ + +clean: + rm -rf $(BUILD_DIR) + rm -f $(FED).bc + +.PHONY: all clean \ No newline at end of file diff --git a/examples/patmos/s4noc_fed/receiver/receiver.c b/examples/patmos/s4noc_fed/receiver/receiver.c new file mode 100644 index 000000000..6347052e2 --- /dev/null +++ b/examples/patmos/s4noc_fed/receiver/receiver.c @@ -0,0 +1,175 @@ +#include "reactor-uc/platform/patmos/s4noc_channel.h" +#include "reactor-uc/schedulers/dynamic/scheduler.h" +#include "reactor-uc/reactor-uc.h" +#include "reactor-uc/environments/federated_environment.h" +#include "reactor-uc/startup_coordinator.h" +#include "reactor-uc/clock_synchronization.h" +#include + +#define SENDER_CORE_ID 2 + +typedef struct { + int size; + char msg[512]; +} lf_msg_t; + +lf_ret_t deserialize_msg_t(void *user_struct, const unsigned char *msg_buf, size_t msg_size) { + (void)msg_size; + + lf_msg_t *msg = user_struct; + memcpy(&msg->size, msg_buf, sizeof(msg->size)); + memcpy(msg->msg, msg_buf + sizeof(msg->size), msg->size); + + /* Make sure msg->msg is null-terminated before printing. */ + if (msg->size < (int)sizeof(msg->msg)) { + msg->msg[msg->size] = '\0'; + } else { + msg->msg[sizeof(msg->msg) - 1] = '\0'; + } + + printf("Receiver: deserialize_msg_t: deserialized size=%d, msg='%s'\n", msg->size, msg->msg); + + return LF_OK; +} + +LF_DEFINE_REACTION_STRUCT(Receiver, r, 0) +LF_DEFINE_REACTION_CTOR(Receiver, r, 0, NULL, NULL) +LF_DEFINE_INPUT_STRUCT(Receiver, in, 1, 0, lf_msg_t, 0) +LF_DEFINE_INPUT_CTOR(Receiver, in, 1, 0, lf_msg_t, 0) + +typedef struct { + Reactor super; + LF_REACTION_INSTANCE(Receiver, r); + LF_PORT_INSTANCE(Receiver, in, 1); + int cnt; + LF_REACTOR_BOOKKEEPING_INSTANCES(1, 1, 0); +} Receiver; + +LF_DEFINE_REACTION_BODY(Receiver, r) { + LF_SCOPE_SELF(Receiver); + LF_SCOPE_ENV(); + LF_SCOPE_PORT(Receiver, in); + printf("Receiver: Input triggered @ " PRINTF_TIME " with %s size %d\n", env->get_elapsed_logical_time(env), in->value.msg, + in->value.size); +} + +LF_REACTOR_CTOR_SIGNATURE_WITH_PARAMETERS(Receiver, InputExternalCtorArgs *in_external) { + LF_REACTOR_CTOR_PREAMBLE(); + LF_REACTOR_CTOR(Receiver); + LF_INITIALIZE_REACTION(Receiver, r, NEVER); + LF_INITIALIZE_INPUT(Receiver, in, 1, in_external); + + // Register reaction as an effect of in + LF_PORT_REGISTER_EFFECT(self->in, self->r, 1); +} + +LF_DEFINE_FEDERATED_INPUT_CONNECTION_STRUCT(Receiver, in, lf_msg_t, 5); +LF_DEFINE_FEDERATED_INPUT_CONNECTION_CTOR(Receiver, in, lf_msg_t, 5, MSEC(100), false, 0); + +typedef struct { + FederatedConnectionBundle super; + S4NOCPollChannel channel; + LF_FEDERATED_INPUT_CONNECTION_INSTANCE(Receiver, in); + LF_FEDERATED_CONNECTION_BUNDLE_BOOKKEEPING_INSTANCES(1, 0) +} LF_FEDERATED_CONNECTION_BUNDLE_TYPE(Receiver, Sender); + +LF_FEDERATED_CONNECTION_BUNDLE_CTOR_SIGNATURE(Receiver, Sender) { + LF_FEDERATED_CONNECTION_BUNDLE_CTOR_PREAMBLE(); + S4NOCPollChannel_ctor(&self->channel, SENDER_CORE_ID); + printf("Receiver: initialized channel for core %d\n", SENDER_CORE_ID); + LF_FEDERATED_CONNECTION_BUNDLE_CALL_CTOR(); + LF_INITIALIZE_FEDERATED_INPUT_CONNECTION(Receiver, in, deserialize_msg_t); +} + +typedef struct { + StartupCoordinator super; + StartupEvent events[6]; + bool used[6]; + NeighborState neighbors[1]; +} ReceiverStartupCoordinator; + + + void ReceiverStartupCoordinator_ctor(ReceiverStartupCoordinator *self, Environment *env) { + StartupCoordinator_ctor(&self->super, env, self->neighbors, 1, 1, JOIN_IMMEDIATELY, + sizeof(StartupEvent), (void *)self->events, self->used, 6); + } + + typedef struct { + ClockSynchronization super; + ClockSyncEvent events[2]; + NeighborClock neighbor_clocks[1]; + bool used[2]; + } ReceiverClockSynchronization; + + void ReceiverClockSynchronization_ctor(ReceiverClockSynchronization *self, Environment *env) { + ClockSynchronization_ctor(&self->super, env, self->neighbor_clocks, 1, false, + sizeof(ClockSyncEvent), (void *)self->events, self->used, (2), + CLOCK_SYNC_DEFAULT_PERIOD, CLOCK_SYNC_DEFAULT_MAX_ADJ, CLOCK_SYNC_DEFAULT_KP, + CLOCK_SYNC_DEFAULT_KI); + } + +typedef struct { + Reactor super; + LF_CHILD_REACTOR_INSTANCE(Receiver, receiver, 1); + LF_FEDERATED_CONNECTION_BUNDLE_INSTANCE(Receiver, Sender); + LF_FEDERATE_BOOKKEEPING_INSTANCES(1); + LF_CHILD_INPUT_SOURCES(receiver, in, 1, 1, 0); + LF_DEFINE_STARTUP_COORDINATOR(Receiver); + LF_DEFINE_CLOCK_SYNC(Receiver); +} MainRecv; + +LF_REACTOR_CTOR_SIGNATURE(MainRecv) { + LF_REACTOR_CTOR(MainRecv); + LF_FEDERATE_CTOR_PREAMBLE(); + LF_DEFINE_CHILD_INPUT_ARGS(receiver, in, 1, 1); + LF_INITIALIZE_CHILD_REACTOR_WITH_PARAMETERS(Receiver, receiver, 1, _receiver_in_args[i]); + LF_INITIALIZE_FEDERATED_CONNECTION_BUNDLE(Receiver, Sender); + LF_INITIALIZE_STARTUP_COORDINATOR(Receiver); + LF_INITIALIZE_CLOCK_SYNC(Receiver); + lf_connect_federated_input(&self->Receiver_Sender_bundle.inputs[0]->super, &self->receiver->in[0].super); +} + +#define NumEvents 32 +#define NumSystemEvents 32 +#define NumReactions 32 +#define Timeout SEC(1) +#define KeepAlive true +#define NumBundles 1 +#define DoClockSync false + +static MainRecv main_reactor; +static FederatedEnvironment env; +Environment *_lf_environment = &env.super; +static DynamicScheduler scheduler; +static ArbitraryEvent events[(NumEvents)]; +static EventQueue event_queue; +static ArbitraryEvent system_events[(NumSystemEvents)]; +static EventQueue system_event_queue; +static Reaction *reactions[(NumReactions)][(NumReactions)]; +static int level_size[(NumReactions)]; +static ReactionQueue reaction_queue; + +void lf_exit_receiver(void) { + printf("lf_exit_receiver: cleaning up federated environment\n"); + FederatedEnvironment_free(&env); +} + +void lf_start_receiver() { + EventQueue_ctor(&event_queue, events, (NumEvents)); + EventQueue_ctor(&system_event_queue, system_events, (NumSystemEvents)); + ReactionQueue_ctor(&reaction_queue, (Reaction **)reactions, level_size, (NumReactions)); + DynamicScheduler_ctor(&scheduler, _lf_environment, &event_queue, &system_event_queue, &reaction_queue, (Timeout), + (KeepAlive)); + FederatedEnvironment_ctor( + &env, (Reactor *)&main_reactor, &scheduler.super, false, (FederatedConnectionBundle **)&main_reactor._bundles, + (NumBundles), &main_reactor.startup_coordinator.super, (DoClockSync) ? &main_reactor.clock_sync.super : NULL); + MainRecv_ctor(&main_reactor, NULL, _lf_environment); + env.net_bundles_size = (NumBundles); + env.net_bundles = (FederatedConnectionBundle **)&main_reactor._bundles; + printf("lf_start_receiver: assembling federated environment (bundles=%d)\n", env.net_bundles_size); + _lf_environment->assemble(_lf_environment); + printf("lf_start_receiver: starting federated environment\n"); + _lf_environment->start(_lf_environment); + printf("lf_start_receiver: federated environment started\n"); + lf_exit_receiver(); +} diff --git a/examples/patmos/s4noc_fed/receiver/receiver.h b/examples/patmos/s4noc_fed/receiver/receiver.h new file mode 100644 index 000000000..657a53e3a --- /dev/null +++ b/examples/patmos/s4noc_fed/receiver/receiver.h @@ -0,0 +1 @@ +void lf_start_receiver(void); \ No newline at end of file diff --git a/examples/patmos/s4noc_fed/sender/Makefile b/examples/patmos/s4noc_fed/sender/Makefile new file mode 100644 index 000000000..4867feffc --- /dev/null +++ b/examples/patmos/s4noc_fed/sender/Makefile @@ -0,0 +1,34 @@ +include $(REACTOR_UC_PATH)/make/patmos/patmos.mk + +FED = sender + +# Paths +SRC_DIR = $(CURDIR) +BUILD_DIR = $(CURDIR)/build + +# Source files +SOURCES = $(FED).c + +OBJECTS ?= $(SOURCES:.c=.bc) + +# Output binary +OUTPUT = $(FED).a + +all: $(OUTPUT) + +# Build rule +$(OUTPUT): $(OBJECTS) + @echo "BUILDING $(notdir $@) from $^" + mkdir -p $(BUILD_DIR) + llvm-ar rcsv $(BUILD_DIR)/$(OUTPUT) $(OBJECTS); + +%.bc: %.c + @echo "$(notdir $^) COMPILED TO $(notdir $@)" + mkdir -p $(BUILD_DIR) + $(CC) $(CFLAGS) -emit-llvm -c $^ -o $@ + +clean: + rm -rf $(BUILD_DIR) + rm -f $(FED).bc + +.PHONY: all clean \ No newline at end of file diff --git a/examples/patmos/s4noc_fed/sender/sender.c b/examples/patmos/s4noc_fed/sender/sender.c new file mode 100644 index 000000000..0cb76d90b --- /dev/null +++ b/examples/patmos/s4noc_fed/sender/sender.c @@ -0,0 +1,158 @@ +#include "reactor-uc/platform/patmos/s4noc_channel.h" +#include "reactor-uc/schedulers/dynamic/scheduler.h" +#include "reactor-uc/reactor-uc.h" +#include "reactor-uc/startup_coordinator.h" +#include "reactor-uc/clock_synchronization.h" +#include "reactor-uc/environments/federated_environment.h" +#include + + #define RECEIVER_CORE_ID 1 + +typedef struct { + int size; + char msg[512]; +} lf_msg_t; + +int serialize_msg_t(const void *user_struct, size_t user_struct_size, unsigned char *msg_buf) { + (void)user_struct_size; + const lf_msg_t *msg = user_struct; + + memcpy(msg_buf, &msg->size, sizeof(msg->size)); + memcpy(msg_buf + sizeof(msg->size), msg->msg, msg->size); + + /* Null-terminate a temporary view for logging (do not modify msg_buf) */ + { + int printable = msg->size; + if (printable > 200) printable = 200; + char tmp[201]; + if (printable > 0) { + memcpy(tmp, msg->msg, printable); + } + tmp[printable] = '\0'; + printf("serialize_msg_t: size=%d, preview='%s'\n", msg->size, tmp); + } + + return sizeof(msg->size) + msg->size; +} + +LF_DEFINE_TIMER_STRUCT(Sender, t, 1, 0) +LF_DEFINE_TIMER_CTOR(Sender, t, 1, 0) +LF_DEFINE_REACTION_STRUCT(Sender, r, 1) +LF_DEFINE_REACTION_CTOR(Sender, r, 0, NULL, NULL) +LF_DEFINE_OUTPUT_STRUCT(Sender, out, 1, lf_msg_t) +LF_DEFINE_OUTPUT_CTOR(Sender, out, 1) + +typedef struct { + Reactor super; + LF_TIMER_INSTANCE(Sender, t); + LF_REACTION_INSTANCE(Sender, r); + LF_PORT_INSTANCE(Sender, out, 1); + LF_REACTOR_BOOKKEEPING_INSTANCES(1, 2, 0); +} Sender; + +LF_DEFINE_REACTION_BODY(Sender, r) { + LF_SCOPE_SELF(Sender); + LF_SCOPE_ENV(); + LF_SCOPE_PORT(Sender, out); + + printf("Sender: Timer triggered @ " PRINTF_TIME "\n", env->get_elapsed_logical_time(env)); + lf_msg_t val; + strcpy(val.msg, "Hello From Sender"); + val.size = sizeof("Hello From Sender"); + printf("Sender reaction: preparing message size=%d, msg='%s'\n", val.size, val.msg); + lf_set(out, val); +} + +LF_REACTOR_CTOR_SIGNATURE_WITH_PARAMETERS(Sender, OutputExternalCtorArgs *out_external) { + LF_REACTOR_CTOR_PREAMBLE(); + LF_REACTOR_CTOR(Sender); + printf("Sender: Initializing reaction and timer...\n"); + LF_INITIALIZE_REACTION(Sender, r, NEVER); + LF_INITIALIZE_TIMER(Sender, t, SEC(1), SEC(1)); // Start at 1s, period 1s + LF_INITIALIZE_OUTPUT(Sender, out, 1, out_external); + + printf("Sender: Registering timer effects and port sources...\n"); + LF_TIMER_REGISTER_EFFECT(self->t, self->r); + LF_PORT_REGISTER_SOURCE(self->out, self->r, 1); +} + +LF_DEFINE_FEDERATED_OUTPUT_CONNECTION_STRUCT(Sender, out, lf_msg_t) +LF_DEFINE_FEDERATED_OUTPUT_CONNECTION_CTOR(Sender, out, lf_msg_t, 0) + +typedef struct { + FederatedConnectionBundle super; + S4NOCPollChannel channel; + LF_FEDERATED_OUTPUT_CONNECTION_INSTANCE(Sender, out); + LF_FEDERATED_CONNECTION_BUNDLE_BOOKKEEPING_INSTANCES(0, 1); +} LF_FEDERATED_CONNECTION_BUNDLE_TYPE(Sender, Receiver); + +LF_FEDERATED_CONNECTION_BUNDLE_CTOR_SIGNATURE(Sender, Receiver) { + LF_FEDERATED_CONNECTION_BUNDLE_CTOR_PREAMBLE(); + S4NOCPollChannel_ctor(&self->channel, RECEIVER_CORE_ID); + printf("Sender: initialized channel for core %d\n", RECEIVER_CORE_ID); + LF_FEDERATED_CONNECTION_BUNDLE_CALL_CTOR(); + LF_INITIALIZE_FEDERATED_OUTPUT_CONNECTION(Sender, out, serialize_msg_t); +} + +LF_DEFINE_STARTUP_COORDINATOR_STRUCT(Federate, 1, 6); +LF_DEFINE_STARTUP_COORDINATOR_CTOR(Federate, 1, 1, 6, JOIN_IMMEDIATELY); + +LF_DEFINE_CLOCK_SYNC_STRUCT(Federate, 1, 2); +LF_DEFINE_CLOCK_SYNC_DEFAULTS_CTOR(Federate, 1, 1, true); + +// Reactor main +typedef struct { + Reactor super; + LF_CHILD_REACTOR_INSTANCE(Sender, sender, 1); + LF_FEDERATED_CONNECTION_BUNDLE_INSTANCE(Sender, Receiver); + LF_FEDERATE_BOOKKEEPING_INSTANCES(1); + LF_CHILD_OUTPUT_CONNECTIONS(sender, out, 1, 1, 1); + LF_CHILD_OUTPUT_EFFECTS(sender, out, 1, 1, 0); + LF_CHILD_OUTPUT_OBSERVERS(sender, out, 1, 1, 0); + LF_DEFINE_STARTUP_COORDINATOR(Federate); + LF_DEFINE_CLOCK_SYNC(Federate); +} MainSender; + +LF_REACTOR_CTOR_SIGNATURE(MainSender) { + LF_REACTOR_CTOR(MainSender); + LF_FEDERATE_CTOR_PREAMBLE(); + LF_DEFINE_CHILD_OUTPUT_ARGS(sender, out, 1, 1); + LF_INITIALIZE_CHILD_REACTOR_WITH_PARAMETERS(Sender, sender, 1, _sender_out_args[i]); + LF_INITIALIZE_FEDERATED_CONNECTION_BUNDLE(Sender, Receiver); + lf_connect_federated_output((Connection *)self->Sender_Receiver_bundle.outputs[0], (Port *)self->sender->out); + LF_INITIALIZE_STARTUP_COORDINATOR(Federate); + LF_INITIALIZE_CLOCK_SYNC(Federate); +} + +static MainSender main_reactor; +static FederatedEnvironment env; +Environment *_lf_environment_sender = &env.super; +// Define queues used by scheduler +LF_DEFINE_EVENT_QUEUE(Main_EventQueue, 1) +LF_DEFINE_EVENT_QUEUE(Main_SystemEventQueue, 11) +LF_DEFINE_REACTION_QUEUE(Main_ReactionQueue, 1) +static DynamicScheduler _scheduler; +static Scheduler* scheduler = &_scheduler.super; + +void lf_exit_sender(void) { + printf("lf_exit_sender: cleaning up federated environment\n"); + FederatedEnvironment_free(&env); +} + +void lf_start_sender(void) { + // Define queues used by scheduler + LF_INITIALIZE_EVENT_QUEUE(Main_EventQueue, 1) + LF_INITIALIZE_EVENT_QUEUE(Main_SystemEventQueue, 11) + LF_INITIALIZE_REACTION_QUEUE(Main_ReactionQueue, 1) + DynamicScheduler_ctor(&_scheduler, _lf_environment_sender, &Main_EventQueue.super, &Main_SystemEventQueue.super, &Main_ReactionQueue.super, FOREVER, false); + FederatedEnvironment_ctor(&env, (Reactor *)&main_reactor, scheduler, false, + (FederatedConnectionBundle **) &main_reactor._bundles, 1, &main_reactor.startup_coordinator.super, + &main_reactor.clock_sync.super); + MainSender_ctor(&main_reactor, NULL, _lf_environment_sender); + printf("lf_start_sender: assembling federated environment (bundles=%d)\n", env.net_bundles_size); + _lf_environment_sender->assemble(_lf_environment_sender); + printf("lf_start_sender: starting federated environment\n"); + _lf_environment_sender->start(_lf_environment_sender); + printf("lf_start_sender: federated environment started\n"); + lf_exit_sender(); +} diff --git a/examples/patmos/s4noc_fed/sender/sender.h b/examples/patmos/s4noc_fed/sender/sender.h new file mode 100644 index 000000000..f956c4ec0 --- /dev/null +++ b/examples/patmos/s4noc_fed/sender/sender.h @@ -0,0 +1 @@ +void lf_start_sender(void); \ No newline at end of file diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 270cd4671..f48196072 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -265,7 +265,7 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { if (bytes_left >= 0) { size_t remaining = (size_t)bytes_left; - receive_channel->receive_buffer_index = (remaining + 3) & ~3U; //rounded up to the next 4 + receive_channel->receive_buffer_index = (remaining + 3) & ~3U; // rounded up to the next 4 S4NOC_CHANNEL_DEBUG("Message received at core %d from core %d", get_cpuid(), source); printf_msg("received msg type:", &receive_channel->output); From dc046296e9f1332149b35e5747408235e1e4d556 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Fri, 31 Oct 2025 13:23:58 +0100 Subject: [PATCH 23/28] fpga config & some renaming --- examples/patmos/s4noc_fed/build.sh | 18 ++++++++++++++++-- examples/patmos/s4noc_fed/sender/sender.c | 16 ++++++++-------- src/platform/patmos/s4noc_channel.c | 2 +- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/examples/patmos/s4noc_fed/build.sh b/examples/patmos/s4noc_fed/build.sh index 0a5bdf46e..af770409c 100755 --- a/examples/patmos/s4noc_fed/build.sh +++ b/examples/patmos/s4noc_fed/build.sh @@ -3,7 +3,6 @@ LF_MAIN=s4noc_fed BIN_DIR=bin CC=patmos-clang -rm -rf $BIN_DIR make clean -C ./sender make clean -C ./receiver @@ -14,4 +13,19 @@ make all -C ./receiver echo "Linking sender and receiver to create executable" make clean make all -patemu $BIN_DIR/$LF_MAIN.elf + +read -n 1 -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action +action=${action:-e} +if [[ "$action" == "e" ]]; then + patemu $BIN_DIR/$LF_MAIN.elf +elif [[ "$action" == "f" ]]; then + if jtagconfig | grep -q "USB-Blaster"; then + mv $BIN_DIR/$LF_MAIN.elf ~/t-crest/patmos/tmp/$LF_MAIN.elf + make -C ~/t-crest/patmos APP=$LF_MAIN config download + else + echo "JTAG not connected. Please connect USB-Blaster." + fi +else + echo "Invalid option. Please choose 'e' for emulate or 'f' for fpga." +fi + diff --git a/examples/patmos/s4noc_fed/sender/sender.c b/examples/patmos/s4noc_fed/sender/sender.c index 0cb76d90b..801644a47 100644 --- a/examples/patmos/s4noc_fed/sender/sender.c +++ b/examples/patmos/s4noc_fed/sender/sender.c @@ -94,11 +94,11 @@ LF_FEDERATED_CONNECTION_BUNDLE_CTOR_SIGNATURE(Sender, Receiver) { LF_INITIALIZE_FEDERATED_OUTPUT_CONNECTION(Sender, out, serialize_msg_t); } -LF_DEFINE_STARTUP_COORDINATOR_STRUCT(Federate, 1, 6); -LF_DEFINE_STARTUP_COORDINATOR_CTOR(Federate, 1, 1, 6, JOIN_IMMEDIATELY); +LF_DEFINE_STARTUP_COORDINATOR_STRUCT(Sender, 1, 6); +LF_DEFINE_STARTUP_COORDINATOR_CTOR(Sender, 1, 1, 6, JOIN_IMMEDIATELY); -LF_DEFINE_CLOCK_SYNC_STRUCT(Federate, 1, 2); -LF_DEFINE_CLOCK_SYNC_DEFAULTS_CTOR(Federate, 1, 1, true); +LF_DEFINE_CLOCK_SYNC_STRUCT(Sender, 1, 2); +LF_DEFINE_CLOCK_SYNC_DEFAULTS_CTOR(Sender, 1, 1, true); // Reactor main typedef struct { @@ -109,8 +109,8 @@ typedef struct { LF_CHILD_OUTPUT_CONNECTIONS(sender, out, 1, 1, 1); LF_CHILD_OUTPUT_EFFECTS(sender, out, 1, 1, 0); LF_CHILD_OUTPUT_OBSERVERS(sender, out, 1, 1, 0); - LF_DEFINE_STARTUP_COORDINATOR(Federate); - LF_DEFINE_CLOCK_SYNC(Federate); + LF_DEFINE_STARTUP_COORDINATOR(Sender); + LF_DEFINE_CLOCK_SYNC(Sender); } MainSender; LF_REACTOR_CTOR_SIGNATURE(MainSender) { @@ -120,8 +120,8 @@ LF_REACTOR_CTOR_SIGNATURE(MainSender) { LF_INITIALIZE_CHILD_REACTOR_WITH_PARAMETERS(Sender, sender, 1, _sender_out_args[i]); LF_INITIALIZE_FEDERATED_CONNECTION_BUNDLE(Sender, Receiver); lf_connect_federated_output((Connection *)self->Sender_Receiver_bundle.outputs[0], (Port *)self->sender->out); - LF_INITIALIZE_STARTUP_COORDINATOR(Federate); - LF_INITIALIZE_CLOCK_SYNC(Federate); + LF_INITIALIZE_STARTUP_COORDINATOR(Sender); + LF_INITIALIZE_CLOCK_SYNC(Sender); } static MainSender main_reactor; diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index f48196072..659bcd784 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -167,7 +167,7 @@ static lf_ret_t S4NOCPollChannel_send_blocking(NetworkChannel *untyped_self, con // *((int *)self->write_buffer) = message_size; // S4NOC_CHANNEL_DEBUG("S4NOCPollChannel_send_blocking: message size: ((%d)).", message_size); int total_size = message_size + 4; - // S4NOC_CHANNEL_DEBUG("Total size to send: ((%d))", total_size); + S4NOC_CHANNEL_DEBUG("Total size to send: ((%d))", total_size); *s4noc_dest = self->destination_core; int bytes_send = 0; From b74cc7d3094337a2de3a4fd938968bde73a56e31 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Fri, 31 Oct 2025 14:52:27 +0100 Subject: [PATCH 24/28] readme update --- README.md | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 813c5a438..a2fe8cde4 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,18 @@ information on reactor-uc see our [docs](https://www.lf-lang.org/reactor-uc/) - Java 17 - Additional requirements depend on the target platform +### Installation & Quick Start + + +Clone the repository and set REACTOR_UC_PATH: +```sh +git clone https://github.com/lf-lang/reactor-uc.git +export REACTOR_UC_PATH="$HOME/path/to/reactor-uc" +``` + + ## Supported Platforms -`reactor-uc` can run on top of Zephyr, RIOT, Raspberry Pi Pico and POSIX-compliant OSes. +`reactor-uc` can run on top of Zephyr, RIOT, Raspberry Pi Pico, Patmos, and POSIX-compliant OSes. ### Native (macOS and Linux) `reactor-uc` can also run natively on a host system based on Linux or macOS. This is very useful for developing and testing applications @@ -89,14 +99,14 @@ make ### Patmos -To install Patmos, follow instructions in [https://github.com/t-crest/patmos/](https://github.com/t-crest/patmos) readme file. For now, use the previous version of compiler by running `./misc/build.sh toolchain1`. +To install Patmos, follow instructions in [https://github.com/t-crest/patmos/](https://github.com/t-crest/patmos) readme file. -Compile and run a Hello World example by running these lines: +To compile and run patmos examples, navigate to their folders inside `exmaples/patmos` folder and run `./build.sh` +To run all examples together by runing the following lines: ```shell -cd examples/patmos/hello -make all -pasim build/hello.elf +cd examples/patmos +./buildAll.sh ``` ## Contributing @@ -137,6 +147,16 @@ make lf-test This depends on having the `timeout` utility installed. For macOS users run `brew install coreutils`. +Run platform related tests with +```sh +make platform-test +``` + +Run all examples with +```sh +make examples +``` + Compute unit test coverage ```sh make coverage From abd04561642542b2a85af3034ebe952f4945e1a3 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Fri, 31 Oct 2025 17:08:30 +0100 Subject: [PATCH 25/28] --recursive in readme --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a2fe8cde4..f21c1553b 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,9 @@ information on reactor-uc see our [docs](https://www.lf-lang.org/reactor-uc/) Clone the repository and set REACTOR_UC_PATH: ```sh -git clone https://github.com/lf-lang/reactor-uc.git -export REACTOR_UC_PATH="$HOME/path/to/reactor-uc" +git clone https://github.com/lf-lang/reactor-uc.git --recursive +cd reactor-uc +export REACTOR_UC_PATH=$(pwd) ``` From 7f335fdc949ccbbf1c9e575bb270e753787c810c Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Mon, 3 Nov 2025 14:57:10 +0100 Subject: [PATCH 26/28] log lock --- include/reactor-uc/logging.h | 2 +- src/logging.c | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/reactor-uc/logging.h b/include/reactor-uc/logging.h index d8f020710..10b19de39 100644 --- a/include/reactor-uc/logging.h +++ b/include/reactor-uc/logging.h @@ -29,7 +29,7 @@ #endif /** Add timestamps to each log entry. */ -#if !defined(LF_TIMESTAMP_LOGS) && !defined(PLATFORM_FLEXPRET) +#if !defined(LF_TIMESTAMP_LOGS) && !defined(PLATFORM_FLEXPRET) && !defined(PLATFORM_PATMOS) #define LF_TIMESTAMP_LOGS 1 #else #undef LF_TIMESTAMP_LOGS diff --git a/src/logging.c b/src/logging.c index 0b13dbc3a..f06bf464f 100644 --- a/src/logging.c +++ b/src/logging.c @@ -4,6 +4,7 @@ #include #include +#include #define ANSI_COLOR_RED "\x1b[31m" #define ANSI_COLOR_GREEN "\x1b[32m" @@ -13,10 +14,16 @@ #define ANSI_COLOR_CYAN "\x1b[36m" #define ANSI_COLOR_RESET "\x1b[0m" +static pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER; + void log_printf(const char *fmt, ...) { va_list args; va_start(args, fmt); + + pthread_mutex_lock(&log_lock); Platform_vprintf(fmt, args); + pthread_mutex_unlock(&log_lock); + va_end(args); } @@ -40,6 +47,8 @@ void log_message(int level, const char *module, const char *fmt, ...) { break; } + pthread_mutex_lock(&log_lock); + va_list args; va_start(args, fmt); @@ -83,5 +92,8 @@ void log_message(int level, const char *module, const char *fmt, ...) { #else log_printf("\n"); #endif + + pthread_mutex_unlock(&log_lock); + va_end(args); } From 0486db0afd8972b0a16bbd146bcf8a471ceddf6a Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Tue, 4 Nov 2025 17:37:38 +0100 Subject: [PATCH 27/28] cpu_id in log --- README.md | 5 +++-- include/reactor-uc/logging.h | 2 +- src/logging.c | 6 +++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f21c1553b..1ae80114b 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,9 @@ make To install Patmos, follow instructions in [https://github.com/t-crest/patmos/](https://github.com/t-crest/patmos) readme file. -To compile and run patmos examples, navigate to their folders inside `exmaples/patmos` folder and run `./build.sh` -To run all examples together by runing the following lines: +To compile and run patmos examples, navigate to their folders inside `exmaples/patmos` folder and run `./build.sh`. + +To compile and run all examples together, run the following lines: ```shell cd examples/patmos diff --git a/include/reactor-uc/logging.h b/include/reactor-uc/logging.h index 10b19de39..d8f020710 100644 --- a/include/reactor-uc/logging.h +++ b/include/reactor-uc/logging.h @@ -29,7 +29,7 @@ #endif /** Add timestamps to each log entry. */ -#if !defined(LF_TIMESTAMP_LOGS) && !defined(PLATFORM_FLEXPRET) && !defined(PLATFORM_PATMOS) +#if !defined(LF_TIMESTAMP_LOGS) && !defined(PLATFORM_FLEXPRET) #define LF_TIMESTAMP_LOGS 1 #else #undef LF_TIMESTAMP_LOGS diff --git a/src/logging.c b/src/logging.c index f06bf464f..a80ed544a 100644 --- a/src/logging.c +++ b/src/logging.c @@ -76,7 +76,11 @@ void log_message(int level, const char *module, const char *fmt, ...) { if (_lf_environment) { timestamp = _lf_environment->platform->get_physical_time(_lf_environment->platform); } - log_printf("(" PRINTF_TIME ") [%s] [%s] ", timestamp, level_str, module); + #if defined(PLATFORM_PATMOS) + log_printf("(" PRINTF_TIME ") [%s] [%s] [%d] ", timestamp, level_str, module, get_cpuid()); + #else + log_printf("(" PRINTF_TIME ") [%s] [%s] ", timestamp, level_str, module); + #endif #else log_printf("[%s] [%s] ", level_str, module); From 737cd87ea94b45e15af9894e812675ec37bc83f8 Mon Sep 17 00:00:00 2001 From: Ehsan Khodadad Date: Wed, 5 Nov 2025 13:32:05 +0100 Subject: [PATCH 28/28] handle_new_connection as a macro --- examples/patmos/s4noc_fed/main.c | 3 +- .../platform/patmos/s4noc_channel.h | 1 - src/logging.c | 10 +++--- src/platform/patmos/s4noc_channel.c | 32 +++++++++---------- .../patmos/s4noc_channel_test/Makefile | 1 + .../platform/patmos/s4noc_channel_test/main.c | 1 - .../platform/patmos/s4noc_channel_test/run.sh | 3 ++ 7 files changed, 26 insertions(+), 25 deletions(-) diff --git a/examples/patmos/s4noc_fed/main.c b/examples/patmos/s4noc_fed/main.c index 3cabc57b1..05c07296c 100644 --- a/examples/patmos/s4noc_fed/main.c +++ b/examples/patmos/s4noc_fed/main.c @@ -18,8 +18,7 @@ static void* sender_thread(void* arg) { } int main(void) { - pthread_t threads[2]; - S4NOC_set_handle_new_connections(1); + pthread_t threads[2]; printf("Starting S4NOC Federated Example\n"); pthread_create(&threads[0], NULL, receiver_thread, NULL); pthread_create(&threads[1], NULL, sender_thread, NULL); diff --git a/include/reactor-uc/platform/patmos/s4noc_channel.h b/include/reactor-uc/platform/patmos/s4noc_channel.h index 1b0df7a89..d68beb289 100644 --- a/include/reactor-uc/platform/patmos/s4noc_channel.h +++ b/include/reactor-uc/platform/patmos/s4noc_channel.h @@ -38,5 +38,4 @@ struct S4NOCPollChannel { }; void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core); -void S4NOC_set_handle_new_connections(bool enable); #endif diff --git a/src/logging.c b/src/logging.c index a80ed544a..b6eea8296 100644 --- a/src/logging.c +++ b/src/logging.c @@ -76,11 +76,11 @@ void log_message(int level, const char *module, const char *fmt, ...) { if (_lf_environment) { timestamp = _lf_environment->platform->get_physical_time(_lf_environment->platform); } - #if defined(PLATFORM_PATMOS) - log_printf("(" PRINTF_TIME ") [%s] [%s] [%d] ", timestamp, level_str, module, get_cpuid()); - #else - log_printf("(" PRINTF_TIME ") [%s] [%s] ", timestamp, level_str, module); - #endif +#if defined(PLATFORM_PATMOS) + log_printf("(" PRINTF_TIME ") [%s] [%s] [%d] ", timestamp, level_str, module, get_cpuid()); +#else + log_printf("(" PRINTF_TIME ") [%s] [%s] ", timestamp, level_str, module); +#endif #else log_printf("[%s] [%s] ", level_str, module); diff --git a/src/platform/patmos/s4noc_channel.c b/src/platform/patmos/s4noc_channel.c index 659bcd784..2966b31ac 100644 --- a/src/platform/patmos/s4noc_channel.c +++ b/src/platform/patmos/s4noc_channel.c @@ -11,19 +11,18 @@ #define S4NOC_CHANNEL_INFO(fmt, ...) LF_INFO(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) #define S4NOC_CHANNEL_DEBUG(fmt, ...) LF_DEBUG(NET, "S4NOCPollChannel: " fmt, ##__VA_ARGS__) +#ifndef HANDLE_NEW_CONNECTIONS +#define HANDLE_NEW_CONNECTIONS 0 +#endif + +#if HANDLE_NEW_CONNECTIONS #define S4NOC_OPEN_MESSAGE_REQUEST \ { 0xC0, 0x18, 0x11, 0xC0 } #define S4NOC_OPEN_MESSAGE_RESPONSE \ { 0xC0, 0xFF, 0x31, 0xC0 } +#endif S4NOCGlobalState s4noc_global_state = {0}; -// Control whether the driver will handle S4NOC "new connection" open/response words -static bool s4noc_handle_new_connections = true; - -// API to enable/disable handling of new connection handshakes. -void S4NOC_set_handle_new_connections(bool enable) { - s4noc_handle_new_connections = enable; -} void S4NOCPollChannel_poll(NetworkChannel *untyped_self); @@ -40,12 +39,9 @@ static void S4NOCPollChannel_free(NetworkChannel *untyped_self) { static lf_ret_t S4NOCPollChannel_is_connected(NetworkChannel *untyped_self) { S4NOCPollChannel *self = (S4NOCPollChannel *)untyped_self; +#if HANDLE_NEW_CONNECTIONS volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_dest = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); - if (!s4noc_handle_new_connections) { - S4NOC_CHANNEL_DEBUG("New connection handling disabled; assuming connected."); - return LF_OK; - } if (!self->received_response) { *s4noc_dest = self->destination_core; @@ -64,6 +60,10 @@ static lf_ret_t S4NOCPollChannel_is_connected(NetworkChannel *untyped_self) { S4NOC_CHANNEL_DEBUG("Network is %s", NetworkChannel_state_to_string(self->state)); return self->state == NETWORK_CHANNEL_STATE_CONNECTED && self->received_response && self->send_response; +#else + S4NOC_CHANNEL_DEBUG("New connection handling disabled; assuming connected."); + return self->state == NETWORK_CHANNEL_STATE_CONNECTED; +#endif } static lf_ret_t S4NOCPollChannel_open_connection(NetworkChannel *untyped_self) { @@ -200,9 +200,9 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { volatile _IODEV int *s4noc_data = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 4); volatile _IODEV int *s4noc_source = (volatile _IODEV int *)(PATMOS_IO_S4NOC + 8); - // if unconnected, and s4noc data available, respond. - if ((s4noc_handle_new_connections == true) && (self->state != NETWORK_CHANNEL_STATE_CONNECTED) && - (((*s4noc_status) & 0x02) != 0)) { +// if unconnected, and s4noc data available, respond. +#if HANDLE_NEW_CONNECTIONS + if ((self->state != NETWORK_CHANNEL_STATE_CONNECTED) && (((*s4noc_status) & 0x02) != 0)) { uint32_t word = (uint32_t)(*s4noc_data); uint8_t req_bytes[] = S4NOC_OPEN_MESSAGE_REQUEST; uint8_t resp_bytes[] = S4NOC_OPEN_MESSAGE_RESPONSE; @@ -225,7 +225,7 @@ void S4NOCPollChannel_poll(NetworkChannel *untyped_self) { return; } - +#endif // Check if data is available on the S4NOC interface if (((*s4noc_status) & 0x02) == 0) { S4NOC_CHANNEL_INFO("S4NOCPollChannel_poll: No data is available"); // if i remove it platform-test doesn't work @@ -297,7 +297,7 @@ void S4NOCPollChannel_ctor(S4NOCPollChannel *self, unsigned int destination_core self->receive_buffer_index = 0; self->receive_callback = NULL; self->federated_connection = NULL; - self->state = s4noc_handle_new_connections ? NETWORK_CHANNEL_STATE_UNINITIALIZED : NETWORK_CHANNEL_STATE_CONNECTED; + self->state = HANDLE_NEW_CONNECTIONS ? NETWORK_CHANNEL_STATE_UNINITIALIZED : NETWORK_CHANNEL_STATE_CONNECTED; self->destination_core = destination_core; memset(self->receive_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); memset(self->write_buffer, 0, S4NOC_CHANNEL_BUFFERSIZE); diff --git a/test/platform/patmos/s4noc_channel_test/Makefile b/test/platform/patmos/s4noc_channel_test/Makefile index ea4ae5f34..5a5ea6a6e 100644 --- a/test/platform/patmos/s4noc_channel_test/Makefile +++ b/test/platform/patmos/s4noc_channel_test/Makefile @@ -9,6 +9,7 @@ BUILD_DIR = $(CURDIR)/build # Source files SOURCES += $(SRC_DIR)/$(APP).c +CFLAGS += -DHANDLE_NEW_CONNECTIONS=0 # Output binary OUTPUT = $(BUILD_DIR)/$(APP).elf all : $(OUTPUT) diff --git a/test/platform/patmos/s4noc_channel_test/main.c b/test/platform/patmos/s4noc_channel_test/main.c index ec90acf72..671dd5791 100644 --- a/test/platform/patmos/s4noc_channel_test/main.c +++ b/test/platform/patmos/s4noc_channel_test/main.c @@ -31,7 +31,6 @@ void setUp(void) { /* init channel */ LF_INFO(NET,"init channel"); - S4NOC_set_handle_new_connections(false); S4NOCPollChannel_ctor(&sender_channel, DESTINATION_CORE); S4NOCPollChannel_ctor(&receiver_channel, SOURCE_CORE); diff --git a/test/platform/patmos/s4noc_channel_test/run.sh b/test/platform/patmos/s4noc_channel_test/run.sh index c1c3e9990..b9b6a6fed 100755 --- a/test/platform/patmos/s4noc_channel_test/run.sh +++ b/test/platform/patmos/s4noc_channel_test/run.sh @@ -1,9 +1,12 @@ #!/bin/bash + LF_MAIN=main BIN_DIR=./build + # Make test make clean make all + read -n 1 -t 10 -p "Choose action: [e]mulate or [f]pga? (default: e) " action action=${action:-e} if [[ "$action" == "e" ]]; then