Merge pull request #264 from slsdetectorgroup/g2features

vetostream
This commit is contained in:
Dhanya Thattil 2021-07-20 10:01:02 +02:00 committed by GitHub
commit 206c48c7a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 526 additions and 82 deletions

View File

@ -22,13 +22,16 @@ This document describes the differences between 5.2.0 and 5.1.0 releases.
Client Client
------ ------
1. 1. (Gotthard2) veto streaming
New command to enable/ disable veto streaming via 2.5GbE or/ and 10GbE (debugging).
Command: vetostream, Detector::setVetoStream
Mythen3 server Gotthard2 server
----------------- ----------------
1. Bad Channels moved to a new register
1.
2. Resolved Issues 2. Resolved Issues

View File

@ -11,14 +11,29 @@ import subprocess
from parse import remove_comments from parse import remove_comments
allow_bitwise_op = ["EthernetInterface"]
op_key = {"operator|": "__or__",
"operator&" : "__and__"}
def single_line_enum(line): def single_line_enum(line):
sub = line[line.find('{')+1:line.find('}')] sub = line[line.find('{')+1:line.find('}')]
return sub.strip().split(',') return sub.strip().split(',')
def extract_enums(lines): def extract_enums(lines):
# deal with enum class EthernetInterface : int32_t
# and normal enum burstMode {
line_iter = iter(lines) line_iter = iter(lines)
enums = {} enums = {}
for line in line_iter: for line in line_iter:
#Hack away class enum defs
if "class" in line:
line = line.replace("class", "")
line = line.replace(line[line.find(':'):line.find('{')], "")
line = line.replace(" ", " ")
m = re.search("(?<=enum )\w+(?= {)", line) m = re.search("(?<=enum )\w+(?= {)", line)
if m: if m:
enum_name = m.group() enum_name = m.group()
@ -44,25 +59,80 @@ def extract_enums(lines):
pass pass
fields = [f.strip() for f in fields] fields = [f.strip() for f in fields]
enums[enum_name] = fields enums[enum_name] = fields
#Loop again to find operators
for key in enums:
for line in lines:
if key in line and "operator" in line:
pos = line.find("operator")
op_type = line[pos:pos+9]
enums[key].append(op_type)
return enums return enums
def generate_enum_string(enums): def generate_enum_string(enums):
data = [] data = []
for key, value in enums.items(): for key, value in enums.items():
data.append(f'py::enum_<slsDetectorDefs::{key}>(Defs, "{key}")\n') if key in allow_bitwise_op:
tag=", py::arithmetic()"
else:
tag=""
data.append(f'py::enum_<slsDetectorDefs::{key}>(Defs, "{key}"{tag})\n')
operators = []
for v in value: for v in value:
if "operator" not in v:
data.append(f'\t.value("{v}", slsDetectorDefs::{key}::{v})\n') data.append(f'\t.value("{v}", slsDetectorDefs::{key}::{v})\n')
data.append('.export_values();\n\n') else:
operators.append(v)
data.append('\t.export_values()')
#Here add the operators
for op in operators:
data.append(f"\n\t.def(\"{op_key[op]}\", py::overload_cast< const slsDetectorDefs::EthernetInterface&, const slsDetectorDefs::EthernetInterface&>(&{op}))")
data.append(';\n\n')
return ''.join(data) return ''.join(data)
def remove_ifdefs(lines):
"""Keeps C++ version of the code"""
out = []
it = iter(lines)
skip = False
for line in it:
if "#ifdef __cplusplus" in line:
line = next(it)
if "#else" in line:
skip = True
if "#endif" in line:
skip = False
if not skip and "#endif" not in line:
out.append(line)
return out
with open('../../slsSupportLib/include/sls/sls_detector_defs.h') as f: with open('../../slsSupportLib/include/sls/sls_detector_defs.h') as f:
data = f.read() data = f.read()
data = remove_comments(data) data = remove_comments(data)
data = data.splitlines() data = data.splitlines()
data = remove_ifdefs(data)
enums = extract_enums(data) enums = extract_enums(data)
s = generate_enum_string(enums) s = generate_enum_string(enums)
# print(s)
# for i, line in enumerate(data):
# print(i, line)
with open('../src/enums_in.cpp') as f: with open('../src/enums_in.cpp') as f:
data = f.read() data = f.read()

View File

@ -2212,7 +2212,7 @@ class Detector(CppDetectorApi):
@element @element
def veto(self): def veto(self):
""" """
[Gotthard2] Enable or disable veto data streaming from detector. [Gotthard2] Enable or disable veto data from chip.
Note Note
---- ----
Default is 0. Default is 0.
@ -2332,6 +2332,18 @@ class Detector(CppDetectorApi):
ut.set_using_dict(self.setVetoReference, *args) ut.set_using_dict(self.setVetoReference, *args)
@property
@element
def vetostream(self):
return self.getVetoStream()
@vetostream.setter
def vetostream(self, args):
if not isinstance(args, tuple):
args = (args,)
ut.set_using_dict(self.setVetoStream, *args)
""" """
Mythen3 specific Mythen3 specific
""" """

View File

