From ff9f7c27951d2f95901f276f755f0b6418ffaefe Mon Sep 17 00:00:00 2001 From: Alice Date: Fri, 1 May 2026 13:08:41 +0200 Subject: [PATCH] implemented bus read and write --- etc/generate_registerdefs.py | 1 + .../include/BaseMatterhornServer.h | 56 +++++++++++- .../matterhornServer/include/RegisterDefs.hpp | 26 +++--- .../include/SpecializedTemplates.h | 48 ++++++++++ .../include/VirtualMatterhornServer.h | 2 + .../matterhornServer/src/MatterhornServer.cpp | 3 +- .../src/VirtualMatterhornServer.cpp | 8 ++ .../slsDetectorServer_cpp/CMakeLists.txt | 1 + .../include/ArmBusCommunication.hpp | 88 +++++++++++++++++++ .../include/DetectorServer.h | 6 +- .../include/MemoryModel.hpp | 61 +++++++++++++ .../include/RegisterHelperStructs.hpp | 1 + .../slsDetectorServer_cpp/src/MemoryModel.cpp | 68 ++++++++++++++ 13 files changed, 355 insertions(+), 14 deletions(-) create mode 100644 slsDetectorServers/matterhornServer/include/SpecializedTemplates.h create mode 100644 slsDetectorServers/slsDetectorServer_cpp/include/ArmBusCommunication.hpp create mode 100644 slsDetectorServers/slsDetectorServer_cpp/include/MemoryModel.hpp rename slsDetectorServers/{matterhornServer => slsDetectorServer_cpp}/include/RegisterHelperStructs.hpp (98%) create mode 100644 slsDetectorServers/slsDetectorServer_cpp/src/MemoryModel.cpp diff --git a/etc/generate_registerdefs.py b/etc/generate_registerdefs.py index edc3ab733..2e83a9057 100644 --- a/etc/generate_registerdefs.py +++ b/etc/generate_registerdefs.py @@ -78,6 +78,7 @@ constexpr RegisterField ModuleIndex{ """ postpend = r""" +} // namespace Reg } // namespace sls // clang-format on """ diff --git a/slsDetectorServers/matterhornServer/include/BaseMatterhornServer.h b/slsDetectorServers/matterhornServer/include/BaseMatterhornServer.h index 176cfac9a..dbd4c400a 100644 --- a/slsDetectorServers/matterhornServer/include/BaseMatterhornServer.h +++ b/slsDetectorServers/matterhornServer/include/BaseMatterhornServer.h @@ -1,7 +1,10 @@ #pragma once +#include "ArmBusCommunication.hpp" #include "DetectorServer.h" +#include "MemoryModel.hpp" +#include "RegisterDefs.hpp" +#include "SpecializedTemplates.h" #include "TCPInterface.h" -// #include "communication_funcs.h" #include "fmt/format.h" #include "sls/logger.h" #include "sls/network_utils.h" @@ -16,6 +19,9 @@ namespace sls { +class VirtualMatterhornServer; // forward declaration +class MatterhornServer; // forward declaration + /// @brief Base class for Matterhorn Server, can be used to implement a virtual /// server for testing and actual server template @@ -45,6 +51,8 @@ class BaseMatterhornServer ReturnCode get_run_status(ServerInterface &socket) const; + ReturnCode get_receiver_parameters(ServerInterface &socket) const; + /** * @brief call function corresponding to the function ID received from the * client and send back the result @@ -54,9 +62,18 @@ class BaseMatterhornServer ReturnCode processFunction(const detFuncs function_id, ServerInterface &socket); + protected: + using MemoryModel = std::conditional_t< + std::is_same_v, + VirtualMemoryModel, HardwareMemoryModel>; + + BusCommunication busCommunication{}; + private: static std::string getMatterhornServerVersion(); + int64_t getNumFrames() const; + static constexpr uint8_t numUDPInterfaces = 1; // only one udp per module for now }; @@ -119,4 +136,41 @@ ReturnCode BaseMatterhornServer::get_run_status( return static_cast(this)->get_run_status(socket); } +template +ReturnCode BaseMatterhornServer::get_receiver_parameters( + ServerInterface &socket) const { + + slsDetectorDefs::rxParameters rx_params{}; + + rx_params.udpInterfaces = numUDPInterfaces; + + rx_params.udp_dstip = this->udpDetails[0].dstip; + + rx_params.udp_dstport = this->udpDetails[0].dstport; + + rx_params.udp_dstmac = this->udpDetails[0].dstmac; + + rx_params.frames = static_cast(this)->get_frames(); + + // rx_params.triggers = 0; + + // rx_params.expTimeNs = 0; + + // rx_params.periodNs = 0; + + // rx_params.dynamicRange = 0; + + // rx_params.timMode = AUTO_TIMING; + + // rx_params.counterMask = 0; + + return static_cast(socket.sendResult(rx_params)); +} + +template +int64_t BaseMatterhornServer::getNumFrames() const { + // bus_r(Reg::MH_SM_Frames_Reg); + return 0; // TODO: implement +} + } // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/matterhornServer/include/RegisterDefs.hpp b/slsDetectorServers/matterhornServer/include/RegisterDefs.hpp index 60335ccb4..d0aa2f914 100644 --- a/slsDetectorServers/matterhornServer/include/RegisterDefs.hpp +++ b/slsDetectorServers/matterhornServer/include/RegisterDefs.hpp @@ -1,19 +1,24 @@ - -// clang-format off +#pragma once #include "RegisterHelperStructs.hpp" namespace sls { /// @brief Enum for IP cores, value are adresses -constexpr enum class IPCore : uint32_t { - MH_RO_SM_AXI = 0, // dummy adresses for now - FHDR_AXI = 1, - AURORA_STATUS = 2, - AURORA_STATUS2 = 3, +enum class IPCore : uint32_t { + MH_RO_SM_AXI = 0xB0010000, + FHDR_AXI = 0xB0011000, + AURORA_STATUS = 0xB0014000, + AURORA_STATUS2 = 0xB0015000, PACKETIZERREG = 4, - UNKNOWN = 5 + UNKNOWN = 0x00000000 // dont know yet }; +constexpr size_t IPCORE_REGISTER_BLOCK_SIZE = + 0x1000; // size of each IP core address space in bytes // TODO: maybe add in + // other file definitions + +// clang-format off +namespace Reg { // Register definitions constexpr Register CTRL_Reg{IPCore::UNKNOWN, 0x0}; @@ -22,7 +27,7 @@ constexpr Register Status_Reg{IPCore::UNKNOWN, 0x4}; constexpr Register FPGAVersionReg{IPCore::UNKNOWN, 0x8}; -constexpr Register FPGA_GIT_HEAD{IPCore::UNKNOWN, 0xc}; +constexpr Register FPGA_GIT_HEAD_Reg{IPCore::UNKNOWN, 0xc}; constexpr Register FixedPatternReg{IPCore::UNKNOWN, 0x10}; @@ -116,7 +121,7 @@ constexpr RegisterField FPGADetType{ FPGAVersionReg, 24, 0xff}; constexpr RegisterField FPGA_GIT_HEAD{ - FPGA_GIT_HEAD, 0, 0xffffffff}; + FPGA_GIT_HEAD_Reg, 0, 0xffffffff}; constexpr RegisterField FixedPattern{ FixedPatternReg, 0, 0xffffffff}; @@ -235,6 +240,7 @@ constexpr RegisterField Coordy{ constexpr RegisterField Coordz{ PktCoordReg2, 0, 0xffff}; +} // namespace Reg } // namespace sls // clang-format on diff --git a/slsDetectorServers/matterhornServer/include/SpecializedTemplates.h b/slsDetectorServers/matterhornServer/include/SpecializedTemplates.h new file mode 100644 index 000000000..00e27cd2e --- /dev/null +++ b/slsDetectorServers/matterhornServer/include/SpecializedTemplates.h @@ -0,0 +1,48 @@ +#pragma once +#include "ArmBusCommunication.hpp" +#include "RegisterDefs.hpp" + +/** + * @file SpecializedTemplates.h + * @short contains specializations of the template classes for the Matterhorn + * server implementation + */ + +namespace sls { + +template +struct IpCoreRegisterBlock { + + std::map &operator()() { + memoryblocks_.try_emplace( + IPCore::MH_RO_SM_AXI, + MemoryModel{static_cast(IPCore::MH_RO_SM_AXI), + IPCORE_REGISTER_BLOCK_SIZE}); + memoryblocks_.try_emplace( + IPCore::FHDR_AXI, + MemoryModel{static_cast(IPCore::FHDR_AXI), + IPCORE_REGISTER_BLOCK_SIZE}); + memoryblocks_.try_emplace( + IPCore::AURORA_STATUS, + MemoryModel{static_cast(IPCore::AURORA_STATUS), + IPCORE_REGISTER_BLOCK_SIZE}); + memoryblocks_.try_emplace( + IPCore::AURORA_STATUS2, + MemoryModel{static_cast(IPCore::AURORA_STATUS2), + IPCORE_REGISTER_BLOCK_SIZE}); + memoryblocks_.try_emplace( + IPCore::PACKETIZERREG, + MemoryModel{static_cast(IPCore::PACKETIZERREG), + IPCORE_REGISTER_BLOCK_SIZE}); + memoryblocks_.try_emplace( + IPCore::UNKNOWN, MemoryModel{static_cast(IPCore::UNKNOWN), + IPCORE_REGISTER_BLOCK_SIZE}); + + return memoryblocks_; + } + + private: + std::map memoryblocks_; +}; + +} // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/matterhornServer/include/VirtualMatterhornServer.h b/slsDetectorServers/matterhornServer/include/VirtualMatterhornServer.h index 00377bf50..1d5c54765 100644 --- a/slsDetectorServers/matterhornServer/include/VirtualMatterhornServer.h +++ b/slsDetectorServers/matterhornServer/include/VirtualMatterhornServer.h @@ -21,6 +21,8 @@ class VirtualMatterhornServer ReturnCode initial_checks(ServerInterface &socket); ReturnCode get_run_status(ServerInterface &socket) const; + + size_t get_frames() const; }; } // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/matterhornServer/src/MatterhornServer.cpp b/slsDetectorServers/matterhornServer/src/MatterhornServer.cpp index 522d5b486..489e25963 100644 --- a/slsDetectorServers/matterhornServer/src/MatterhornServer.cpp +++ b/slsDetectorServers/matterhornServer/src/MatterhornServer.cpp @@ -5,7 +5,8 @@ namespace sls { MatterhornServer::MatterhornServer(uint16_t port) : BaseMatterhornServer(port) { - // TODO: when do i set the udp mac and ip ? + // map the IP core base addresses to memory + busCommunication.mapToMemory(); // TODO: should this happen in constructor? // should maybe be part of the constructor? tcpInterface->startTCPServer(); diff --git a/slsDetectorServers/matterhornServer/src/VirtualMatterhornServer.cpp b/slsDetectorServers/matterhornServer/src/VirtualMatterhornServer.cpp index ab4068c26..f044ec9b1 100644 --- a/slsDetectorServers/matterhornServer/src/VirtualMatterhornServer.cpp +++ b/slsDetectorServers/matterhornServer/src/VirtualMatterhornServer.cpp @@ -8,6 +8,9 @@ VirtualMatterhornServer::VirtualMatterhornServer(uint16_t port) udpDetails[0].srcip = LOCALHOSTIP_INT; + // map the IP core base addresses to virtual memory + busCommunication.mapToMemory(); + // should maybe be part of the constructor? tcpInterface->startTCPServer(); @@ -42,4 +45,9 @@ VirtualMatterhornServer::get_run_status(ServerInterface &socket) const { return static_cast(socket.sendResult(status)); } +size_t VirtualMatterhornServer::get_frames() const { + // TODO: dummy implementation for now + return 0; +} + } // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer_cpp/CMakeLists.txt b/slsDetectorServers/slsDetectorServer_cpp/CMakeLists.txt index 9060b99f2..2f4e60f07 100644 --- a/slsDetectorServers/slsDetectorServer_cpp/CMakeLists.txt +++ b/slsDetectorServers/slsDetectorServer_cpp/CMakeLists.txt @@ -1,6 +1,7 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/TCPInterface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/CommandLineOptions.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/MemoryModel.cpp ) add_library(slsServerObject OBJECT diff --git a/slsDetectorServers/slsDetectorServer_cpp/include/ArmBusCommunication.hpp b/slsDetectorServers/slsDetectorServer_cpp/include/ArmBusCommunication.hpp new file mode 100644 index 000000000..4e2c82936 --- /dev/null +++ b/slsDetectorServers/slsDetectorServer_cpp/include/ArmBusCommunication.hpp @@ -0,0 +1,88 @@ +#pragma once +#include "RegisterHelperStructs.hpp" +#include "fmt/format.h" +#include +#include +#include +#include +#include +#include +#include + +// TODO: maybe should be templated on address type (e.g. uint32_t or uint64_t) +// for more flexibility? + +namespace sls { + +template +struct IpCoreRegisterBlock { + + std::map &operator()() { + return memoryblocks_; + } + + private: + std::map memoryblocks_; +}; + +template +class BusCommunication { + + public: + BusCommunication() = default; + + void mapToMemory(); + + uint32_t readRegister(const Register ®ister_) const; + void writeRegister(const Register ®ister_, const uint32_t data) const; + + private: + /// @brief stores register blocks for each IP core + IpCoreRegisterBlock ipcoreregisterblocks; + + void bus_w(const uint32_t offset, const uint32_t baseadress, + const uint32_t data) const; + + uint32_t bus_r(const uint32_t offset, const uint32_t baseadress) const; +}; + +template +void BusCommunication::mapToMemory() { + + for (auto &map_elem : ipcoreregisterblocks()) { + map_elem.second.mapToMemory(); + } +} + +template +uint32_t BusCommunication::readRegister( + const Register ®ister_) const { + return bus_r(register_.offset_in_bytes, + static_cast(register_.ip_core)); +} + +template +void BusCommunication::writeRegister( + const Register ®ister_, const uint32_t data) const { + bus_w(register_.offset_in_bytes, static_cast(register_.ip_core), + data); +} + +template +uint32_t BusCommunication::bus_r( + const uint32_t offset, const uint32_t baseadress) const { + auto ptr1 = ipcoreregisterblocks()[baseadress].getMappedMemoryPtr() + + offset / (sizeof(uint32_t)); + return *ptr1; +} + +template +void BusCommunication::bus_w( + const uint32_t offset, const uint32_t baseadress, + const uint32_t data) const { + auto ptr1 = ipcoreregisterblocks()[baseadress].getMappedMemoryPtr() + + offset / (sizeof(uint32_t)); + *ptr1 = data; +} + +} // namespace sls \ No newline at end of file diff --git a/slsDetectorServers/slsDetectorServer_cpp/include/DetectorServer.h b/slsDetectorServers/slsDetectorServer_cpp/include/DetectorServer.h index 28781ef6c..c3170526d 100644 --- a/slsDetectorServers/slsDetectorServer_cpp/include/DetectorServer.h +++ b/slsDetectorServers/slsDetectorServer_cpp/include/DetectorServer.h @@ -67,7 +67,7 @@ template class DetectorServer { /// @brief TODO what is this? bool updateMode{true}; - /// @brief + /// @brief shared mempory with aquisition status mutable SharedMemory shm{ 0, 0}; // TODO: is mutable really neccessary? @@ -162,7 +162,9 @@ ReturnCode DetectorServer::processFunction( case detFuncs::F_GET_RUN_STATUS: return static_cast(this)->get_run_status( socket); - + case detFuncs::F_GET_RECEIVER_PARAMETERS: + return static_cast(this) + ->get_receiver_parameters(socket); default: LOG(logDEBUG) << "Checking specific server functions for function ID: " << function_id; diff --git a/slsDetectorServers/slsDetectorServer_cpp/include/MemoryModel.hpp b/slsDetectorServers/slsDetectorServer_cpp/include/MemoryModel.hpp new file mode 100644 index 000000000..d1b1a5aea --- /dev/null +++ b/slsDetectorServers/slsDetectorServer_cpp/include/MemoryModel.hpp @@ -0,0 +1,61 @@ +#include "fmt/format.h" +#include +#include + +/// @brief class to handle memory mapping and access for hardware IP cores +class HardwareMemoryModel { + + public: + HardwareMemoryModel(const uint32_t IPcore_base_address, + const size_t size_memory_space_); + + ~HardwareMemoryModel(); + + void mapToMemory(); + + void unmapMemory(); + + volatile uint32_t *getMappedMemoryPtr() const; + + private: + volatile uint32_t *mapped_memory_ptr{nullptr}; + + /// @brief offset of the IP core base address in the memory space, used for + /// mapping + const size_t IPCore_base_address{0}; + + /// @brief size mapped memory region [bytes] + const size_t size_memory_space{0}; +}; + +/// @brief class to handle memory mapping and access for virtual IP cores (e.g. +/// use software implementation of memory) +class VirtualMemoryModel { + + public: + VirtualMemoryModel(const uint32_t IPcore_base_address, + const size_t size_memory_space_); + + ~VirtualMemoryModel() = default; + + VirtualMemoryModel(const VirtualMemoryModel &) = delete; + VirtualMemoryModel &operator=(const VirtualMemoryModel &) = delete; + + VirtualMemoryModel(VirtualMemoryModel &&) noexcept = default; + VirtualMemoryModel & + operator=(VirtualMemoryModel &&) = delete; // const members + + void mapToMemory(); + + uint32_t *getMappedMemoryPtr() const; + + private: + std::unique_ptr mapped_memory_ptr; + + /// @brief offset of the IP core base address in the memory space, used for + /// mapping + const size_t IPCore_base_address{0}; + + /// @brief size mapped memory region [bytes] + const size_t size_memory_space{0}; +}; diff --git a/slsDetectorServers/matterhornServer/include/RegisterHelperStructs.hpp b/slsDetectorServers/slsDetectorServer_cpp/include/RegisterHelperStructs.hpp similarity index 98% rename from slsDetectorServers/matterhornServer/include/RegisterHelperStructs.hpp rename to slsDetectorServers/slsDetectorServer_cpp/include/RegisterHelperStructs.hpp index 5f561a285..c62273cdc 100644 --- a/slsDetectorServers/matterhornServer/include/RegisterHelperStructs.hpp +++ b/slsDetectorServers/slsDetectorServer_cpp/include/RegisterHelperStructs.hpp @@ -1,3 +1,4 @@ +#pragma once #include #include diff --git a/slsDetectorServers/slsDetectorServer_cpp/src/MemoryModel.cpp b/slsDetectorServers/slsDetectorServer_cpp/src/MemoryModel.cpp new file mode 100644 index 000000000..ce91b57d3 --- /dev/null +++ b/slsDetectorServers/slsDetectorServer_cpp/src/MemoryModel.cpp @@ -0,0 +1,68 @@ +#include "MemoryModel.hpp" +#include +#include +#include +#include +#include +#include + +HardwareMemoryModel::HardwareMemoryModel(const uint32_t IPcore_base_address, + const size_t size_memory_space_) + : IPCore_base_address(IPcore_base_address), + size_memory_space(size_memory_space_) {} + +void HardwareMemoryModel::mapToMemory() { + + int fd = open("/dev/mem", O_RDWR | O_SYNC, 0); + + if (fd == -1) { + throw std::runtime_error("Can't find /dev/mem"); + } + + mapped_memory_ptr = reinterpret_cast( + mmap(nullptr, size_memory_space, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + IPCore_base_address)); + + if (mapped_memory_ptr == + reinterpret_cast(MAP_FAILED)) { + throw std::runtime_error( + fmt::format("Failed to map base address: {}", + IPCore_base_address)); // TODO: needs ToString + } + + close(fd); +} + +volatile uint32_t *HardwareMemoryModel::getMappedMemoryPtr() const { + return mapped_memory_ptr; +} + +void HardwareMemoryModel::unmapMemory() { + + if (mapped_memory_ptr != nullptr) { + if (munmap(const_cast(mapped_memory_ptr), + size_memory_space) < 0) { + throw std::runtime_error( + fmt::format("Failed to unmap memory for IP core: {}", + IPCore_base_address)); // TODO: needs ToString + } + mapped_memory_ptr = nullptr; + } +} + +HardwareMemoryModel::~HardwareMemoryModel() { unmapMemory(); } + +VirtualMemoryModel::VirtualMemoryModel(const uint32_t IPcore_base_address, + const size_t size_memory_space_) + : IPCore_base_address(IPcore_base_address), + size_memory_space(size_memory_space_) {} + +void VirtualMemoryModel::mapToMemory() { + + mapped_memory_ptr = + std::make_unique(size_memory_space / sizeof(uint32_t)); +} + +uint32_t *VirtualMemoryModel::getMappedMemoryPtr() const { + return mapped_memory_ptr.get(); +} \ No newline at end of file