File asic_config_base.cpp

File List > libmudaq > asic_config_base.cpp

Go to the documentation of this file

//

#include "asic_config_base.h"

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <iterator>

#include <cstring>

namespace mudaq {

ASICConfigBase::para_t ASICConfigBase::make_param(std::string name, size_t nbits, bool endianess){
    std::vector<uint8_t> bitorder(nbits);
    if(endianess)
        for(size_t i=0;i<nbits;i++) bitorder[i]=i;
    else
        for(size_t i=0;i<nbits;i++) bitorder[i]=nbits-1-i;
    return std::make_tuple(name,nbits,bitorder);
}

ASICConfigBase::para_t ASICConfigBase::make_param(std::string name, size_t nbits, std::vector<uint8_t> bitorder){
    return std::make_tuple(name,nbits,bitorder);
}

ASICConfigBase::para_t ASICConfigBase::make_param(std::string name, std::string bitorderstring){
    std::istringstream is(bitorderstring);
    std::vector<unsigned int> order_t;
    std::vector<uint8_t> order;
    order_t.assign(std::istream_iterator<unsigned int>( is ), std::istream_iterator<unsigned int>() );

    for (unsigned int i = 0; i < order_t.size(); ++ i) {
        for (unsigned int n = 0; n < order_t.size(); ++n) {
            if (order_t.at(n) == i) {
                order.push_back((uint8_t)n);
            }
        }
    }
    //std::reverse(order.begin(), order.end());
    size_t sizze = (size_t)order.size();
    return std::make_tuple(name,sizze,order);
}

void ASICConfigBase::addPara(const para_t& para, const std::string postfix) {
    paras_offsets[std::get<0>(para)+postfix] = std::make_tuple(length_bits, std::get<1>(para), std::get<2>(para));
//reporting
//    printf("%s\t[%lu:%lu] (",(std::get<0>(para)+postfix).c_str(),length_bits,length_bits+std::get<1>(para));
//    for(size_t i=0;i<std::get<1>(para);i++) printf("%d ",std::get<2>(para)[i]);
//    printf(")\n");
//reporting

    length_bits += std::get<1>(para);
}

ASICConfigBase::ASICConfigBase(){
/*
    //assemble the pattern from the list of parameters. Needs to be done in inherited classes, here only for reference!
    // populate name/offset map
    length_bits = 0;
    // header
    for(const auto& para : parameters_header )
        addPara(para, "");
    for(unsigned int ch = 0; ch < nch; ++ch) {
        for(const auto& para : parameters_ch )
            addPara(para, "_"+std::to_string(ch));
    }
    for(const auto& para : parameters_tdc )
        addPara(para, "");
    //for(const auto& para : parameters_tdc ) addPara(para, "_right");
    for(const auto& para : parameters_footer )
        addPara(para, "");

    // allocate memory for bitpattern
    length = length_bits/8;
    if( length_bits%8 > 0 ) length++;
    length_32bits = length/4;
    if( length%4 > 0 ) length_32bits++;
    bitpattern_r = new uint8_t[length_32bits*4];
    bitpattern_w = new uint8_t[length_32bits*4];
    reset();
*/
}

ASICConfigBase::~ASICConfigBase(){
/*
 *  to be done in the inherited class
    delete[] bitpattern_r;
    delete[] bitpattern_w;
*/
}

int ASICConfigBase::setParameter(std::string name, uint32_t value, bool reverse) {
    auto para = paras_offsets.find(name);
    if( para == paras_offsets.end() ) {
        std::cerr << "Parameter '" << name << "' is not present in mutrig config" << std::endl;
        return 1; // parameter name not present
    }
    size_t offset;
    size_t nbits;
    std::vector<uint8_t> bitorder;
    std::tie(offset, nbits, bitorder) = para->second;
    if( (value >> nbits) != 0 ) {
        std::cerr << "Value '" << value << "' outside of range of " << nbits << " bits for '" << name << "'" << std::endl;
        return 2; // out of range
    }
    //printf("offset=%lu n=%lu\n",offset,nbits);
    uint32_t mask = 0x01;
    for(unsigned int pos = 0; (pos < nbits); pos++, mask <<= 1) {
        unsigned int n = (offset+bitorder.at(nbits-pos-1))%8;
        unsigned int b = (offset+bitorder.at(nbits-pos-1))/8;
        if (reverse) {
            n = (offset + nbits -1 - bitorder.at(pos))%8;
            b = (offset + nbits -1 - bitorder.at(pos))/8;
            //unsigned int b2 = length_bits/8;
            unsigned int b2 = length-1;
            b = b2 -b;
        }
        //printf("b:%3.3u.%1.1u = %u\n",b,n,mask&value);
        if ((mask & value) != 0 ) bitpattern_w[b] |=   1 << n;  // set nth bit
        else                      bitpattern_w[b] &= ~(1 << n); // clear nth bit
    }
    return 0;
}

uint32_t ASICConfigBase::getParameter(std::string name, bool reverse) {
    auto para = paras_offsets.find(name);
    if( para == paras_offsets.end() ) {
        std::cerr << "Parameter '" << name << "' is not present in mutrig config" << std::endl;
        return uint32_t(-1); // parameter name not present
    }
    unsigned int offset;
    size_t nbits;
    std::vector<uint8_t> bitorder;
    std::tie(offset, nbits, bitorder) = para->second;

    uint32_t value = 0;
    for(unsigned int pos = 0; pos < nbits; pos++) {
        unsigned int n = offset+bitorder.at(nbits-pos-1)%8;
        unsigned int b = offset+bitorder.at(nbits-pos-1)/8;
        if (reverse) {
            n = (offset + nbits -1 - bitorder.at(pos))%8;
            b = (offset + nbits -1 - bitorder.at(pos))/8;
            unsigned int b2 = length_bits/8;
            b = b2 -b;
        }
        value += ( ( (bitpattern_r[b] & (1 << n)) != 0 ) << pos);
    }
    return value;
}

int ASICConfigBase::reset(char o) {
    switch(o) {
      case 'r': std::memset(bitpattern_r, 0, length_32bits*4);
                break;
      case 'w': std::memset(bitpattern_w, 0, length_32bits*4);
                break;
      default:  std::memset(bitpattern_r, 0, length_32bits*4);
                std::memset(bitpattern_w, 0, length_32bits*4);
    }
    return 0;
}

std::string ASICConfigBase::getPattern() {
    std::stringstream buffer;
    buffer << *this;
    return buffer.str();
}

int ASICConfigBase::VerifyReadbackPattern(){
    m_verification_error="";
    for(size_t i=0;i<length-1;++i){
        if(bitpattern_w[i]!=bitpattern_r[i]){
        m_verification_error="Write/Read mismatch at byte "+std::to_string(i)+", written value "+std::to_string(bitpattern_w[i])+" vs. "+std::to_string(bitpattern_r[i]);
        return FE_ERR_HW;
    }
    }
    for(size_t i=0;i<length_bits%8;i++){
        if((bitpattern_w[length-1]&(1<<i))!=(bitpattern_r[length-1]&(1<<i))){
        m_verification_error="Write/Read mismatch at last byte ("+std::to_string(i)+"), written value "+std::to_string(bitpattern_w[i])+" vs. "+std::to_string(bitpattern_r[i]);
        return FE_ERR_HW;
    }

    }
    return FE_SUCCESS;
}

std::ostream& operator<<(std::ostream& os, const ASICConfigBase& config) {
    os << " bitpattern: (" << config.length << "/" << config.length_bits << ") 0x" << std::hex;
    os << std::endl<<" write: 0x" << std::hex;
    for( unsigned int i = 0; i < config.length; i++) os << std::setw(2) << std::setfill('0') << ((uint16_t)config.bitpattern_w[config.length - i - 1]); // << " ";// << config.bitpattern_r[i] << " ";
    //os << std::endl;
    os << std::endl<<" read:  0x" << std::hex;
    for( unsigned int i = 0; i < config.length; i++) os << std::setw(2) << std::setfill('0') << ((uint16_t)config.bitpattern_r[config.length - i - 1]);
    os << std::endl;
    os << std::dec;
    //std::cout << "bitpattern write: 0x" << std::hex << std::setw(2) << std::setfill('0') << config.bitpattern_w[0] << std::endl;
    return os;
}


} // namespace mudaq