Program Listing for File config_trickle.cpp

Return to documentation for file (config/config_trickle.cpp)

#include "config.hpp"


ConfigTrickle::ConfigTrickle() : Config()
{
    resource.toflx = true;
}


std::ostream& ConfigTrickle::format(std::ostream& os) const
{
    os << "ConfigTrickle" << std::endl;
    os << "cmem_buffersize: " << resource.cmem_buffersize << std::endl;
    os << "unbuffered: " << unbuffered << std::endl;
    os << "bus_dir: " << network.bus_dir << std::endl;
    os << "bus_groupname: " << network.bus_groupname << std::endl;
    os << "cid: ";
        std::copy(resource.cid.begin(), resource.cid.end(), std::ostream_iterator<int>(os << std::hex << std::showbase, " "));
        os << std::endl;
    os << "did: 0x" << std::hex << resource.did << std::dec << std::endl;
    os << "device: ";
        std::copy(resource.device.begin(), resource.device.end(), std::ostream_iterator<int>(os, " "));
        os << std::endl;
    os << "free_previous_cmem: " << resource.free_previous_cmem << std::endl;
    os << "ip: " << network.ip << std::endl;
    os << std::endl;
    os << "verbose: " << verbose << std::endl;
    os << "verbose_bus: " << network.verbose_bus << std::endl;
    os << "vid: 0x" << std::hex << static_cast<uint32_t>(resource.vid) << std::dec << std::endl;
    os << std::endl;
    return os;
}

std::ostream& operator<<(std::ostream& os, const ConfigTrickle& c) {
    return c.format(os);
}


std::string ConfigTrickle::usage()
{
    return
R"(felix-trickle - FELIX app for sending trickle configuration to front-end devices

    Usage:
      felix-trickle [options --device=<device>... --cid=<cid>...]
)";
}


std::string ConfigTrickle::options()
{
    return
R"(
    General Options:
        --bus-dir=DIRECTORY          Write felix-bus information to this directory. [default: ./bus]
        --bus-groupname=NAME         Use this groupname for the bus. [default: FELIX]
        --cid=<cid>...               CID (Connector Ids) to set in FID (Felix ID). Can be used multiple times. [default: device]
        --did=<did>                  DID (Detector Id) to set in FID (Felix ID). [default: 0]
    -d, --device=<device>...         Use FLX device DEVICE. [default: 0]
        --free-cmem                  Free previously booked cmem segment by name-<device>-<dma>
    -?, --help                       Give this help list
        --iface=<iface>              Send data to the interface. [calculated: use --ip value]
    -i, --ip=<ip>                    Publish data on the ip address IP. [default: libfabric:127.0.0.1]
    -v, --verbose                    Produce verbose output
        --verbose-bus                Produce verbose output for bus
    -V, --version                    Print program version
        --vid=N                      VID (Version Id) to set in FID (Felix ID) [default: 1]
    Trickle Options:
    -c, --cmem=SIZE                 CMEM buffer size in MB. [default: 800]
    -p, --port=PORT                 Send data to port PORT. [calculated: 53600 + 10*device + dma]
)";
}


void ConfigTrickle::handle_cmd_line(std::map<std::string, docopt::value> args)
{
    auto devices = args["--device"].asStringList();
    for(const auto& i : devices){
        resource.device.push_back(stoi(i));
    }

    resource.vid = args["--vid"].asLong();
    resource.did = args["--did"].asLong();

    auto cids = args["--cid"].asStringList();
    if (cids.empty()) { // No cids, impossible, there should be the default
        ers::error(felix_log::config_issue("No cid provided, aborting."));
        throw std::runtime_error("No cid provided, aborting.");
    }
    else if (cids.size() == 1) {
        if ( cids.at(0) == "device" ) {
            resource.cid = resource.device;
        }
        else {
            int base_cid = stoi(cids.at(0), 0, 16);
            for(unsigned int i = 0; i < resource.device.size(); ++i) {
                resource.cid.push_back(base_cid + i);
            }
        }
    }
    else if (cids.size() == devices.size()){
        for(unsigned int i = 0; i < cids.size(); ++i) {
            uint16_t cid = static_cast<uint16_t>(stoi(cids.at(i), 0, 16));
            resource.cid.push_back(cid);
        }
    }
    else {
        ers::error(felix_log::config_issue("The number of provided CIDs is not one nor equal to the number of devices."));
        throw std::runtime_error("No cid provided, aborting.");
    }

    resource.free_previous_cmem = args["--free-cmem"].asBool();

    network.bus_dir = args["--bus-dir"].asString();
    network.bus_groupname = args["--bus-groupname"].asString();
    network.verbose_bus = args["--verbose-bus"].asBool();

    verbose = args["--verbose"].asBool();

    // derive ip
    if (args["--iface"]) {
        network.ip = utility::get_value_from_getifaddrs(args["--iface"].asString());
    } else {
        network.ip = args["--ip"].asString();
    }

    resource.cmem_buffersize = args["--cmem"].asLong() * 1024 * 1024;

    constexpr static uint16_t default_port = 0;
    const uint16_t trickle_port = args["--port"] ? args["--port"].asLong() : default_port;
    for(auto dev : resource.device){
        network.ports.emplace(dev, trickle_port);
    }
}