Program Listing for File device.cpp

Return to documentation for file (device.cpp)

#include <algorithm>

#include "device.hpp"
#include "log.hpp"

#define BROADCAST_NONE    0
#define BROADCAST_ALL     1
#define BROADCAST_CHANNEL 2
#define BROADCAST_ELINK   3

#define MAX_BROADCAST_CHANNELS (32)
#define MAX_BROADCAST_ELINKS (1 + 32 + 64)

Device::Device(unsigned dev_no, uint8_t vid, uint16_t did, uint16_t cid)
    : m_device_number(dev_no), m_vid(vid), m_did(did), m_cid(cid) {}


bool Device::has_wrong_rm() {
    unsigned int regmap = get_regmap_version();
#if REGMAP_VERSION < 0x0500
    return ((regmap < 0x0400) || (regmap >= 0x0500));
#else
    return ((regmap < 0x0500) || (regmap >= 0x0600));
#endif
}


bool Device::is_full_mode() {
    return (m_firmware_type == FIRMW_FULL or m_firmware_type == FIRMW_MROD or m_firmware_type == FIRMW_INTERLAKEN);
}


bool Device::is_lpgbt_mode() {
    u_int mode = m_firmware_type;
    return (mode == FIRMW_PIXEL or mode == FIRMW_STRIP or mode == FIRMW_LPGBT or mode == FIRMW_HGTD_LUMI or mode == FIRMW_BCM_PRIME);
}


uint64_t Device::get_elink(u_int channel, u_int egroup, u_int epath) {
    bool lpgbt = this->is_lpgbt_mode();
    int egroup_shift = (lpgbt) ? 2 : 3;
    return (channel << 6) + (egroup << egroup_shift) + epath;
}


uint32_t Device::get_channel(uint32_t elink) {
    return (elink >> 6);
}


uint32_t Device::get_egroup(uint32_t elink) {
    bool lpgbt = this->is_lpgbt_mode();
    int egroup_shift = (lpgbt) ? 2 : 3;
    return (elink & 0x3f) >> egroup_shift;
}


uint32_t Device::get_epath(uint32_t elink) {
    bool lpgbt = this->is_lpgbt_mode();
    int egroup_shift = (lpgbt) ? 2 : 3;
    return egroup_shift == 2 ? elink & 0x03 : elink & 0x07;
}


u_int Device::get_egroups_per_channel(u_int is_to_flx) {
    u_int egroups_per_chan;
    if( is_to_flx == 0 ) {
        // tohost
        if( this->is_full_mode() )
            egroups_per_chan = 1;
        else if( this->is_lpgbt_mode() )
            egroups_per_chan = 7;
        else if( this->get_wide_mode() )
            egroups_per_chan = 7;
        else
            egroups_per_chan = 5;
    } else {
        // toflx
        if( this->is_full_mode() )
            egroups_per_chan = 5;
        else if( this->is_lpgbt_mode() )
            egroups_per_chan = 4;
        else if( this->get_wide_mode() )
            egroups_per_chan = 3;
        else
            egroups_per_chan = 5;
    }
  return egroups_per_chan;
}


u_int Device::get_epaths_per_egroup(u_int is_to_flx) {
    int epaths_per_egroup;
    if( is_to_flx == 0 ) {
    // tohost
        if( this->is_full_mode() )
            epaths_per_egroup = 1;
        else if( this->is_lpgbt_mode() )
            epaths_per_egroup = 4;
        else if( this->get_wide_mode())
            epaths_per_egroup = 8;
        else
            epaths_per_egroup = 8;
    } else {
        // toflx
        if( this->is_full_mode() )
            epaths_per_egroup = 8;
        else if( this->is_lpgbt_mode() and this->get_firmware_type() != FIRMW_STRIP )
            epaths_per_egroup = 4;
        else if( this->is_lpgbt_mode() and this->get_firmware_type() == FIRMW_STRIP )
            epaths_per_egroup = 5;
        else if( this->get_wide_mode() )
            epaths_per_egroup = 8;
        else
            epaths_per_egroup = 8;
    }
    return epaths_per_egroup;
}


u_int Device::get_ctrl_elinks_per_channel() {
    if( m_firmware_type == FIRMW_LTDB )
        return 3; // IC, EC, AUX
    else
        return  2; // IC, EC
}


const std::string Device::get_elink_type_str(elink_type_t encoding) {
    switch(encoding) {
        case NONE_ELINK_TYPE: return "NONE_ELINK_TYPE";
        case DAQ: return "DAQ";
        case TTC: return "TTC";
        case DCS: return "DCS";
        case IC: return "IC";
        default: return "UNKNOWN";
    }
}


