Line data Source code
1 : #include "config.hpp" 2 : #include "felixtag.h" 3 : #include "log.hpp" 4 : 5 : #include "felix/felix_fid.h" 6 : #include "felix/felix_ports.h" 7 : #include "felix/felix_client_util.hpp" 8 : #include <cstdint> 9 : 10 27 : std::string Config::options() { 11 27 : return 12 27 : R"( 13 : General Options: 14 : --bus-dir=DIRECTORY Write felix-bus information to this directory. [default: ./bus] 15 : --bus-groupname=NAME Use this groupname for the bus. [default: FELIX] 16 : --cid=<cid>... CID (Connector Ids) to set in FID (Felix ID). Can be used multiple times. [default: device] 17 : --did=<did> DID (Detector Id) to set in FID (Felix ID). [default: 0] 18 : -d, --device=<device>... Use FLX device DEVICE. [default: 0] 19 : --error-out=<fifo> Write error information to a UNIX FIFO 20 : --free-cmem Free previously booked cmem segment by name-<device>-<dma> 21 : --iface=<iface> Send data to the interface. [calculated: use --ip value] 22 : -i, --ip=<ip> Publish data on the ip address IP. [default: libfabric:127.0.0.1] 23 : -b, --netio-pagesize=<size> NetIO page size in Byte. [default: 65536] 24 : -B, --netio-pages=<size> Number of NetIO pages. [default: 256] 25 : --stats-out=<fifo> Write periodic statistics data to a UNIX FIFO 26 : --stats-period=<ms> Period in milliseconds for statistics dumps. [default: 1000] 27 : -?, --help Give this help list 28 : -v, --verbose Produce verbose output 29 : --verbose-bus Produce verbose output for bus 30 : -V, --version Print program version 31 : --evloop-type=<type> Event loop type to use. [default: netio-next] 32 : --vid=N VID (Version Id) to set in FID (Felix ID) [default: 1] 33 : )"; 34 : } 35 : 36 27 : Config::Config() {} 37 : 38 27 : Config::~Config() {} 39 : 40 : 41 27 : void Config::parse(int argc, char **argv) { 42 27 : appname = argv[0]; 43 : 44 27 : std::map<std::string, docopt::value> args 45 54 : = docopt::docopt(usage() + options() + bugs(), 46 27 : { argv + 1, argv + argc }, 47 : true, // show help if requested 48 135 : (std::string(argv[0]) + " " + FELIX_TAG).c_str()); // version string 49 : 50 54 : handle_cmd_line(args); 51 27 : } 52 : 53 0 : std::ostream& Config::format(std::ostream& os) const { 54 0 : os << "Config" << std::endl; 55 0 : os << "bus_dir: " << network.bus_dir << std::endl; 56 0 : os << "bus_groupname: " << network.bus_groupname << std::endl; 57 0 : os << "cid: "; 58 0 : std::copy(resource.cid.begin(), resource.cid.end(), std::ostream_iterator<int>(os << std::hex << std::showbase, " ")); 59 0 : os << std::endl; 60 0 : os << "did: 0x" << std::hex << resource.did << std::dec << std::endl; 61 0 : os << "device: "; 62 0 : std::copy(resource.device.begin(), resource.device.end(), std::ostream_iterator<int>(os, " ")); 63 0 : os << std::endl; 64 0 : os << "free_previous_cmem: " << resource.free_previous_cmem << std::endl; 65 0 : os << "ip: " << network.ip << std::endl; 66 0 : os << "netio_pagesize: " << network.netio_pagesize << std::endl; 67 0 : os << "netio_pages: " << network.netio_pages << std::endl; 68 0 : os << "statistics_fifo: " << stats.monitoring_fifo << std::endl; 69 0 : os << "statistics_period: " << stats.monitoring_period_ms << std::endl; 70 0 : os << "verbose: " << verbose << std::endl; 71 0 : os << "verbose_bus: " << network.verbose_bus << std::endl; 72 0 : os << "eventloop_type: " << evloop_type_to_str(network.evloop_type) << std::endl; 73 0 : os << "vid: 0x" << std::hex << (uint32_t)resource.vid << std::dec << std::endl; 74 0 : os << std::endl; 75 0 : return os; 76 : } 77 : 78 0 : std::ostream& operator<<(std::ostream& os, const Config& c) { 79 0 : return c.format(os); 80 : } 81 : 82 27 : void Config::handle_cmd_line(std::map<std::string, docopt::value> args) { 83 : 84 27 : auto devices = args["--device"].asStringList(); 85 54 : for(const auto& i : devices){ 86 27 : resource.device.push_back(stoi(i)); 87 : } 88 : 89 27 : resource.vid = args["--vid"].asLong(); 90 27 : resource.did = args["--did"].asLong(); 91 : 92 27 : auto cids = args["--cid"].asStringList(); 93 27 : if (cids.empty()) { // No cids, impossible, there should be the default 94 0 : LOG_ERR("No cid provided, aborting."); 95 0 : throw std::runtime_error("No cid provided, aborting."); 96 : } 97 27 : else if (cids.size() == 1) { 98 27 : if ( cids.at(0) == "device" ) { 99 0 : resource.cid = resource.device; 100 : } 101 : else { 102 27 : int base_cid = stoi(cids.at(0), 0, 16); 103 54 : for(unsigned int i = 0; i < resource.device.size(); ++i) { 104 27 : resource.cid.push_back(base_cid + i); 105 : } 106 : } 107 : } 108 0 : else if (cids.size() == devices.size()){ 109 0 : for(unsigned int i = 0; i < cids.size(); ++i) { 110 0 : uint16_t cid = static_cast<uint16_t>(stoi(cids.at(i), 0, 16)); 111 0 : resource.cid.push_back(cid); 112 : } 113 : } 114 : else { 115 0 : LOG_ERR("The number of provided CIDs is not one nor equal to the number of devices."); 116 0 : throw std::runtime_error("No cid provided, aborting."); 117 : } 118 : 119 27 : resource.free_previous_cmem = args["--free-cmem"].asBool(); 120 : 121 54 : network.bus_dir = args["--bus-dir"].asString(); 122 54 : network.bus_groupname = args["--bus-groupname"].asString(); 123 27 : network.dcs_tcp = false; 124 27 : network.netio_pagesize = args["--netio-pagesize"].asLong(); 125 27 : network.netio_pages = args["--netio-pages"].asLong(); 126 27 : network.verbose_bus = args["--verbose-bus"].asBool(); 127 : 128 27 : network.evloop_type = evloop_type_from_str(args["--evloop-type"].asString()); 129 : 130 54 : stats.monitoring_fifo = args["--stats-out"] ? args["--stats-out"].asString() : ""; 131 27 : stats.monitoring_period_ms = args["--stats-period"].asLong(); 132 : 133 27 : verbose = args["--verbose"].asBool(); 134 : 135 : // derive ip 136 27 : if (args["--iface"]) { 137 0 : network.ip = get_value_from_getifaddrs(args["--iface"].asString(), true); 138 : } else { 139 54 : network.ip = args["--ip"].asString(); 140 : } 141 27 : } 142 : 143 : 144 27 : std::string Config::bugs() { 145 27 : return 146 27 : R"( 147 : Report bugs to <https://its.cern.ch/jira/projects/FLXUSERS>. 148 : )"; 149 : } 150 : 151 : 152 27 : int Config::get_number_devices() 153 : { 154 27 : return resource.device.size(); 155 : }; 156 : 157 : 158 27 : uint16_t Config::get_device_cid(unsigned int dev_no) 159 : { 160 27 : auto it = std::find(resource.device.begin(), resource.device.end(), dev_no); 161 27 : if ( it == resource.device.end() ){ 162 0 : throw std::invalid_argument("Cannot find cid for the requested device."); 163 : } else { 164 27 : int idx = it - resource.device.begin(); 165 27 : return resource.cid.at(idx); 166 : } 167 : } 168 : 169 : 170 66 : int Config::get_unique_dmaid(int dmaid, uint16_t device) 171 : { 172 66 : return (dmaid + 10*device); 173 : } 174 : 175 : 176 375 : int Config::udmaid_to_dmaid(int udmaid) 177 : { 178 375 : return (udmaid % 10); 179 : } 180 : 181 : 182 177 : int Config::udmaid_to_deviceid(int udmaid) 183 : { 184 177 : return ( (udmaid - udmaid_to_dmaid(udmaid)) / 10 ); 185 : } 186 : 187 0 : std::string Config::evloop_type_to_str(EventLoopType type) 188 : { 189 0 : switch (type) { 190 0 : case EventLoopType::netio_next: 191 0 : return "netio-next"; 192 0 : case EventLoopType::netio3_native: 193 0 : return "netio3-native"; 194 0 : case EventLoopType::netio3_asio: 195 0 : return "netio3-asio"; 196 0 : default: 197 0 : throw std::logic_error("Invalid EventLoopType"); 198 : } 199 : } 200 : 201 27 : EventLoopType Config::evloop_type_from_str(std::string_view type) 202 : { 203 27 : if (type == "netio-next") { 204 : return EventLoopType::netio_next; 205 0 : } else if (type == "netio3-native") { 206 : return EventLoopType::netio3_native; 207 0 : } else if (type == "netio3-asio") { 208 : return EventLoopType::netio3_asio; 209 : } else { 210 0 : throw std::logic_error("Invalid EventLoopType"); 211 : } 212 : }