mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-07-10 15:01:44 +02:00
implemented bus read and write
This commit is contained in:
@@ -78,6 +78,7 @@ constexpr RegisterField ModuleIndex{
|
||||
"""
|
||||
|
||||
postpend = r"""
|
||||
} // namespace Reg
|
||||
} // namespace sls
|
||||
// clang-format on
|
||||
"""
|
||||
|
||||
@@ -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 <typename DerivedServer>
|
||||
@@ -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<DerivedServer, VirtualMatterhornServer>,
|
||||
VirtualMemoryModel, HardwareMemoryModel>;
|
||||
|
||||
BusCommunication<IPCore, MemoryModel> 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<DerivedServer>::get_run_status(
|
||||
return static_cast<const DerivedServer *>(this)->get_run_status(socket);
|
||||
}
|
||||
|
||||
template <typename DerivedServer>
|
||||
ReturnCode BaseMatterhornServer<DerivedServer>::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<const DerivedServer *>(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<ReturnCode>(socket.sendResult(rx_params));
|
||||
}
|
||||
|
||||
template <typename DerivedServer>
|
||||
int64_t BaseMatterhornServer<DerivedServer>::getNumFrames() const {
|
||||
// bus_r(Reg::MH_SM_Frames_Reg);
|
||||
return 0; // TODO: implement
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
@@ -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
|
||||
|
||||
@@ -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 <typename MemoryModel>
|
||||
struct IpCoreRegisterBlock<IPCore, MemoryModel> {
|
||||
|
||||
std::map<IPCore, MemoryModel> &operator()() {
|
||||
memoryblocks_.try_emplace(
|
||||
IPCore::MH_RO_SM_AXI,
|
||||
MemoryModel{static_cast<uint32_t>(IPCore::MH_RO_SM_AXI),
|
||||
IPCORE_REGISTER_BLOCK_SIZE});
|
||||
memoryblocks_.try_emplace(
|
||||
IPCore::FHDR_AXI,
|
||||
MemoryModel{static_cast<uint32_t>(IPCore::FHDR_AXI),
|
||||
IPCORE_REGISTER_BLOCK_SIZE});
|
||||
memoryblocks_.try_emplace(
|
||||
IPCore::AURORA_STATUS,
|
||||
MemoryModel{static_cast<uint32_t>(IPCore::AURORA_STATUS),
|
||||
IPCORE_REGISTER_BLOCK_SIZE});
|
||||
memoryblocks_.try_emplace(
|
||||
IPCore::AURORA_STATUS2,
|
||||
MemoryModel{static_cast<uint32_t>(IPCore::AURORA_STATUS2),
|
||||
IPCORE_REGISTER_BLOCK_SIZE});
|
||||
memoryblocks_.try_emplace(
|
||||
IPCore::PACKETIZERREG,
|
||||
MemoryModel{static_cast<uint32_t>(IPCore::PACKETIZERREG),
|
||||
IPCORE_REGISTER_BLOCK_SIZE});
|
||||
memoryblocks_.try_emplace(
|
||||
IPCore::UNKNOWN, MemoryModel{static_cast<uint32_t>(IPCore::UNKNOWN),
|
||||
IPCORE_REGISTER_BLOCK_SIZE});
|
||||
|
||||
return memoryblocks_;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<IPCore, MemoryModel> memoryblocks_;
|
||||
};
|
||||
|
||||
} // namespace sls
|
||||
@@ -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
|
||||
@@ -5,7 +5,8 @@ namespace sls {
|
||||
MatterhornServer::MatterhornServer(uint16_t port)
|
||||
: BaseMatterhornServer<MatterhornServer>(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();
|
||||
|
||||
@@ -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<ReturnCode>(socket.sendResult(status));
|
||||
}
|
||||
|
||||
size_t VirtualMatterhornServer::get_frames() const {
|
||||
// TODO: dummy implementation for now
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace sls
|
||||
@@ -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
|
||||
|
||||
@@ -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 ®ister_) const;
|
||||
void writeRegister(const Register ®ister_, 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 ®ister_) 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 ®ister_, 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};
|
||||
};
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string_view>
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "MemoryModel.hpp"
|
||||
#include <fcntl.h>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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<volatile uint32_t *>(
|
||||
mmap(nullptr, size_memory_space, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
|
||||
IPCore_base_address));
|
||||
|
||||
if (mapped_memory_ptr ==
|
||||
reinterpret_cast<volatile uint32_t *>(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<uint32_t *>(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<uint32_t[]>(size_memory_space / sizeof(uint32_t));
|
||||
}
|
||||
|
||||
uint32_t *VirtualMemoryModel::getMappedMemoryPtr() const {
|
||||
return mapped_memory_ptr.get();
|
||||
}
|
||||
Reference in New Issue
Block a user