txdelay for all modules (#584)

* setting txdelay for all modules for eiger, jungfrau and m3
* added txdelay in python and renamed txndelay_ to txdelay_
* call in parallel
This commit is contained in:
Dhanya Thattil 2022-11-24 11:57:26 +01:00 committed by GitHub
parent 928d778fb1
commit 61c31ed44a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 250 additions and 21 deletions

View File

@ -127,6 +127,7 @@ This document describes the differences between v7.0.0 and v6.x.x
- gui nios temperature added - gui nios temperature added
- detector header change (bunchid, reserved, debug, roundRnumber) ->detSpec1 - 4 - detector header change (bunchid, reserved, debug, roundRnumber) ->detSpec1 - 4
-ctb and moench (allowing all clkdivs (totaldiv was a float instead of int)) -ctb and moench (allowing all clkdivs (totaldiv was a float instead of int))
- txndelay_ ->txdelay_ (also for python), txdelay = delay for all with step
- hardwareversion - hardwareversion
- jungfrau connected moduleid to detid_jungfrau.txt on board - jungfrau connected moduleid to detid_jungfrau.txt on board

View File

@ -627,25 +627,46 @@ class Detector(CppDetectorApi):
@property @property
@element @element
def txndelay_frame(self): def txdelay(self):
"""
[Eiger][Jungfrau][Mythen3] Set transmission delay for all modules in the detector using the step size provided.
Note
----
Sets up the following for every module:\n
\t\t[Eiger] txdelay_left to (2 * mod_index * n_delay), \n
\t\t[Eiger] txdelay_right to ((2 * mod_index + 1) * n_delay) and \n
\t\t[Eiger] txdelay_frame to (2 *num_modules * n_delay) \n
\t\t[Jungfrau][Mythen3] txdelay_frame to (num_modules * n_delay)\n\n
Please refer txdelay_left, txdelay_right and txdelay_frame for details.
"""
return self.getTransmissionDelay()
@txdelay.setter
def txdelay(self, args):
ut.set_using_dict(self.setTransmissionDelay, args)
@property
@element
def txdelay_frame(self):
""" """
[Eiger][Jungfrau][Mythen3] Transmission delay of first udp packet being streamed out of the module.\n [Eiger][Jungfrau][Mythen3] Transmission delay of first udp packet being streamed out of the module.\n
Note Note
---- ----
[Jungfrau] [0-31] Each value represents 1 ms. \n [Jungfrau] [0-31] Each value represents 1 ms. \n
[Eiger] Additional delay to txndelay_left and txndelay_right. Each value represents 10ns. Typical value is 50000. \n [Eiger] Additional delay to txdelay_left and txdelay_right. Each value represents 10ns. Typical value is 50000. \n
[Mythen3] [0-16777215] Each value represents 8 ns (125 MHz clock), max is 134 ms. [Mythen3] [0-16777215] Each value represents 8 ns (125 MHz clock), max is 134 ms.
""" """
return self.getTransmissionDelayFrame() return self.getTransmissionDelayFrame()
@txndelay_frame.setter @txdelay_frame.setter
def txndelay_frame(self, args): def txdelay_frame(self, args):
ut.set_using_dict(self.setTransmissionDelayFrame, args) ut.set_using_dict(self.setTransmissionDelayFrame, args)
@property @property
@element @element
def txndelay_left(self): def txdelay_left(self):
"""[Eiger] Transmission delay of first packet in an image being streamed out of the module's left UDP port. """[Eiger] Transmission delay of first packet in an image being streamed out of the module's left UDP port.
Note Note
@ -654,13 +675,13 @@ class Detector(CppDetectorApi):
""" """
return self.getTransmissionDelayLeft() return self.getTransmissionDelayLeft()
@txndelay_left.setter @txdelay_left.setter
def txndelay_left(self, args): def txdelay_left(self, args):
ut.set_using_dict(self.setTransmissionDelayLeft, args) ut.set_using_dict(self.setTransmissionDelayLeft, args)
@property @property
@element @element
def txndelay_right(self): def txdelay_right(self):
""" """
[Eiger] Transmission delay of first packet in an image being streamed out of the module's right UDP port. [Eiger] Transmission delay of first packet in an image being streamed out of the module's right UDP port.
@ -670,8 +691,8 @@ class Detector(CppDetectorApi):
""" """
return self.getTransmissionDelayRight() return self.getTransmissionDelayRight()
@txndelay_right.setter @txdelay_right.setter
def txndelay_right(self, args): def txdelay_right(self, args):
ut.set_using_dict(self.setTransmissionDelayRight, args) ut.set_using_dict(self.setTransmissionDelayRight, args)
@property @property

View File

@ -783,6 +783,12 @@ void init_det(py::module &m) {
(void (Detector::*)(int, sls::Positions)) & (void (Detector::*)(int, sls::Positions)) &
Detector::setTransmissionDelayRight, Detector::setTransmissionDelayRight,
py::arg(), py::arg() = Positions{}); py::arg(), py::arg() = Positions{});
CppDetectorApi.def("getTransmissionDelay",
(int (Detector::*)() const) &
Detector::getTransmissionDelay);
CppDetectorApi.def(
"setTransmissionDelay",
(void (Detector::*)(int)) & Detector::setTransmissionDelay, py::arg());
CppDetectorApi.def("getUseReceiverFlag", CppDetectorApi.def("getUseReceiverFlag",
(Result<bool>(Detector::*)(sls::Positions) const) & (Result<bool>(Detector::*)(sls::Positions) const) &
Detector::getUseReceiverFlag, Detector::getUseReceiverFlag,

View File

@ -835,6 +835,20 @@ class Detector {
* port * port
*/ */
void setTransmissionDelayRight(int value, Positions pos = {}); void setTransmissionDelayRight(int value, Positions pos = {});
/** [Eiger][Jungfrau] */
int getTransmissionDelay() const;
/**
* [Eiger][Jungfrau][Mythen3] Set transmission delay for all modules in the
* detector using the step size provided.Sets up \n\t\t[Eiger] txdelay_left
* to (2 * mod_index * n_delay), \n\t\t[Eiger] txdelay_right to ((2 *
* mod_index + 1) * n_delay) and \n\t\t[Eiger] txdelay_frame to (2
* *num_modules * n_delay) \n\t\t[Jungfrau][Mythen3] txdelay_frame to
* (num_modules * n_delay) \nfor every module.
*/
void setTransmissionDelay(int step);
///@} ///@}
/** @name Receiver Configuration */ /** @name Receiver Configuration */

View File

@ -1705,6 +1705,42 @@ std::string CmdProxy::UDPDestinationIP2(int action) {
return os.str(); return os.str();
} }
std::string CmdProxy::TransmissionDelay(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[n_delay]\n\t[Eiger][Jungfrau][Mythen3] Set transmission delay "
"for all modules in the detector using the step size "
"provided.Sets up \n\t\t[Eiger] txdelay_left to (2 * mod_index * "
"n_delay), \n\t\t[Eiger] txdelay_right to ((2 * mod_index + 1) * "
"n_delay) and \n\t\t[Eiger] txdelay_frame to (2 *num_modules * "
"n_delay) \n\t\t[Jungfrau][Mythen3] txdelay_frame to "
"(num_modules * n_delay) \nfor every module."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (det_id != -1) {
throw RuntimeError("Cannot execute this at module level");
}
if (args.size() != 0) {
WrongNumberOfParameters(0);
}
auto t = det->getTransmissionDelay();
os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) {
if (det_id != -1) {
throw RuntimeError("Cannot execute this at module level");
}
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
det->setTransmissionDelay(StringTo<int>(args[0]));
os << args.front() << '\n';
} else {
throw RuntimeError("Unknown action");
}
return os.str();
}
/* Receiver Config */ /* Receiver Config */
std::string CmdProxy::ReceiverHostname(int action) { std::string CmdProxy::ReceiverHostname(int action) {
std::ostringstream os; std::ostringstream os;

View File

@ -697,6 +697,9 @@ class CmdProxy {
{"rx_udpport", "udp_dstport"}, {"rx_udpport", "udp_dstport"},
{"rx_udpport2", "udp_dstport2"}, {"rx_udpport2", "udp_dstport2"},
{"flowcontrol_10g", "flowcontrol10g"}, {"flowcontrol_10g", "flowcontrol10g"},
{"txndelay_frame", "txdelay_frame"},
{"txndelay_left", "txdelay_left"},
{"txndelay_right", "txdelay_right"},
/* Receiver Config */ /* Receiver Config */
{"r_silent", "rx_silent"}, {"r_silent", "rx_silent"},
@ -893,9 +896,10 @@ class CmdProxy {
{"rx_printconfig", &CmdProxy::rx_printconfig}, {"rx_printconfig", &CmdProxy::rx_printconfig},
{"tengiga", &CmdProxy::tengiga}, {"tengiga", &CmdProxy::tengiga},
{"flowcontrol10g", &CmdProxy::flowcontrol10g}, {"flowcontrol10g", &CmdProxy::flowcontrol10g},
{"txndelay_frame", &CmdProxy::txndelay_frame}, {"txdelay_frame", &CmdProxy::txdelay_frame},
{"txndelay_left", &CmdProxy::txndelay_left}, {"txdelay_left", &CmdProxy::txdelay_left},
{"txndelay_right", &CmdProxy::txndelay_right}, {"txdelay_right", &CmdProxy::txdelay_right},
{"txdelay", &CmdProxy::TransmissionDelay},
/* Receiver Config */ /* Receiver Config */
{"rx_hostname", &CmdProxy::ReceiverHostname}, {"rx_hostname", &CmdProxy::ReceiverHostname},
@ -1158,6 +1162,7 @@ class CmdProxy {
std::string UDPSourceIP2(int action); std::string UDPSourceIP2(int action);
std::string UDPDestinationIP(int action); std::string UDPDestinationIP(int action);
std::string UDPDestinationIP2(int action); std::string UDPDestinationIP2(int action);
std::string TransmissionDelay(int action);
/* Receiver Config */ /* Receiver Config */
std::string ReceiverHostname(int action); std::string ReceiverHostname(int action);
std::string Rx_ROI(int action); std::string Rx_ROI(int action);
@ -1689,24 +1694,24 @@ class CmdProxy {
"[0, 1]\n\t[Eiger][Jungfrau] 10GbE Flow Control."); "[0, 1]\n\t[Eiger][Jungfrau] 10GbE Flow Control.");
INTEGER_COMMAND_VEC_ID( INTEGER_COMMAND_VEC_ID(
txndelay_frame, getTransmissionDelayFrame, setTransmissionDelayFrame, txdelay_frame, getTransmissionDelayFrame, setTransmissionDelayFrame,
StringTo<int>, StringTo<int>,
"[n_delay]\n\t[Eiger][Jungfrau][Mythen3] Transmission delay of first " "[n_delay]\n\t[Eiger][Jungfrau][Mythen3] Transmission delay of first "
"udp packet being streamed out of the module.\n\t[Jungfrau] [0-31] " "udp packet being streamed out of the module.\n\t[Jungfrau] [0-31] "
"Each value represents 1 ms\n\t[Eiger] Additional delay to " "Each value represents 1 ms\n\t[Eiger] Additional delay to "
"txndelay_left and txndelay_right. Each value represents 10ns. Typical " "txdelay_left and txdelay_right. Each value represents 10ns. Typical "
"value is 50000.\n\t[Mythen3] [0-16777215] Each value represents 8 ns " "value is 50000.\n\t[Mythen3] [0-16777215] Each value represents 8 ns "
"(125 MHz clock), max is 134 ms."); "(125 MHz clock), max is 134 ms.");
INTEGER_COMMAND_VEC_ID( INTEGER_COMMAND_VEC_ID(
txndelay_left, getTransmissionDelayLeft, setTransmissionDelayLeft, txdelay_left, getTransmissionDelayLeft, setTransmissionDelayLeft,
StringTo<int>, StringTo<int>,
"[n_delay]\n\t[Eiger] Transmission delay of first packet in an image " "[n_delay]\n\t[Eiger] Transmission delay of first packet in an image "
"being streamed out of the module's left UDP port. Each value " "being streamed out of the module's left UDP port. Each value "
"represents 10ns. Typical value is 50000."); "represents 10ns. Typical value is 50000.");
INTEGER_COMMAND_VEC_ID( INTEGER_COMMAND_VEC_ID(
txndelay_right, getTransmissionDelayRight, setTransmissionDelayRight, txdelay_right, getTransmissionDelayRight, setTransmissionDelayRight,
StringTo<int>, StringTo<int>,
"[n_delay]\n\t[Eiger] Transmission delay of first packet in an image " "[n_delay]\n\t[Eiger] Transmission delay of first packet in an image "
"being streamed out of the module's right UDP port. Each value " "being streamed out of the module's right UDP port. Each value "

View File

@ -1120,6 +1120,14 @@ void Detector::setTransmissionDelayRight(int value, Positions pos) {
pimpl->Parallel(&Module::setTransmissionDelayRight, pos, value); pimpl->Parallel(&Module::setTransmissionDelayRight, pos, value);
} }
int Detector::getTransmissionDelay() const {
return pimpl->getTransmissionDelay();
}
void Detector::setTransmissionDelay(int step) {
pimpl->setTransmissionDelay(step);
}
// Receiver // Receiver
Result<bool> Detector::getUseReceiverFlag(Positions pos) const { Result<bool> Detector::getUseReceiverFlag(Positions pos) const {

View File

@ -431,6 +431,89 @@ void DetectorImpl::setGapPixelsinCallback(const bool enable) {
shm()->gapPixels = enable; shm()->gapPixels = enable;
} }
int DetectorImpl::getTransmissionDelay() const {
bool eiger = false;
switch (shm()->detType) {
case JUNGFRAU:
case MYTHEN3:
break;
case EIGER:
eiger = true;
break;
default:
throw RuntimeError(
"Transmission delay is not implemented for the this detector.");
}
if (!eiger && size() <= 1) {
throw RuntimeError(
"Cannot get intermodule transmission delays with just one module");
}
int step = 0;
if (eiger) {
// between left and right
step = modules[0]->getTransmissionDelayRight();
} else {
// between first and second
step = modules[1]->getTransmissionDelayFrame();
}
for (int i = 0; i != size(); ++i) {
if (eiger) {
if ((modules[i]->getTransmissionDelayLeft() != (2 * i * step)) ||
(modules[i]->getTransmissionDelayRight() !=
((2 * i + 1) * step)) ||
(modules[i]->getTransmissionDelayFrame() !=
(2 * size() * step))) {
return -1;
}
} else {
if (modules[i]->getTransmissionDelayFrame() != (i * step)) {
return -1;
}
}
}
return step;
}
void DetectorImpl::setTransmissionDelay(int step) {
bool eiger = false;
switch (shm()->detType) {
case JUNGFRAU:
case MYTHEN3:
break;
case EIGER:
eiger = true;
break;
default:
throw RuntimeError(
"Transmission delay is not implemented for the this detector.");
}
//using a asyc+future directly (instead of Parallel) to pass different values
std::vector<std::future<void>> futures;
for (int i = 0; i != size(); ++i) {
if (eiger) {
futures.push_back(std::async(std::launch::async,
&Module::setTransmissionDelayLeft,
modules[i].get(), 2 * i * step));
futures.push_back(std::async(std::launch::async,
&Module::setTransmissionDelayRight,
modules[i].get(), (2 * i + 1) * step));
futures.push_back(std::async(std::launch::async,
&Module::setTransmissionDelayFrame,
modules[i].get(), 2 * size() * step));
} else {
futures.push_back(std::async(std::launch::async,
&Module::setTransmissionDelayFrame,
modules[i].get(), i * step));
}
}
//wait for calls to complete
for (auto &f : futures)
f.get();
}
int DetectorImpl::destroyReceivingDataSockets() { int DetectorImpl::destroyReceivingDataSockets() {
LOG(logINFO) << "Going to destroy data sockets"; LOG(logINFO) << "Going to destroy data sockets";
// close socket // close socket

View File

@ -237,11 +237,10 @@ class DetectorImpl : public virtual slsDetectorDefs {
* Sets maximum number of channels of all sls modules */ * Sets maximum number of channels of all sls modules */
void setNumberOfChannels(const slsDetectorDefs::xy c); void setNumberOfChannels(const slsDetectorDefs::xy c);
/** [Eiger][Jungfrau] */
bool getGapPixelsinCallback() const; bool getGapPixelsinCallback() const;
/** [Eiger][Jungfrau] */
void setGapPixelsinCallback(const bool enable); void setGapPixelsinCallback(const bool enable);
int getTransmissionDelay() const;
void setTransmissionDelay(int step);
bool getDataStreamingToClient(); bool getDataStreamingToClient();
void setDataStreamingToClient(bool enable); void setDataStreamingToClient(bool enable);
int getClientStreamingHwm() const; int getClientStreamingHwm() const;

View File

@ -2672,7 +2672,7 @@ TEST_CASE("txndelay_frame", "[.cmd]") {
det_type == defs::MYTHEN3) { det_type == defs::MYTHEN3) {
auto prev_val = det.getTransmissionDelayFrame(); auto prev_val = det.getTransmissionDelayFrame();
auto val = 5000; auto val = 5000;
if (det_type == defs::JUNGFRAU) { if (det_type == defs::JUNGFRAU || det_type == defs::MYTHEN3) {
val = 5; val = 5;
} }
std::string sval = std::to_string(val); std::string sval = std::to_string(val);
@ -2691,6 +2691,62 @@ TEST_CASE("txndelay_frame", "[.cmd]") {
} }
} }
TEST_CASE("txdelay", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::EIGER || det_type == defs::JUNGFRAU ||
det_type == defs::MYTHEN3) {
Result<int> prev_left, prev_right;
bool eiger = false;
if (det_type == defs::EIGER) {
eiger = true;
prev_left = det.getTransmissionDelayLeft();
prev_right = det.getTransmissionDelayRight();
}
auto prev_frame = det.getTransmissionDelayFrame();
auto val = 5000;
if (det_type == defs::JUNGFRAU || det_type == defs::MYTHEN3) {
val = 5;
}
std::string sval = std::to_string(val);
{
std::ostringstream oss1, oss2;
proxy.Call("txdelay", {sval}, -1, PUT, oss1);
REQUIRE(oss1.str() == "txdelay " + sval + "\n");
proxy.Call("txdelay", {}, -1, GET, oss2);
REQUIRE(oss2.str() == "txdelay " + sval + "\n");
}
// test other mods
for (int i = 0; i != det.size(); ++i) {
if (eiger) {
REQUIRE(det.getTransmissionDelayLeft({i}).squash(-1) ==
(3 * i * val));
REQUIRE(det.getTransmissionDelayRight({i}).squash(-1) ==
((3 * i + 1) * val));
REQUIRE(det.getTransmissionDelayFrame({i}).squash(-1) ==
((3 * i + 2) * val));
} else {
REQUIRE(det.getTransmissionDelayFrame({i}).squash(-1) ==
(i * val));
}
}
// not a module level command
REQUIRE_THROWS(proxy.Call("txdelay", {"5"}, 0, PUT));
REQUIRE_THROWS(proxy.Call("txdelay", {}, 0, GET));
for (int i = 0; i != det.size(); ++i) {
if (eiger) {
det.setTransmissionDelayLeft(prev_left[i]);
det.setTransmissionDelayRight(prev_right[i]);
}
det.setTransmissionDelayFrame(prev_frame[i]);
}
} else {
REQUIRE_THROWS(proxy.Call("txdelay", {}, -1, GET));
}
}
/* ZMQ Streaming Parameters (Receiver<->Client) */ /* ZMQ Streaming Parameters (Receiver<->Client) */
TEST_CASE("zmqport", "[.cmd]") { TEST_CASE("zmqport", "[.cmd]") {