mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-08-05 13:32:25 +02:00
modified memory model
This commit is contained in:
@@ -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 ®ister_) const;
|
||||
void writeRegister(const Register ®ister_, const uint32_t data) const;
|
||||
void writeRegister(const Register ®ister_, 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 ®ister_, const uint32_t data) const {
|
||||
const Register ®ister_, 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 ®istervalue, const RegisterField ®_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 ®istervalue,
|
||||
const RegisterField ®_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
|
||||
Reference in New Issue
Block a user