modified memory model

This commit is contained in:
2026-05-29 15:55:09 +02:00
parent 008c09cf04
commit 8f18eaca92
13 changed files with 408 additions and 73 deletions
@@ -9,8 +9,8 @@
#include <sys/mman.h>
#include <vector>
// TODO: maybe should be templated on address type (e.g. uint32_t or uint64_t)
// for more flexibility?
// TODO: maybe should be templated on address type (e.g. uint32_t register or
// uint64_t register) for more flexibility?
namespace sls {
@@ -38,14 +38,14 @@ class BusCommunication {
void mapToMemory();
uint32_t readRegister(const Register &register_) const;
void writeRegister(const Register &register_, const uint32_t data) const;
void writeRegister(const Register &register_, const uint32_t data);
private:
/// @brief stores register blocks for each IP core
IpCoreRegisterBlock<IPCoreEnumType, MemoryModel> ipcoreregisterblocks;
void bus_w(const uint32_t offset, IPCoreEnumType baseadress,
const uint32_t data) const;
const uint32_t data);
uint32_t bus_r(const uint32_t offset, IPCoreEnumType baseadress) const;
};
@@ -66,7 +66,7 @@ uint32_t BusCommunication<IPCoreEnumType, MemoryModel>::readRegister(
template <typename IPCoreEnumType, typename MemoryModel>
void BusCommunication<IPCoreEnumType, MemoryModel>::writeRegister(
const Register &register_, const uint32_t data) const {
const Register &register_, const uint32_t data) {
bus_w(register_.offset_in_bytes, register_.ip_core, data);
}
@@ -81,7 +81,7 @@ uint32_t BusCommunication<IPCoreEnumType, MemoryModel>::bus_r(
template <typename IPCoreEnumType, typename MemoryModel>
void BusCommunication<IPCoreEnumType, MemoryModel>::bus_w(
const uint32_t offset, const IPCoreEnumType baseadress,
const uint32_t data) const {
const uint32_t data) {
auto ptr1 = ipcoreregisterblocks().at(baseadress).getMappedMemoryPtr() +
offset / (sizeof(uint32_t));
*ptr1 = data;
@@ -26,6 +26,19 @@ struct UDPInfo {
};
using ReturnCode = slsDetectorDefs::ReturnCode;
/// @brief generates a random locally administered unicast MAC address for the
/// source UDP
/// @return generated MAC address
inline uint64_t generaterandomMacAddress() {
uint64_t mac =
0xAA0000000000; // locally administered unicast address (0xA: 0b1010) //
// TODO maybe 0x02000000000 better?
for (int i = 2; i < 5; ++i) {
mac |= (static_cast<uint64_t>(rand() % 256) << (i * 8));
}
return mac;
}
/// @brief Shared memory structure for stop server to store run status
struct acquisitionStatus {
@@ -65,12 +78,17 @@ template <typename DerivedDetectorServer> class DetectorServer {
udpDetails{}; // TODO: for now only one receiver per module
/// @brief TODO what is this?
bool updateMode{true};
bool updateMode{
false}; // what should the default be - can update module size etc.
/// @brief shared mempory with aquisition status
mutable SharedMemory<acquisitionStatus> shm{
0, 0}; // TODO: is mutable really neccessary?
/// @brief sets source UDP MAC address in udpDetails and updates udp header
/// @param srcmac
void updateSrcMacAddress(const uint64_t srcmac);
private:
/// @brief creates and maps shared memory
void createSharedMemory();
@@ -102,6 +120,14 @@ template <typename DerivedDetectorServer> class DetectorServer {
ReturnCode set_destination_udp_port(ServerInterface &socket);
ReturnCode get_destination_udp_port(ServerInterface &socket) const;
ReturnCode get_num_frames(ServerInterface &socket) const;
ReturnCode set_num_frames(ServerInterface &socket);
ReturnCode get_num_triggers(ServerInterface &socket) const;
ReturnCode set_num_triggers(ServerInterface &socket);
};
template <typename DerivedDetectorServer>
@@ -162,9 +188,20 @@ ReturnCode DetectorServer<DerivedDetectorServer>::processFunction(
case detFuncs::F_GET_RUN_STATUS:
return static_cast<DerivedDetectorServer *>(this)->get_run_status(
socket);
case detFuncs::F_GET_NUM_FRAMES:
return get_num_frames(socket);
case detFuncs::F_SET_NUM_FRAMES:
return set_num_frames(socket);
case detFuncs::F_GET_NUM_TRIGGERS:
return get_num_triggers(socket);
case detFuncs::F_SET_NUM_TRIGGERS:
return set_num_triggers(socket);
case detFuncs::F_GET_RECEIVER_PARAMETERS:
return static_cast<DerivedDetectorServer *>(this)
->get_receiver_parameters(socket);
case detFuncs::F_SET_POSITION:
return static_cast<DerivedDetectorServer *>(this)->set_module_position(
socket);
default:
LOG(logDEBUG) << "Checking specific server functions for function ID: "
<< function_id;
@@ -189,6 +226,30 @@ void DetectorServer<DerivedDetectorServer>::createSharedMemory() {
}
}
template <typename DerivedDetectorServer>
void DetectorServer<DerivedDetectorServer>::updateSrcMacAddress(
const uint64_t srcmac) {
LOG(logINFO) << "Updating source MAC address to: "
<< fmt::format("{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
(srcmac >> 40) & 0xff, (srcmac >> 32) & 0xff,
(srcmac >> 24) & 0xff, (srcmac >> 16) & 0xff,
(srcmac >> 8) & 0xff, srcmac & 0xff);
if ((srcmac & 0x020000000000) == 0) {
LOG(logERROR) << "Invalid source MAC address: unicast bit or local "
"administration bit is not set";
throw std::invalid_argument("Invalid source MAC address: unicast bit "
"or local administration bit is not set");
}
udpDetails[0].srcmac = srcmac;
// TODO: update UDP header with new source MAC address
// TODO: do i need to keep track of the configured member ?
}
template <typename DerivedDetectorServer>
ReturnCode DetectorServer<DerivedDetectorServer>::get_update_mode(
ServerInterface &socket) const {
@@ -210,8 +271,13 @@ ReturnCode DetectorServer<DerivedDetectorServer>::set_source_udp_mac(
return ReturnCode::FAIL;
}
udpDetails[0].srcmac = newsrcudpMac;
// TODO: configuremac, check unicast address
try {
updateSrcMacAddress(newsrcudpMac);
} catch (const std::invalid_argument &e) {
LOG(logERROR) << "Failed to update source MAC address: " << e.what();
return ReturnCode::FAIL;
}
return static_cast<ReturnCode>(socket.Send(ReturnCode::OK));
}
@@ -315,4 +381,71 @@ ReturnCode DetectorServer<DerivedDetectorServer>::get_destination_udp_port(
return static_cast<ReturnCode>(socket.sendResult(udpDetails[0].dstport));
};
template <typename DerivedDetectorServer>
ReturnCode DetectorServer<DerivedDetectorServer>::get_num_frames(
ServerInterface &socket) const {
uint64_t num_frames{};
try {
num_frames =
static_cast<const DerivedDetectorServer *>(this)->getNumFrames();
} catch (const std::exception &e) {
LOG(logERROR) << "Failed to get number of frames: " << e.what();
return ReturnCode::FAIL;
}
return static_cast<ReturnCode>(socket.sendResult(num_frames));
}
template <typename DerivedDetectorServer>
ReturnCode
DetectorServer<DerivedDetectorServer>::set_num_frames(ServerInterface &socket) {
int64_t num_frames{};
try {
int ret = socket.Receive(num_frames);
} catch (const SocketError &e) {
LOG(logERROR) << "Failed to receive number of frames: " << e.what();
return ReturnCode::FAIL;
}
try {
static_cast<DerivedDetectorServer *>(this)->setNumFrames(num_frames);
} catch (const std::exception &e) {
LOG(logERROR) << "Failed to set number of frames: " << e.what();
return ReturnCode::FAIL;
}
return static_cast<ReturnCode>(socket.Send(ReturnCode::OK));
}
template <typename DerivedDetectorServer>
ReturnCode DetectorServer<DerivedDetectorServer>::get_num_triggers(
ServerInterface &socket) const {
uint32_t num_triggers{};
try {
num_triggers =
static_cast<const DerivedDetectorServer *>(this)->getNumTriggers();
} catch (const std::exception &e) {
LOG(logERROR) << "Failed to get number of triggers: " << e.what();
return ReturnCode::FAIL;
}
return static_cast<ReturnCode>(socket.sendResult(num_triggers));
}
template <typename DerivedDetectorServer>
ReturnCode DetectorServer<DerivedDetectorServer>::set_num_triggers(
ServerInterface &socket) {
uint32_t num_triggers{};
try {
int ret = socket.Receive(num_triggers);
} catch (const SocketError &e) {
LOG(logERROR) << "Failed to receive number of triggers: " << e.what();
return ReturnCode::FAIL;
}
try {
static_cast<DerivedDetectorServer *>(this)->setNumTriggers(
num_triggers);
} catch (const std::exception &e) {
LOG(logERROR) << "Failed to set number of triggers: " << e.what();
return ReturnCode::FAIL;
}
return static_cast<ReturnCode>(socket.Send(ReturnCode::OK));
}
} // namespace sls
@@ -1,6 +1,6 @@
#include "fmt/format.h"
#include <cstdint>
#include <memory>
#include <vector>
/// @brief class to handle memory mapping and access for hardware IP cores
class HardwareMemoryModel {
@@ -38,19 +38,14 @@ class VirtualMemoryModel {
~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;
uint32_t *getMappedMemoryPtr();
const uint32_t *getMappedMemoryPtr() const;
private:
std::unique_ptr<uint32_t[]> mapped_memory_ptr;
std::vector<uint32_t> mapped_memory{};
/// @brief offset of the IP core base address in the memory space, used for
/// mapping
@@ -6,6 +6,7 @@ namespace sls {
enum class IPCore : uint32_t; // forward declaration of IPCore enum class
/// @brief struct representing 32 bit register
struct Register {
/// @brief IP core address space
const IPCore ip_core{}; // TODO replace by enum type
@@ -27,4 +28,27 @@ struct RegisterField {
const uint32_t bitmask{};
};
// TODO: maybe static member function of RegisterField?
template <typename T>
void setRegisterField(uint32_t &registervalue, const RegisterField &reg_field,
T field_value) {
// Clear the bits corresponding to the field
registervalue &= ~(reg_field.bitmask << reg_field.bit_position);
// Set the new value for the field
registervalue |= (static_cast<uint32_t>(field_value) & reg_field.bitmask)
<< reg_field.bit_position;
}
template <typename T>
T getRegisterField(const uint32_t &registervalue,
const RegisterField &reg_field) {
// Extract the bits corresponding to the field and shift them to get the
// value
auto field_value =
(registervalue >> reg_field.bit_position) & reg_field.bitmask;
return static_cast<T>(field_value);
}
} // namespace sls