implemented bus read and write

This commit is contained in:
2026-05-29 15:54:29 +02:00
parent 55b5511485
commit ff9f7c2795
13 changed files with 355 additions and 14 deletions
@@ -0,0 +1,88 @@
#pragma once
#include "RegisterHelperStructs.hpp"
#include "fmt/format.h"
#include <cstdint>
#include <fcntl.h>
#include <map>
#include <memory>
#include <stdexcept>
#include <sys/mman.h>
#include <vector>
// TODO: maybe should be templated on address type (e.g. uint32_t or uint64_t)
// for more flexibility?
namespace sls {
template <typename IPCoreEnumType, typename MemoryModel>
struct IpCoreRegisterBlock {
std::map<IPCoreEnumType, MemoryModel> &operator()() {
return memoryblocks_;
}
private:
std::map<IPCoreEnumType, MemoryModel> memoryblocks_;
};
template <typename IPCoreEnumType, typename MemoryModel>
class BusCommunication {
public:
BusCommunication() = default;
void mapToMemory();
uint32_t readRegister(const Register &register_) const;
void writeRegister(const Register &register_, const uint32_t data) const;
private:
/// @brief stores register blocks for each IP core
IpCoreRegisterBlock<IPCoreEnumType, MemoryModel> 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 <typename IPCoreEnumType, typename MemoryModel>
void BusCommunication<IPCoreEnumType, MemoryModel>::mapToMemory() {
for (auto &map_elem : ipcoreregisterblocks()) {
map_elem.second.mapToMemory();
}
}
template <typename IPCoreEnumType, typename MemoryModel>
uint32_t BusCommunication<IPCoreEnumType, MemoryModel>::readRegister(
const Register &register_) const {
return bus_r(register_.offset_in_bytes,
static_cast<uint32_t>(register_.ip_core));
}
template <typename IPCoreEnumType, typename MemoryModel>
void BusCommunication<IPCoreEnumType, MemoryModel>::writeRegister(
const Register &register_, const uint32_t data) const {
bus_w(register_.offset_in_bytes, static_cast<uint32_t>(register_.ip_core),
data);
}
template <typename IPCoreEnumType, typename MemoryModel>
uint32_t BusCommunication<IPCoreEnumType, MemoryModel>::bus_r(
const uint32_t offset, const uint32_t baseadress) const {
auto ptr1 = ipcoreregisterblocks()[baseadress].getMappedMemoryPtr() +
offset / (sizeof(uint32_t));
return *ptr1;
}
template <typename IPCoreEnumType, typename MemoryModel>
void BusCommunication<IPCoreEnumType, MemoryModel>::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
@@ -67,7 +67,7 @@ template <typename DerivedDetectorServer> class DetectorServer {
/// @brief TODO what is this?
bool updateMode{true};
/// @brief
/// @brief shared mempory with aquisition status
mutable SharedMemory<acquisitionStatus> shm{
0, 0}; // TODO: is mutable really neccessary?
@@ -162,7 +162,9 @@ ReturnCode DetectorServer<DerivedDetectorServer>::processFunction(
case detFuncs::F_GET_RUN_STATUS:
return static_cast<DerivedDetectorServer *>(this)->get_run_status(
socket);
case detFuncs::F_GET_RECEIVER_PARAMETERS:
return static_cast<DerivedDetectorServer *>(this)
->get_receiver_parameters(socket);
default:
LOG(logDEBUG) << "Checking specific server functions for function ID: "
<< function_id;
@@ -0,0 +1,61 @@
#include "fmt/format.h"
#include <cstdint>
#include <memory>
/// @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<uint32_t[]> 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};
};
@@ -0,0 +1,30 @@
#pragma once
#include <cstdint>
#include <string_view>
namespace sls {
enum class IPCore : uint32_t; // forward declaration of IPCore enum class
struct Register {
/// @brief IP core address space
const IPCore ip_core{}; // TODO replace by enum type
/// @brief Offset of the register in bytes from the base address of the IP
/// core
const uint32_t offset_in_bytes{};
};
struct RegisterField {
/// @brief Register to which the field belongs
const Register register_{};
/// @brief Bit position of the least significant bit of the field in the
/// register
const uint32_t bit_position{};
/// @brief Bitmask for the field
const uint32_t bitmask{};
};
} // namespace sls