std::vector<Elink> Device::get_enabled_elinks_of_type(int dmaid, elink_type_t t)
{
    auto all_elinks = read_enabled_elinks(dmaid);
    std::vector<Elink> ret;
    std::copy_if(all_elinks.begin(), all_elinks.end(),  std::back_inserter(ret), [t](Elink e) { return e.type == t; });

//    for (auto& e : all_elinks){
//        if ( e.type == t ){
//            ret.emplace_back(e);
//        }
//    }
    return ret;
}

unsigned int Device::make_dma_lock_mask(const std::vector<int>& dmaids)
{
    unsigned int lock_mask(LOCK_NONE);
    for(int id : dmaids){
        lock_mask |= LOCK_DMA(id);
    }
    return lock_mask;
}


int64_t Device::broadcast_for(uint64_t elink) {
    if ((elink & 0x7ff) == 0x7ff) return -1;
    if ((elink & 0x3f) == 0x3f) return (elink >> 6) & 0x1f;
    if ((elink & (0x1f << 6)) == (0x1f << 6)) return elink & 0x3f;
    return elink;
}


int Device::broadcast_type(uint64_t elink) {
    if ((elink & 0x7ff) == 0x7ff) return BROADCAST_ALL;
    if ((elink & 0x3f) == 0x3f) return BROADCAST_CHANNEL;
    if ((elink & (0x1f << 6)) == (0x1f << 6)) return BROADCAST_ELINK;
    return BROADCAST_NONE;
}


const std::string Device::broadcast_type_str(uint64_t elink) {
    switch(Device::broadcast_type(elink)) {
        case BROADCAST_NONE:
            return "None";
        case BROADCAST_ALL:
            return "All";
        case BROADCAST_CHANNEL:
            return "Channel";
        case BROADCAST_ELINK:
            return "E-Link";
        default:
            return "Unknown";
    }
}


// Note allow an array of MAX_BROADCAST_ELINKS for bc_elinks.
unsigned Device::broadcast_elinks(uint64_t broadcast_elinks[], const uint64_t broadcast_enable_registers[], uint32_t num_of_channels) {
    unsigned no_of_broadcast_elinks = 0;

    int broadcast_to_all = 0;
    int broadcast_to_elink[64] = {0};
    for (uint32_t channel = 0; channel < num_of_channels; channel++) {
        if (broadcast_enable_registers[channel] > 0) {
            // Save Broadcast to All
            broadcast_to_all = 1;

            // Add Broadcast to all e-links of one link
            broadcast_elinks[no_of_broadcast_elinks] = ((channel << 6) | 0x03F);
            // LOG_INFO("Broadcast for link %d to 0x%x", link, broadcast_elinks[no_of_broadcast_elinks]);
            no_of_broadcast_elinks++;

            // Save Broadcast to 1 e-link of all links
            for (uint32_t elink = 0; elink < 64; elink++) {
                if (broadcast_enable_registers[channel] & (1UL << elink)) {
                    // LOG_INFO("Adding for link %d, elink %d, based on 0x%x and mask 0x%x", link, elink, broadcast_enable_registers[link], (1 << elink));
                    broadcast_to_elink[elink] = 1;
                }
            }
        }
    }

    // Add Broadcast to 1 e-link of all links
    for (uint32_t elink = 0; elink < 64; elink++) {
        if (broadcast_to_elink[elink]) {
            broadcast_elinks[no_of_broadcast_elinks] = ((0x1F << 6) | elink);
            //LOG_INFO("Broadcast for elink 0x%x to 0x%x", elink, broadcast_elinks[no_of_broadcast_elinks]);
            no_of_broadcast_elinks++;
        }
    }

    // Add Broadcast to All if needed
    if (broadcast_to_all) {
        broadcast_elinks[no_of_broadcast_elinks] = 0x7ff;
        //LOG_INFO("Broadcast all for links to 0x%x", broadcast_elinks[no_of_broadcast_elinks]);
        no_of_broadcast_elinks++;
    }

    return no_of_broadcast_elinks;
}


u_int Device::get_broadcast_elinks(uint64_t broadcast_elinks[], uint32_t num_of_channels) {
    uint64_t broadcast_enable_registers[MAX_BROADCAST_CHANNELS];

    for( unsigned channel=0; channel < num_of_channels; ++channel ) {
        broadcast_enable_registers[channel] = get_broadcast_enable_gen(channel);
    }

    unsigned no_of_broadcast_elinks = Device::broadcast_elinks(broadcast_elinks, broadcast_enable_registers, num_of_channels);

    LOG_INFO("Deduced %d broadcast elinks", no_of_broadcast_elinks);
    return no_of_broadcast_elinks;
}