@ -1074,6 +1074,16 @@ void init_det(py::module &m) {
(void (Detector::*)(const bool, sls::Positions)) & (void (Detector::*)(const bool, sls::Positions)) &
Detector::setVeto, Detector::setVeto,
py::arg(), py::arg() = Positions{}) py::arg(), py::arg() = Positions{})
.def("getVetoStream",
(Result<defs::EthernetInterface>(Detector::*)(sls::Positions)
const) &
Detector::getVetoStream,
py::arg() = Positions{})
.def("setVetoStream",
(void (Detector::*)(const defs::EthernetInterface,
sls::Positions)) &
Detector::setVetoStream,
py::arg(), py::arg() = Positions{})
.def("getADCConfiguration", .def("getADCConfiguration",
(Result<int>(Detector::*)(const int, const int, sls::Positions) (Result<int>(Detector::*)(const int, const int, sls::Positions)
const) & const) &

View File

@ -277,4 +277,20 @@ void init_enums(py::module &m) {
.value("TIMING_EXTERNAL", .value("TIMING_EXTERNAL",
slsDetectorDefs::timingSourceType::TIMING_EXTERNAL) slsDetectorDefs::timingSourceType::TIMING_EXTERNAL)
.export_values(); .export_values();
py::enum_<slsDetectorDefs::EthernetInterface>(Defs, "EthernetInterface",
py::arithmetic())
.value("NONE", slsDetectorDefs::EthernetInterface::NONE)
.value("I3GBE", slsDetectorDefs::EthernetInterface::I3GBE)
.value("I10GBE", slsDetectorDefs::EthernetInterface::I10GBE)
.value("ALL", slsDetectorDefs::EthernetInterface::ALL)
.export_values()
.def("__or__",
py::overload_cast<const slsDetectorDefs::EthernetInterface &,
const slsDetectorDefs::EthernetInterface &>(
&operator|))
.def("__and__",
py::overload_cast<const slsDetectorDefs::EthernetInterface &,
const slsDetectorDefs::EthernetInterface &>(
&operator&));
} }

View File

@ -34,6 +34,10 @@
#define BASE_FLOW_CONTROL (0x00200) // 0x1806_0200 - 0x1806_02FF #define BASE_FLOW_CONTROL (0x00200) // 0x1806_0200 - 0x1806_02FF
// https://git.psi.ch/sls_detectors_firmware/vhdl_library/blob/f37608230b4721661f29aacc20124555705ee705/flow/flow_ctrl.vhd // https://git.psi.ch/sls_detectors_firmware/vhdl_library/blob/f37608230b4721661f29aacc20124555705ee705/flow/flow_ctrl.vhd
/** Veto processing core */
#define BASE_VETO_PRCSSNG (0x0300) // 0x1806_0300 - 0x1806_03FF?
// https://git.psi.ch/sls_detectors_firmware/gotthard_II_mcb/blob/master/code/hdl/veto/veto_ctrl.vhd
/* UDP datagram generator */ /* UDP datagram generator */
#define BASE_UDP_RAM (0x01000) // 0x1806_1000 - 0x1806_1FFF #define BASE_UDP_RAM (0x01000) // 0x1806_1000 - 0x1806_1FFF
@ -86,7 +90,9 @@
#define CONFIG_VETO_ENBL_OFST (0) #define CONFIG_VETO_ENBL_OFST (0)
#define CONFIG_VETO_ENBL_MSK (0x00000001 << CONFIG_VETO_ENBL_OFST) #define CONFIG_VETO_ENBL_MSK (0x00000001 << CONFIG_VETO_ENBL_OFST)
#define CONFIG_VETO_CH_10GB_ENBL_OFST (1) #define CONFIG_VETO_CH_3GB_ENBL_OFST (11)
#define CONFIG_VETO_CH_3GB_ENBL_MSK (0x00000001 << CONFIG_VETO_CH_3GB_ENBL_OFST)
#define CONFIG_VETO_CH_10GB_ENBL_OFST (15)
#define CONFIG_VETO_CH_10GB_ENBL_MSK (0x00000001 << CONFIG_VETO_CH_10GB_ENBL_OFST) #define CONFIG_VETO_CH_10GB_ENBL_MSK (0x00000001 << CONFIG_VETO_CH_10GB_ENBL_OFST)
/* Control RW register */ /* Control RW register */
@ -110,10 +116,6 @@
/** DTA Offset Register */ /** DTA Offset Register */
#define DTA_OFFSET_REG (0x0A * REG_OFFSET + BASE_CONTROL) #define DTA_OFFSET_REG (0x0A * REG_OFFSET + BASE_CONTROL)
/** Mask Strip Registers (40) */
#define MASK_STRIP_START_REG (0x18 * REG_OFFSET + BASE_CONTROL)
#define MASK_STRIP_NUM_REGS (40)
/* ASIC registers --------------------------------------------------*/ /* ASIC registers --------------------------------------------------*/
/* ASIC Config register */ /* ASIC Config register */
@ -258,4 +260,10 @@
#define RXR_ENDPOINTS_MAX (32) #define RXR_ENDPOINTS_MAX (32)
#define RXR_ENDPOINT_OFST (16 * REG_OFFSET) #define RXR_ENDPOINT_OFST (16 * REG_OFFSET)
/** Veto processing core --------------------------------------------------*/
/** Mask Strip Registers (40) */
#define MASK_STRIP_START_REG (0x00 * REG_OFFSET + BASE_VETO_PRCSSNG)
#define MASK_STRIP_NUM_REGS (40)
// clang-format on // clang-format on

View File

@ -1581,14 +1581,14 @@ enum timingMode getTiming() {
void setNumberofUDPInterfaces(int val) { void setNumberofUDPInterfaces(int val) {
uint32_t addr = CONFIG_REG; uint32_t addr = CONFIG_REG;
// 2 interfaces (enable veto) // 2 rxr interfaces (enable debugging interface)
if (val > 1) { if (val > 1) {
LOG(logINFOBLUE, ("Setting #Interfaces: 2 (10gbps veto streaming)\n")); LOG(logINFOBLUE, ("Enabling 10GbE (debugging) veto streaming\n"));
bus_w(addr, bus_r(addr) | CONFIG_VETO_CH_10GB_ENBL_MSK); bus_w(addr, bus_r(addr) | CONFIG_VETO_CH_10GB_ENBL_MSK);
} }
// 1 interface (disable veto) // 1 rxr interface (disable debugging interface)
else { else {
LOG(logINFOBLUE, ("Setting #Interfaces: 1 (2.5gbps veto streaming)\n")); LOG(logINFOBLUE, ("Disabling 10GbE (debugging) veto streaming\n"));
bus_w(addr, bus_r(addr) & ~CONFIG_VETO_CH_10GB_ENBL_MSK); bus_w(addr, bus_r(addr) & ~CONFIG_VETO_CH_10GB_ENBL_MSK);
} }
LOG(logDEBUG, ("config reg:0x%x\n", bus_r(addr))); LOG(logDEBUG, ("config reg:0x%x\n", bus_r(addr)));
@ -2578,6 +2578,23 @@ int getVeto() {
CONFIG_VETO_ENBL_OFST); CONFIG_VETO_ENBL_OFST);
} }
void setVetoStream(int value) {
uint32_t addr = CONFIG_REG;
if (value) {
LOG(logINFOBLUE, ("Enabling 3GbE veto streaming\n"));
bus_w(addr, bus_r(addr) | CONFIG_VETO_CH_3GB_ENBL_MSK);
} else {
LOG(logINFOBLUE, ("Disabling 3GbE veto streaming\n"));
bus_w(addr, bus_r(addr) & ~CONFIG_VETO_CH_3GB_ENBL_MSK);
}
LOG(logDEBUG, ("config reg:0x%x\n", bus_r(addr)));
}
int getVetoStream() {
return ((bus_r(CONFIG_REG) & CONFIG_VETO_CH_3GB_ENBL_MSK) ? 1 : 0);
}
void setBadChannels(int nch, int *channels) { void setBadChannels(int nch, int *channels) {
LOG(logINFO, ("Setting %d bad channels\n", nch)); LOG(logINFO, ("Setting %d bad channels\n", nch));

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#define REQRD_FRMWRE_VRSN (0x200925) #define REQRD_FRMWRE_VRSN (0x210527)
#define KERNEL_DATE_VRSN "Wed May 20 13:58:38 CEST 2020" #define KERNEL_DATE_VRSN "Wed May 20 13:58:38 CEST 2020"
#define CTRL_SRVR_INIT_TIME_US (300 * 1000) #define CTRL_SRVR_INIT_TIME_US (300 * 1000)

View File

@ -540,6 +540,8 @@ void setTimingSource(enum timingSourceType value);
enum timingSourceType getTimingSource(); enum timingSourceType getTimingSource();
void setVeto(int enable); void setVeto(int enable);
int getVeto(); int getVeto();
void setVetoStream(int value);
int getVetoStream();
void setBadChannels(int nch, int *channels); void setBadChannels(int nch, int *channels);
int *getBadChannels(int *nch); int *getBadChannels(int *nch);
#endif #endif

View File

@ -247,3 +247,5 @@ int get_pattern(int);
int load_default_pattern(int); int load_default_pattern(int);
int get_all_threshold_energy(int); int get_all_threshold_energy(int);
int get_master(int); int get_master(int);
int get_veto_stream(int);
int set_veto_stream(int);

View File

@ -369,6 +369,8 @@ void function_table() {
flist[F_LOAD_DEFAULT_PATTERN] = &load_default_pattern; flist[F_LOAD_DEFAULT_PATTERN] = &load_default_pattern;
flist[F_GET_ALL_THRESHOLD_ENERGY] = &get_all_threshold_energy; flist[F_GET_ALL_THRESHOLD_ENERGY] = &get_all_threshold_energy;
flist[F_GET_MASTER] = &get_master; flist[F_GET_MASTER] = &get_master;
flist[F_GET_VETO_STREAM] = &get_veto_stream;
flist[F_SET_VETO_STREAM] = &set_veto_stream;
// check // check
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) { if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
@ -7525,7 +7527,7 @@ int get_veto(int file_des) {
#endif #endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
} }
/*
int set_veto(int file_des) { int set_veto(int file_des) {
ret = OK; ret = OK;
memset(mess, 0, sizeof(mess)); memset(mess, 0, sizeof(mess));
@ -7567,6 +7569,29 @@ int set_veto(int file_des) {
#endif #endif
return Server_SendResult(file_des, INT32, NULL, 0); return Server_SendResult(file_des, INT32, NULL, 0);
} }
*/
int set_veto(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
int arg = 0;
if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0)
return printSocketReadError();
LOG(logINFO, ("Setting veto mode: %u\n", arg));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
setVeto(arg);
int retval = getVeto();
LOG(logDEBUG1, ("veto mode retval: %u\n", retval));
validate(arg, retval, "set veto mode", DEC);
}
#endif
return Server_SendResult(file_des, INT32, NULL, 0);
}
int set_pattern(int file_des) { int set_pattern(int file_des) {
ret = OK; ret = OK;
@ -8383,3 +8408,52 @@ int get_master(int file_des){
#endif #endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval)); return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
} }
int get_veto_stream(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
enum EthernetInterface retval = NONE;
LOG(logDEBUG1, ("Getting veto stream\n"));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// get only
retval = getVetoStream();
LOG(logDEBUG1, ("vetostream retval: %u\n", retval));
#endif
return Server_SendResult(file_des, INT32, &retval, sizeof(retval));
}
int set_veto_stream(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
enum EthernetInterface arg = 0;
if (receiveData(file_des, &arg, sizeof(arg), INT32) < 0)
return printSocketReadError();
LOG(logINFO, ("Setting vetostream: %u\n", (int)arg));
#ifndef GOTTHARD2D
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
if (arg != 0 && arg != 1) {
ret = FAIL;
sprintf(mess,
"Could not set vetostream 3GbE. Invalid argument %d.\n",
arg);
LOG(logERROR, (mess));
} else {
setVetoStream(arg);
int retval = getVetoStream();
LOG(logDEBUG1, ("vetostream retval: %u\n", retval));
validate(arg, retval, "set veto stream", DEC);
}
}
#endif
return Server_SendResult(file_des, INT32, NULL, 0);
}

View File

@ -1244,9 +1244,21 @@ class Detector {
/** [Gotthard2] */ /** [Gotthard2] */
Result<bool> getVeto(Positions pos = {}) const; Result<bool> getVeto(Positions pos = {}) const;
/** [Gotthard2] Default disabled */ /** [Gotthard2] Veto data in chip, Default disabled */
void setVeto(const bool enable, Positions pos = {}); void setVeto(const bool enable, Positions pos = {});
/** [Gotthard2] */
Result<defs::EthernetInterface> getVetoStream(Positions pos = {}) const;
/** [Gotthard2] Options: NONE (Default), I3GBE, I10GBE (debugging), ALL
* Enable or disable the 2 veto streaming interfaces available. Can
* concatenate more than one interface. \n3GbE (2.5GbE) is the default
* interface to work with. \n10GbE is for debugging and also enables second
* interface in receiver for listening to veto packets (writes a separate
* file if writing enabled). Also restarts client and receiver zmq sockets
* if zmq streaming enabled.*/
void setVetoStream(const defs::EthernetInterface value, Positions pos = {});
/** [Gotthard2] */ /** [Gotthard2] */
Result<int> getADCConfiguration(const int chipIndex, const int adcIndex, Result<int> getADCConfiguration(const int chipIndex, const int adcIndex,
Positions pos = {}) const; Positions pos = {}) const;
@ -1727,6 +1739,7 @@ class Detector {
private: private:
std::vector<int> getPortNumbers(int start_port); std::vector<int> getPortNumbers(int start_port);
void updateRxRateCorrections(); void updateRxRateCorrections();
void setNumberofUDPInterfaces_(int n, Positions pos);
Result<int> getNumberofUDPInterfaces_(Positions pos) const;
}; };
} // namespace sls } // namespace sls

