From d7952daa4aabe71128db5bf280357418184fa161 Mon Sep 17 00:00:00 2001 From: Alejandro Homs Puron Date: Thu, 2 Apr 2020 22:34:03 +0200 Subject: [PATCH] Add Eiger BEB FPGA frame write & read ptr diff readout to detect active xfer * Call detector stopAcquisition if Model::isXferActive --- include/SlsDetectorCamera.h | 9 ++++++ include/SlsDetectorEiger.h | 10 ++++++ include/SlsDetectorModel.h | 2 ++ sip/SlsDetectorEiger.sip | 4 +++ sip/SlsDetectorModel.sip | 2 ++ src/SlsDetectorCamera.cpp | 18 +++++++++-- src/SlsDetectorEiger.cpp | 33 +++++++++++++++++++ tango/SlsDetector.py | 5 +++ test/test_eiger_fpga_frame_ptr_diff.py | 45 ++++++++++++++++++++++++++ 9 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 test/test_eiger_fpga_frame_ptr_diff.py diff --git a/include/SlsDetectorCamera.h b/include/SlsDetectorCamera.h index 8fda5e5..a8e4ad2 100644 --- a/include/SlsDetectorCamera.h +++ b/include/SlsDetectorCamera.h @@ -26,6 +26,7 @@ #include "SlsDetectorArgs.h" #include "SlsDetectorReceiver.h" #include "SlsDetectorCPUAffinity.h" +#include "SlsDetectorBebTools.h" #include "slsDetectorUsers.h" @@ -172,6 +173,13 @@ private: typedef std::queue FrameQueue; typedef std::vector > RecvList; + struct Beb { + BebShell shell; + BebFpgaMem fpga_mem; + Beb(const std::string& host_name); + }; + typedef std::vector > BebList; + struct AppInputData { DEB_CLASS_NAMESPC(DebModCamera, "Camera::AppInputData", @@ -289,6 +297,7 @@ private: Cond m_cond; AutoPtr m_input_data; AutoPtr m_det; + BebList m_beb_list; FrameMap m_frame_map; RecvList m_recv_list; TrigMode m_trig_mode; diff --git a/include/SlsDetectorEiger.h b/include/SlsDetectorEiger.h index a8f44ca..fd5e9ce 100644 --- a/include/SlsDetectorEiger.h +++ b/include/SlsDetectorEiger.h @@ -47,6 +47,8 @@ class Eiger : public Model typedef unsigned short Word; typedef unsigned int Long; + typedef std::vector PtrDiffList; + typedef Defs::ClockDiv ClockDiv; enum ParallelMode { @@ -265,6 +267,10 @@ class Eiger : public Model Geometry *getGeometry() { return &m_geom; } + void getFpgaFramePtrDiff(PtrDiffList& ptr_diff); + + virtual bool isXferActive(); + protected: virtual int getNbFrameMapItems(); virtual void updateFrameMapItems(FrameMap *map); @@ -608,6 +614,10 @@ class Eiger : public Model static const LinScale ChipXfer2Buff; static const LinScale ChipRealReadout; + static const unsigned long BebFpgaWritePtrAddr; + static const unsigned long BebFpgaReadPtrAddr; + static const unsigned long BebFpgaPtrRange; + Geometry m_geom; CorrList m_corr_list; RecvList m_recv_list; diff --git a/include/SlsDetectorModel.h b/include/SlsDetectorModel.h index 7aa8046..2d1d9a5 100644 --- a/include/SlsDetectorModel.h +++ b/include/SlsDetectorModel.h @@ -93,6 +93,8 @@ class Model virtual void processBadItemFrame(FrameType frame, int item, char *bptr) = 0; + virtual bool isXferActive() = 0; + protected: void updateCameraModel(); void updateTimeRanges(); diff --git a/sip/SlsDetectorEiger.sip b/sip/SlsDetectorEiger.sip index af00fb9..ce63dfc 100644 --- a/sip/SlsDetectorEiger.sip +++ b/sip/SlsDetectorEiger.sip @@ -93,6 +93,10 @@ class Eiger : public SlsDetector::Model void setTxFrameDelay(int tx_frame_delay); void getTxFrameDelay(int& tx_frame_delay /Out/); + void getFpgaFramePtrDiff(std::vector& ptr_diff /Out/); + + virtual bool isXferActive(); + protected: virtual int getNbFrameMapItems(); virtual void updateFrameMapItems(FrameMap *map); diff --git a/sip/SlsDetectorModel.sip b/sip/SlsDetectorModel.sip index a373edb..01c526e 100644 --- a/sip/SlsDetectorModel.sip +++ b/sip/SlsDetectorModel.sip @@ -72,6 +72,8 @@ public: virtual void processBadItemFrame(unsigned long frame, int item, char *bptr) = 0; + virtual bool isXferActive() = 0; + protected: void updateCameraModel(); diff --git a/src/SlsDetectorCamera.cpp b/src/SlsDetectorCamera.cpp index df261fb..0111322 100644 --- a/src/SlsDetectorCamera.cpp +++ b/src/SlsDetectorCamera.cpp @@ -84,6 +84,11 @@ void Camera::AppInputData::parseConfigFile() } } +Camera::Beb::Beb(const std::string& host_name) + : shell(host_name), fpga_mem(shell) +{ +} + Camera::AcqThread::ExceptionCleanUp::ExceptionCleanUp(AcqThread& thread) : Thread::ExceptionCleanUp(thread) { @@ -275,7 +280,10 @@ void Camera::AcqThread::stopAcq() { DEB_MEMBER_FUNCT(); slsDetectorUsers *det = m_cam->m_det; - if (m_cam->getDetStatus() == Defs::Running) { + DetStatus det_status = m_cam->getDetStatus(); + bool xfer_active = m_cam->m_model->isXferActive(); + DEB_ALWAYS() << DEB_VAR2(det_status, xfer_active); + if ((det_status == Defs::Running) || xfer_active) { DEB_TRACE() << "calling stopAcquisition"; det->stopAcquisition(); Timestamp t0 = Timestamp::now(); @@ -355,6 +363,12 @@ Camera::Camera(string config_fname, int det_id) DEB_TRACE() << "Forcing 10G Ethernet flow control"; setFlowControl10G(true); } + + for (int i = 0; i < getNbDetModules(); ++i) { + const string& host_name = m_input_data->host_name_list[i]; + Beb *beb = new Beb(host_name); + m_beb_list.push_back(beb); + } } Camera::~Camera() @@ -664,7 +678,7 @@ void Camera::setRecvCPUAffinity(const RecvCPUAffinityList& recv_affinity_list) RecvCPUAffinityList::const_iterator ait = recv_affinity_list.begin(); RecvList::iterator rit = m_recv_list.begin(); - for (int i = 0; i < nb_recv; ++i, ++ait, ++rit) { + for (unsigned int i = 0; i < nb_recv; ++i, ++ait, ++rit) { Model::Recv *recv = m_model->getRecv(i); const RecvCPUAffinity& aff = *ait; recv->setNbProcessingThreads(aff.recv_threads.size()); diff --git a/src/SlsDetectorEiger.cpp b/src/SlsDetectorEiger.cpp index a2060b1..18079b7 100644 --- a/src/SlsDetectorEiger.cpp +++ b/src/SlsDetectorEiger.cpp @@ -43,6 +43,10 @@ const double Eiger::MaxFebBebBandwidth = 25600; // Mbit/s const Eiger::LinScale Eiger::ChipXfer2Buff(2.59, 0.85); const Eiger::LinScale Eiger::ChipRealReadout(1.074, -4); +const unsigned long Eiger::BebFpgaWritePtrAddr = 0xD10000C4; +const unsigned long Eiger::BebFpgaReadPtrAddr = 0xD10000E4; +const unsigned long Eiger::BebFpgaPtrRange = 0x10000000; + Eiger::CorrBase::CorrBase(Eiger *eiger) : m_eiger(eiger) { @@ -1474,6 +1478,35 @@ double Eiger::getBorderCorrFactor(int det, int line) } } +void Eiger::getFpgaFramePtrDiff(PtrDiffList& ptr_diff) +{ + DEB_MEMBER_FUNCT(); + Camera::BebList& beb_list = getCamera()->m_beb_list; + for (int i = 0; i != beb_list.size(); ++i) { + BebFpgaMem& fpga_mem = beb_list[i]->fpga_mem; + unsigned long wr_ptr = fpga_mem.read(BebFpgaWritePtrAddr); + unsigned long rd_ptr = fpga_mem.read(BebFpgaReadPtrAddr); + if (rd_ptr > wr_ptr) + wr_ptr += BebFpgaPtrRange; + unsigned long diff = wr_ptr - rd_ptr; + DEB_RETURN() << DEB_VAR2(i, diff); + ptr_diff.push_back(diff); + } +} + +bool Eiger::isXferActive() +{ + DEB_MEMBER_FUNCT(); + PtrDiffList ptr_diff; + getFpgaFramePtrDiff(ptr_diff); + PtrDiffList::const_iterator it, end = ptr_diff.end(); + bool xfer_active = false; + for (it = ptr_diff.begin(); (it != end) && !xfer_active; ++it) + xfer_active = (*it != 0); + DEB_RETURN() << DEB_VAR1(xfer_active); + return xfer_active; +} + ostream& lima::SlsDetector::operator <<(ostream& os, Eiger::ParallelMode mode) { const char *name = "Invalid"; diff --git a/tango/SlsDetector.py b/tango/SlsDetector.py index e8677d4..43aaf93 100644 --- a/tango/SlsDetector.py +++ b/tango/SlsDetector.py @@ -88,6 +88,7 @@ class SlsDetector(PyTango.Device_4Impl): 'fixed_clock_div', 'threshold_energy', 'tx_frame_delay', + 'fpga_frame_ptr_diff', ] def __init__(self,*args) : @@ -662,6 +663,10 @@ class SlsDetectorClass(PyTango.DeviceClass): [[PyTango.DevLong, PyTango.SCALAR, PyTango.READ_WRITE]], + 'fpga_frame_ptr_diff': + [[PyTango.DevULong, + PyTango.SPECTRUM, + PyTango.READ, 64]], } def __init__(self,name) : diff --git a/test/test_eiger_fpga_frame_ptr_diff.py b/test/test_eiger_fpga_frame_ptr_diff.py new file mode 100644 index 0000000..02ee1dc --- /dev/null +++ b/test/test_eiger_fpga_frame_ptr_diff.py @@ -0,0 +1,45 @@ +import sys +import time +import contextlib +import numpy as np +from PyTango import DeviceProxy + +dev_name = 'id00/slsdetector/eiger500k' + +if len(sys.argv) > 1: + dev_name = sys.argv[1] + +eiger_dev = DeviceProxy(dev_name) +data = [] + +ref = eiger_dev.fpga_frame_ptr_diff +nb_hosts = len(ref) +zeros = np.zeros((nb_hosts,), 'uint32') +if (ref != zeros).any(): + raise RuntimeError(f'Invalid reference: {ref}') + +max_val = np.array(zeros) +max_i = np.array(zeros) +t0 = None +print('Ready') +while True: + i = len(data) + d = eiger_dev.fpga_frame_ptr_diff + d > max_val + if (d != ref).all(): + t = time.time() + if t0 is None: + t0 = t + print('Starting') + data.append(((t - t0), d)) + elif i > 0: + break + +elapsed = time.time() - t0 +print(f'Finished: {elapsed:.3f} sec, {len(data)} points') + +ofname = '/tmp/fpga_frame_ptr_diff.dat' +with contextlib.closing(open(ofname, 'wt')) as f: + for t0, d in data: + f.write('\t'.join([str(x) for x in [t0] + list(d)]) + '\n') +print(f'Saved {ofname}') -- GitLab