View File

@ -1802,6 +1802,50 @@ std::string CmdProxy::BurstMode(int action) {
return os.str(); return os.str();
} }
std::string CmdProxy::VetoStreaming(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[none|3gbe|10gbe|...]\n\t[Gotthard2] Enable or disable the 2 "
"veto streaming interfaces available. Can include more than one "
"interface. \n\tDefault: none. 3GbE (2.5GbE) is the default "
"interface to work with. \n\t10GbE is for debugging and also "
"enables second interface in receiver for listening to veto "
"packets (writes a separate file if writing enabled). Also "
"restarts client and receiver zmq sockets if zmq streaming "
"enabled."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
WrongNumberOfParameters(0);
}
auto t = det->getVetoStream(std::vector<int>{det_id});
os << OutString(t) << '\n';
} else if (action == defs::PUT_ACTION) {
if (args.empty()) {
WrongNumberOfParameters(1);
}
defs::EthernetInterface interface = defs::EthernetInterface::NONE;
for (const auto &arg : args) {
if (arg == "none") {
if (args.size() > 1) {
throw sls::RuntimeError(
"cannot have other arguments with 'none'. args: " +
ToString(args));
}
break;
}
StringTo<defs::EthernetInterface>(arg);
interface = interface | (StringTo<defs::EthernetInterface>(arg));
}
det->setVetoStream(interface, std::vector<int>{det_id});
os << ToString(interface) << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::ConfigureADC(int action) { std::string CmdProxy::ConfigureADC(int action) {
std::ostringstream os; std::ostringstream os;
os << cmd << ' '; os << cmd << ' ';

View File

@ -957,6 +957,7 @@ class CmdProxy {
{"currentsource", &CmdProxy::currentsource}, {"currentsource", &CmdProxy::currentsource},
{"timingsource", &CmdProxy::timingsource}, {"timingsource", &CmdProxy::timingsource},
{"veto", &CmdProxy::veto}, {"veto", &CmdProxy::veto},
{"vetostream", &CmdProxy::VetoStreaming},
{"confadc", &CmdProxy::ConfigureADC}, {"confadc", &CmdProxy::ConfigureADC},
{"badchannels", &CmdProxy::BadChannels}, {"badchannels", &CmdProxy::BadChannels},
@ -1132,6 +1133,7 @@ class CmdProxy {
std::string VetoReference(int action); std::string VetoReference(int action);
std::string VetoFile(int action); std::string VetoFile(int action);
std::string BurstMode(int action); std::string BurstMode(int action);
std::string VetoStreaming(int action);
std::string ConfigureADC(int action); std::string ConfigureADC(int action);
std::string BadChannels(int action); std::string BadChannels(int action);
/* Mythen3 Specific */ /* Mythen3 Specific */
@ -1484,13 +1486,11 @@ class CmdProxy {
INTEGER_COMMAND_VEC_ID( INTEGER_COMMAND_VEC_ID(
numinterfaces, getNumberofUDPInterfaces, setNumberofUDPInterfaces, numinterfaces, getNumberofUDPInterfaces, setNumberofUDPInterfaces,
StringTo<int>, StringTo<int>,
"[1, 2]\n\t[Jungfrau][Gotthard2] Number of udp interfaces to stream " "[1, 2]\n\t[Jungfrau] Number of udp interfaces to stream "
"data from detector. Default: 1.\n\tAlso enables second interface in " "data from detector. Default: 1.\n\tAlso enables second interface in "
"receiver for listening (Writes a file per interface if writing " "receiver for listening (Writes a file per interface if writing "
"enabled).\n\tAlso restarts client and receiver zmq sockets if zmq " "enabled).\n\tAlso restarts client and receiver zmq sockets if zmq "
"streaming enabled.\n\t[Gotthard2] second interface enabled to send " "streaming enabled.");
"veto information via 10Gbps for debugging. By default, if veto "
"enabled, it is sent via 2.5 gbps interface.");
INTEGER_COMMAND_VEC_ID( INTEGER_COMMAND_VEC_ID(
selinterface, getSelectedUDPInterface, selectUDPInterface, selinterface, getSelectedUDPInterface, selectUDPInterface,
@ -1913,7 +1913,7 @@ class CmdProxy {
INTEGER_COMMAND_VEC_ID(veto, getVeto, setVeto, StringTo<int>, INTEGER_COMMAND_VEC_ID(veto, getVeto, setVeto, StringTo<int>,
"[0, 1]\n\t[Gotthard2] Enable or disable veto data " "[0, 1]\n\t[Gotthard2] Enable or disable veto data "
"streaming from detector. Default is 0."); "data from chip. Default is 0.");
/* Mythen3 Specific */ /* Mythen3 Specific */

View File

@ -746,10 +746,28 @@ Result<std::string> Detector::getScanErrorMessage(Positions pos) const {
// Network Configuration (Detector<->Receiver) // Network Configuration (Detector<->Receiver)
Result<int> Detector::getNumberofUDPInterfaces(Positions pos) const { Result<int> Detector::getNumberofUDPInterfaces(Positions pos) const {
return pimpl->Parallel(&Module::getNumberofUDPInterfaces, pos); if (getDetectorType().squash() != defs::JUNGFRAU) {
throw sls::RuntimeError(
"Cannot set number of udp interfaces for this detector.");
}
// also called by vetostream (for gotthard2)
return getNumberofUDPInterfaces_(pos);
} }
void Detector::setNumberofUDPInterfaces(int n, Positions pos) { void Detector::setNumberofUDPInterfaces(int n, Positions pos) {
if (getDetectorType().squash() != defs::JUNGFRAU) {
throw sls::RuntimeError(
"Cannot set number of udp interfaces for this detector.");
}
// also called by vetostream (for gotthard2)
setNumberofUDPInterfaces_(n, pos);
}
Result<int> Detector::getNumberofUDPInterfaces_(Positions pos) const {
return pimpl->Parallel(&Module::getNumberofUDPInterfaces, pos);
}
void Detector::setNumberofUDPInterfaces_(int n, Positions pos) {
bool previouslyClientStreaming = pimpl->getDataStreamingToClient(); bool previouslyClientStreaming = pimpl->getDataStreamingToClient();
bool useReceiver = getUseReceiverFlag().squash(false); bool useReceiver = getUseReceiverFlag().squash(false);
bool previouslyReceiverStreaming = false; bool previouslyReceiverStreaming = false;
@ -1547,6 +1565,37 @@ void Detector::setVeto(bool enable, Positions pos) {
pimpl->Parallel(&Module::setVeto, pos, enable); pimpl->Parallel(&Module::setVeto, pos, enable);
} }
Result<defs::EthernetInterface> Detector::getVetoStream(Positions pos) const {
// 3gbe
auto r3 = pimpl->Parallel(&Module::getVetoStream, pos);
// 10gbe (debugging interface) opens 2nd udp interface in receiver
auto r10 = getNumberofUDPInterfaces_(pos);
Result<defs::EthernetInterface> res(r3.size());
for (unsigned int i = 0; i < res.size(); ++i) {
res[i] = (r3[i] ? defs::EthernetInterface::I3GBE
: defs::EthernetInterface::NONE);
if (r10[i] == 2) {
res[i] = res[i] | defs::EthernetInterface::I10GBE;
}
}
return res;
}
void Detector::setVetoStream(defs::EthernetInterface interface, Positions pos) {
// 3gbe
bool i3gbe = (interface & defs::EthernetInterface::I3GBE) == defs::EthernetInterface::I3GBE;
pimpl->Parallel(&Module::setVetoStream, pos, i3gbe);
// 10gbe (debugging interface) opens 2nd udp interface in receiver
int old_numinterfaces = getNumberofUDPInterfaces_(pos).tsquash(
"retrieved inconsistent number of udp interfaces");
int numinterfaces = ((interface & defs::EthernetInterface::I10GBE) == defs::EthernetInterface::I3GBE) ? 2 : 1;
if (numinterfaces != old_numinterfaces) {
setNumberofUDPInterfaces_(numinterfaces, pos);
}
}
Result<int> Detector::getADCConfiguration(const int chipIndex, Result<int> Detector::getADCConfiguration(const int chipIndex,
const int adcIndex, const int adcIndex,
Positions pos) const { Positions pos) const {

View File

@ -1870,6 +1870,14 @@ void Module::setVeto(bool enable) {
sendToDetector(F_SET_VETO, static_cast<int>(enable), nullptr); sendToDetector(F_SET_VETO, static_cast<int>(enable), nullptr);
} }
bool Module::getVetoStream() const {
return (sendToDetector<int>(F_GET_VETO_STREAM));
}
void Module::setVetoStream(const bool value) {
sendToDetector(F_SET_VETO_STREAM, static_cast<int>(value), nullptr);
}
int Module::getADCConfiguration(const int chipIndex, const int adcIndex) const { int Module::getADCConfiguration(const int chipIndex, const int adcIndex) const {
int args[]{chipIndex, adcIndex}; int args[]{chipIndex, adcIndex};
return sendToDetector<int>(F_GET_ADC_CONFIGURATION, args); return sendToDetector<int>(F_GET_ADC_CONFIGURATION, args);

View File

@ -406,6 +406,8 @@ class Module : public virtual slsDetectorDefs {
void setTimingSource(slsDetectorDefs::timingSourceType value); void setTimingSource(slsDetectorDefs::timingSourceType value);
bool getVeto() const; bool getVeto() const;
void setVeto(bool enable); void setVeto(bool enable);
bool getVetoStream() const;
void setVetoStream(const bool value);
int getADCConfiguration(const int chipIndex, const int adcIndex) const; int getADCConfiguration(const int chipIndex, const int adcIndex) const;
void setADCConfiguration(const int chipIndex, const int adcIndex, void setADCConfiguration(const int chipIndex, const int adcIndex,
int value); int value);

View File

@ -639,6 +639,53 @@ TEST_CASE("veto", "[.cmd]") {
} }
} }
TEST_CASE("vetostream", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::GOTTHARD2) {
auto prev_val = det.getVetoStream();
{
std::ostringstream oss;
proxy.Call("vetostream", {"none"}, -1, PUT, oss);
REQUIRE(oss.str() == "vetostream none\n");
}
{
std::ostringstream oss;
proxy.Call("vetostream", {}, -1, GET, oss);
REQUIRE(oss.str() == "vetostream none\n");
}
{
std::ostringstream oss;
proxy.Call("vetostream", {"3gbe"}, -1, PUT, oss);
REQUIRE(oss.str() == "vetostream 3gbe\n");
}
{
std::ostringstream oss;
proxy.Call("vetostream", {}, -1, GET, oss);
REQUIRE(oss.str() == "vetostream 3gbe\n");
}
{
std::ostringstream oss;
proxy.Call("vetostream", {"3gbe", "10gbe"}, -1, PUT, oss);
REQUIRE(oss.str() == "vetostream 3gbe, 10gbe\n");
}
{
std::ostringstream oss;
proxy.Call("vetostream", {}, -1, GET, oss);
REQUIRE(oss.str() == "vetostream 3gbe, 10gbe\n");
}
REQUIRE_THROWS(proxy.Call("vetostream", {"3gbe", "none"}, -1, PUT));
for (int i = 0; i != det.size(); ++i) {
det.setVetoStream(prev_val[i], {i});
}
} else {
REQUIRE_THROWS(proxy.Call("vetostream", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("vetostream", {"none"}, -1, PUT));
}
REQUIRE_THROWS(proxy.Call("vetostream", {"dfgd"}, -1, GET));
}
TEST_CASE("confadc", "[.cmd]") { TEST_CASE("confadc", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);

View File

@ -96,6 +96,39 @@ TEST_CASE("Setting and reading back Jungfrau dacs", "[.cmd][.dacs]") {
/* Network Configuration (Detector<->Receiver) */ /* Network Configuration (Detector<->Receiver) */
TEST_CASE("numinterfaces", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU) {
auto prev_val = det.getNumberofUDPInterfaces().tsquash(
"inconsistent numinterfaces to test");
{
std::ostringstream oss;
proxy.Call("numinterfaces", {"2"}, -1, PUT, oss);
REQUIRE(oss.str() == "numinterfaces 2\n");
}
{
std::ostringstream oss;
proxy.Call("numinterfaces", {"1"}, -1, PUT, oss);
REQUIRE(oss.str() == "numinterfaces 1\n");
}
{
std::ostringstream oss;
proxy.Call("numinterfaces", {}, -1, GET, oss);
REQUIRE(oss.str() == "numinterfaces 1\n");
}
det.setNumberofUDPInterfaces(prev_val);
} else {
std::ostringstream oss;
proxy.Call("numinterfaces", {}, -1, GET, oss);
REQUIRE(oss.str() == "numinterfaces 1\n");
REQUIRE_THROWS(proxy.Call("numinterfaces", {"1"}, -1, PUT));
}
REQUIRE_THROWS(proxy.Call("numinterfaces", {"3"}, -1, PUT));
REQUIRE_THROWS(proxy.Call("numinterfaces", {"0"}, -1, PUT));
}
TEST_CASE("selinterface", "[.cmd]") { TEST_CASE("selinterface", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);

View File

@ -1751,39 +1751,6 @@ TEST_CASE("scanerrmsg", "[.cmd]") {
/* Network Configuration (Detector<->Receiver) */ /* Network Configuration (Detector<->Receiver) */
TEST_CASE("numinterfaces", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU || det_type == defs::GOTTHARD2) {
auto prev_val = det.getNumberofUDPInterfaces().tsquash(
"inconsistent numinterfaces to test");
{
std::ostringstream oss;
proxy.Call("numinterfaces", {"2"}, -1, PUT, oss);
REQUIRE(oss.str() == "numinterfaces 2\n");
}
{
std::ostringstream oss;
proxy.Call("numinterfaces", {"1"}, -1, PUT, oss);
REQUIRE(oss.str() == "numinterfaces 1\n");
}
{
std::ostringstream oss;
proxy.Call("numinterfaces", {}, -1, GET, oss);
REQUIRE(oss.str() == "numinterfaces 1\n");
}
det.setNumberofUDPInterfaces(prev_val);
} else {
std::ostringstream oss;
proxy.Call("numinterfaces", {}, -1, GET, oss);
REQUIRE(oss.str() == "numinterfaces 1\n");
REQUIRE_THROWS(proxy.Call("numinterfaces", {"1"}, -1, PUT));
}
REQUIRE_THROWS(proxy.Call("numinterfaces", {"3"}, -1, PUT));
REQUIRE_THROWS(proxy.Call("numinterfaces", {"0"}, -1, PUT));
}
TEST_CASE("udp_srcip", "[.cmd]") { TEST_CASE("udp_srcip", "[.cmd]") {
Detector det; Detector det;
CmdProxy proxy(&det); CmdProxy proxy(&det);

View File

@ -36,6 +36,7 @@ std::string ToString(const defs::dacIndex s);
std::string ToString(const std::vector<defs::dacIndex> &vec); std::string ToString(const std::vector<defs::dacIndex> &vec);
std::string ToString(const defs::burstMode s); std::string ToString(const defs::burstMode s);
std::string ToString(const defs::timingSourceType s); std::string ToString(const defs::timingSourceType s);
std::string ToString(const defs::EthernetInterface s);
std::string ToString(const slsDetectorDefs::xy &coord); std::string ToString(const slsDetectorDefs::xy &coord);
std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::xy &coord); std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::xy &coord);
@ -297,6 +298,7 @@ template <> defs::readoutMode StringTo(const std::string &s);
template <> defs::dacIndex StringTo(const std::string &s); template <> defs::dacIndex StringTo(const std::string &s);
template <> defs::burstMode StringTo(const std::string &s); template <> defs::burstMode StringTo(const std::string &s);
template <> defs::timingSourceType StringTo(const std::string &s); template <> defs::timingSourceType StringTo(const std::string &s);
template <> defs::EthernetInterface StringTo(const std::string &s);
template <> uint32_t StringTo(const std::string &s); template <> uint32_t StringTo(const std::string &s);
template <> uint64_t StringTo(const std::string &s); template <> uint64_t StringTo(const std::string &s);

View File

@ -394,6 +394,17 @@ typedef struct {
*/ */
enum timingSourceType { TIMING_INTERNAL, TIMING_EXTERNAL }; enum timingSourceType { TIMING_INTERNAL, TIMING_EXTERNAL };
#ifdef __cplusplus
enum class EthernetInterface {
#else
enum EthernetInterface {
#endif
NONE = 0,
I3GBE = 1 << 1,
I10GBE = 1 << 2,
ALL = I3GBE | I10GBE
};
#ifdef __cplusplus #ifdef __cplusplus
/** scan structure */ /** scan structure */
@ -485,8 +496,18 @@ typedef struct {
#ifdef __cplusplus #ifdef __cplusplus
}; };
inline slsDetectorDefs::EthernetInterface
operator|( const slsDetectorDefs::EthernetInterface &a,
const slsDetectorDefs::EthernetInterface &b) {
return slsDetectorDefs::EthernetInterface(static_cast<int32_t>(a) |
static_cast<int32_t>(b));
};
inline slsDetectorDefs::EthernetInterface operator&( const slsDetectorDefs::EthernetInterface &a,
const slsDetectorDefs::EthernetInterface &b) {
return slsDetectorDefs::EthernetInterface(static_cast<int32_t>(a) & static_cast<int32_t>(b));
};
#endif #endif
;
#ifdef __cplusplus #ifdef __cplusplus
struct detParameters { struct detParameters {
@ -632,3 +653,4 @@ using Positions = const std::vector<int> &;
using defs = slsDetectorDefs; using defs = slsDetectorDefs;
} // namespace sls } // namespace sls
#endif #endif

View File

@ -221,6 +221,8 @@ enum detFuncs {
F_LOAD_DEFAULT_PATTERN, F_LOAD_DEFAULT_PATTERN,
F_GET_ALL_THRESHOLD_ENERGY, F_GET_ALL_THRESHOLD_ENERGY,
F_GET_MASTER, F_GET_MASTER,
F_GET_VETO_STREAM,
F_SET_VETO_STREAM,
NUM_DET_FUNCTIONS, NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 256, /**< detector function should not exceed this RECEIVER_ENUM_START = 256, /**< detector function should not exceed this
@ -548,6 +550,9 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_LOAD_DEFAULT_PATTERN: return "F_LOAD_DEFAULT_PATTERN"; case F_LOAD_DEFAULT_PATTERN: return "F_LOAD_DEFAULT_PATTERN";
case F_GET_ALL_THRESHOLD_ENERGY: return "F_GET_ALL_THRESHOLD_ENERGY"; case F_GET_ALL_THRESHOLD_ENERGY: return "F_GET_ALL_THRESHOLD_ENERGY";
case F_GET_MASTER: return "F_GET_MASTER"; case F_GET_MASTER: return "F_GET_MASTER";
case F_GET_VETO_STREAM: return "F_GET_VETO_STREAM";
case F_SET_VETO_STREAM: return "F_SET_VETO_STREAM";
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS"; case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START"; case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";

View File

@ -2,11 +2,11 @@
#define GITBRANCH "5.1.0" #define GITBRANCH "5.1.0"
#define APICTB 0x210225 #define APICTB 0x210225
#define APIGOTTHARD 0x210225 #define APIGOTTHARD 0x210225
#define APIJUNGFRAU 0x210714
#define APIMOENCH 0x210225 #define APIMOENCH 0x210225
#define APIEIGER 0x210225 #define APIEIGER 0x210225
#define APIMYTHEN3 0x210225 #define APIMYTHEN3 0x210225
#define APILIB 0x210225 #define APILIB 0x210225
#define APIRECEIVER 0x210225 #define APIRECEIVER 0x210225
#define APIGUI 0x210225 #define APIGUI 0x210225
#define APIGOTTHARD2 0x210714 #define APIGOTTHARD2 0x210715
#define APIJUNGFRAU 0x210714

View File

@ -519,6 +519,23 @@ std::string ToString(const defs::timingSourceType s) {
} }
} }
std::string ToString(const defs::EthernetInterface s) {
std::ostringstream os;
std::string rs;
switch (s) {
case defs::EthernetInterface::NONE:
return std::string("none");
default:
if ((s & defs::EthernetInterface::I3GBE)!=defs::EthernetInterface::NONE)
os << "3gbe, ";
if ((s & defs::EthernetInterface::I10GBE)!=defs::EthernetInterface::NONE)
os << "10gbe, ";
auto rs = os.str();
rs.erase(rs.end() - 2, rs.end());
return rs;
}
}
const std::string &ToString(const std::string &s) { return s; } const std::string &ToString(const std::string &s) { return s; }
template <> defs::detectorType StringTo(const std::string &s) { template <> defs::detectorType StringTo(const std::string &s) {
@ -859,6 +876,19 @@ template <> defs::timingSourceType StringTo(const std::string &s) {
throw sls::RuntimeError("Unknown timing source type " + s); throw sls::RuntimeError("Unknown timing source type " + s);
} }
template <> defs::EthernetInterface StringTo(const std::string &s) {
std::string rs = s;
if (s.find(',') != std::string::npos)
rs.erase(rs.find(','));
if (rs == "none")
return defs::EthernetInterface::NONE;
if (rs == "3gbe")
return defs::EthernetInterface::I3GBE;
if (rs == "10gbe")
return defs::EthernetInterface::I10GBE;
throw sls::RuntimeError("Unknown EthernetInterface type " + s);
}
template <> uint32_t StringTo(const std::string &s) { template <> uint32_t StringTo(const std::string &s) {
int base = s.find("0x") != std::string::npos ? 16 : 10; int base = s.find("0x") != std::string::npos ? 16 : 10;
return std::stoul(s, nullptr, base); return std::stoul(s, nullptr, base);

View File

@ -4,6 +4,7 @@
#include <chrono> #include <chrono>
#include <future> #include <future>
#include <iostream> #include <iostream>
#include <thread>
std::vector<char> server() { std::vector<char> server() {
std::cout << "starting server\n"; std::cout << "starting server\n";

View File

@ -1,10 +1,10 @@
#include "catch.hpp" #include "catch.hpp"
#include "sls/Pattern.h"
#include "sls/TimeHelper.h" #include "sls/TimeHelper.h"
#include "sls/ToString.h" #include "sls/ToString.h"
#include "sls/network_utils.h"
#include "sls/Pattern.h"
#include "sls/sls_detector_defs.h"
#include "sls/container_utils.h" #include "sls/container_utils.h"
#include "sls/network_utils.h"
#include "sls/sls_detector_defs.h"
#include <array> #include <array>
#include <map> #include <map>
#include <sstream> #include <sstream>
@ -302,25 +302,32 @@ TEST_CASE("Streaming of slsDetectorDefs::scanParameters") {
} }
} }
TEST_CASE("Printing c style arrays of int"){ TEST_CASE("Printing c style arrays of int") {
int arr[]{3, 5}; int arr[]{3, 5};
REQUIRE(ToString(arr) == "[3, 5]"); REQUIRE(ToString(arr) == "[3, 5]");
} }
TEST_CASE("Printing c style arrays of uint8"){ TEST_CASE("Printing c style arrays of uint8") {
uint8_t arr[]{1,2,3,4,5}; uint8_t arr[]{1, 2, 3, 4, 5};
REQUIRE(ToString(arr) == "[1, 2, 3, 4, 5]"); REQUIRE(ToString(arr) == "[1, 2, 3, 4, 5]");
} }
TEST_CASE("Printing c style arrays of double"){ TEST_CASE("Printing c style arrays of double") {
double arr[]{3.4, 5.3, 6.2}; double arr[]{3.4, 5.3, 6.2};
REQUIRE(ToString(arr) == "[3.4, 5.3, 6.2]"); REQUIRE(ToString(arr) == "[3.4, 5.3, 6.2]");
} }
TEST_CASE("Print a member of patternParameters"){ TEST_CASE("Print a member of patternParameters") {
auto pat = sls::make_unique<sls::patternParameters>(); auto pat = sls::make_unique<sls::patternParameters>();
pat->limits[0] = 4; pat->limits[0] = 4;
pat->limits[1] = 100; pat->limits[1] = 100;
REQUIRE(ToString(pat->limits) == "[4, 100]"); REQUIRE(ToString(pat->limits) == "[4, 100]");
}
TEST_CASE("EthernetInterface") {
REQUIRE(ToString(sls::defs::EthernetInterface::NONE) == "none");
REQUIRE(ToString(sls::defs::EthernetInterface::I10GBE) == "10gbe");
REQUIRE(ToString(sls::defs::EthernetInterface::I3GBE) == "3gbe");
REQUIRE(ToString(sls::defs::EthernetInterface::I3GBE |
sls::defs::EthernetInterface::I10GBE) == "3gbe, 10gbe");
} }