Skip to content
Snippets Groups Projects
Select Git revision
  • 2054a2f7d4682359bf75b1e3b01f2ca26e2d65d3
  • master default protected
  • fix-64-bit
  • L2SDP-261
  • 2021-04-14T14.09.01_sdptr
  • 2021-04-14T13.43.34_sdptr
6 results

fpga.cpp

Blame
  • Forked from LOFAR2.0 / sdptr
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    fpga.cpp 10.92 KiB
    /*
     * Copyright 2020 Stichting Nederlandse Wetenschappelijk Onderzoek Instituten,
     * ASTRON Netherlands Institute for Radio Astronomy
     * Licensed under the Apache License, Version 2.0 (the "License");
     *
     * you may not use this file except in compliance with the License.
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     * See ../LICENSE.txt for more info.
     */
    
    #ifndef _REENTRANT
    #error ACK! You need to compile with _REENTRANT defined since this uses threads
    #endif
    
    #include <iostream>
    #include <sstream>
    #include <iomanip>
    #include <fstream>
    #include <vector>
    #include <algorithm>
    #include <string>
    #include <strings.h>
    
    #include <sys/time.h>
    #include <boost/numeric/ublas/matrix.hpp>
    #include <boost/array.hpp>
    #include <boost/numeric/ublas/io.hpp>
    #include <boost/regex.hpp>
    #include <boost/algorithm/string.hpp>
    #include <dirent.h>
    #include <fnmatch.h>
    #include <arpa/inet.h> //inet_aton
    
    #include "fpga.h"
    #include "tools/parse.h"
    
    // Everything addressed with fpga_...
    
    extern int debug;
    using namespace std;
    
    Fpga::Fpga(list<class Node*>& nodelist)
    {
        FPGA = nodelist;
        pointMap = new RegisterMap();
    
        // Add points:
        std::vector<int> nodes = get_all_nodes();
    
        pointMap->add_register("fpga_mask_RW",            0, nodes.size(), 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_BOOLEAN);
        pointMap->add_register("fpga_status_R",           0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_BOOLEAN);
        pointMap->add_register("fpga_temp_R",             0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_FLOAT);
        pointMap->add_register("fpga_version_R",          0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
        pointMap->add_register("fpga_firmware_version_R", 0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
        pointMap->add_register("fpga_hardware_version_R", 0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
    
        uint32_t scrap_span = 0;
        uint32_t scrap_span_next = 0;
        uint32_t scrap_span_prev = 0;
        for(uint idx = 0; idx<nodes.size(); idx++) {
            auto node = select_node(nodes[idx]);
            RegisterMap *regmap = node->get_RegisterMap();
            scrap_span_next = regmap->getSpan("fpga/scrap_RW");
            if(scrap_span_next > scrap_span_prev) scrap_span = scrap_span_next;
            scrap_span_prev = scrap_span_next;
        }
        printf("scrap_span=%d\n",scrap_span);
        scrap_span *= nodes.size();
        printf("scrap_span=%d\n",scrap_span);
        pointMap->add_register("fpga_scrap_R",   0, scrap_span, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INTEGER);
        pointMap->add_register("fpga_scrap_RW",  0, scrap_span, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_INTEGER);
    
        uint32_t weights_span = 0;
        uint32_t weights_span_next = 0;
        uint32_t weights_span_prev = 0;
        for(uint idx = 0; idx<nodes.size(); idx++) {
            auto node = select_node(nodes[idx]);
            RegisterMap *regmap = node->get_RegisterMap();
            weights_span_next = regmap->getSpan("fpga/weights_RW");
            if(weights_span_next > weights_span_prev) weights_span = weights_span_next;
            weights_span_prev = weights_span_next;
        }
        printf("weights_span=%d\n",weights_span);
        weights_span *= nodes.size();
        printf("weights_span=%d\n",weights_span);
        pointMap->add_register("fpga_weights_R",   0, weights_span, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INT16);
        pointMap->add_register("fpga_weights_RW",  0, weights_span, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_INT16);
    }
    
    Fpga::~Fpga()
    {
        if(pointMap != NULL) delete pointMap;
    }
    
    Node * Fpga::select_node(const int nr)
    {
        for(auto node : FPGA) {
            if(node->GetGlobalNr() == (uint)nr) return node;
        }
        throw runtime_error("select_node: not found");
    }
    
    std::vector<int> Fpga::get_all_nodes(void)
    {
        std::vector<int> nodes;
        for(auto node : FPGA) {
            nodes.push_back(node->GetGlobalNr());
        }
        return nodes;
    }
    
    std::vector<bool> Fpga::get_all_enabled_nodes(void)
    {
        std::vector<bool> enabled;
        for(auto node : FPGA) {
            enabled.push_back(node->GetEnabled());
        }
        return enabled;
    }
    
    uint Fpga::node_number(Node *node)
    {
        return (node->GetUniboardNr() * 4) + node->GetLocalNr();
    }
    
    RegisterMap * Fpga::get_pointMap(void)
    {
        return pointMap;
    }
    
    bool Fpga::point(const uint clientId, TermOutput& termout, const char cmd, const string addr, 
                     const unsigned int *data, const int nvalues)
    {
        bool ret, retval = false;
        uint retcnt = 0;
    
        termout.clear();
        std::string relative_addr;
        std::string type          = "fpga";
        std::string instance      = "";
    
    
        try {
            if(cmd == 'R') pointMap->getReadPermission(addr);
            else if(cmd == 'W') pointMap->getWritePermission(addr);
        } catch(std::exception& e) {
            cerr << "Fpga::point: " << addr << " error: " << e.what() << endl;
            return false;
        }
    
        // FIXME: move these relative_addr to some new pointmap entry
        if(addr == "fpga_mask_RW") {
            relative_addr = "fpga/enable_mask_RW";
        } else if(addr == "fpga_status_R") {
            relative_addr = "fpga/status";
        } else if(addr == "fpga_temp_R") {
            relative_addr = "fpga/temp";
        } else if(addr == "fpga_version_R") {
            relative_addr = "fpga/name";
        } else if(addr == "fpga_firmware_version_R") {
            relative_addr = "fpga/firmware_version";
        } else if(addr == "fpga_hardware_version_R") {
            relative_addr = "fpga/hardware_version";        
        } else if(addr == "fpga_scrap_R") {
            relative_addr = "fpga/scrap_R";
        } else if(addr == "fpga_scrap_RW") {
            relative_addr = "fpga/scrap_RW";
        } else if(addr == "fpga_weights_R") {
            relative_addr = "fpga/weights_R";
        } else if(addr == "fpga_weights_RW") {
            relative_addr = "fpga/weights_RW";
        } else {
            retval = false;
            termout.strerr << "no such register: " << addr;
        }
    
        int format = (int)pointMap->getFormat(addr);
    
        std::vector<int> nodes = get_all_nodes();
    
        ostringstream strs, strs_pre;
        TermOutput termresults;
    
        termout.strout << "nodes=[";
        for(auto n : nodes) {
            termout.strout << n << " ";
        }
        termout.strout << "]";
    
        if(cmd == 'R') {
            termout.strout << " point read ok";
            retval = true;
        } else if(cmd == 'W') {
            if(nvalues < (int)pointMap->getSpan(addr)) {
                termout.strerr << "point write nvalues < span" << endl;
                return false;
            }
            termout.strout << " point write ok";
            retval = true;
        }
    
        strs_pre << "[";
        for(uint idx = 0; idx<nodes.size(); idx++) {
            auto node = select_node(nodes[idx]);
            uint node_nr = node_number(node);
    
            RegisterMap *regmap = node->get_RegisterMap();
            int span = regmap->getSpan(relative_addr);
            int nof_values = nvalues;
            if(nvalues < 0 || nvalues > span) nof_values = span;
    
            if(idx > 0) strs_pre << ",";
        
            strs.str(""); strs.clear();
            ret = false;
            try {
                uint didx = 0;
                if(cmd == 'W') {
                    didx = idx*nof_values;
                }
                if((ret=node->exec_cmd(clientId, strs, cmd, relative_addr, type, instance, 
                                       &data[didx], nof_values, format))) {
                    retcnt++;
                }
            } catch(std::exception& e) {
                termout.strerr << e.what() << endl;
            }
            strs_pre << "(" << node_nr << "," << (ret ? "0)" : "1)");
        
        }
        strs_pre << "]";
        retval = (retcnt==nodes.size());
        if(!retval) {
            termout.strout << strs_pre.str();
            return false;
        }
    
        termout.nof_vals = pointMap->getSpan(addr);
        termout.datatype = format;
        
        termout.strout << "[";
        for(uint idx=0;idx<nodes.size();idx++) {
            auto node = select_node(nodes[idx]);
            uint node_nr = node_number(node);
            if(idx > 0) termout.strout << ",";
        
            strs.str(""); strs.clear();
            ret = false;
            termresults.clear();
            try {
                if((ret=node->exec_reply(clientId, termresults))) {
                    retcnt++;
                }
            } catch(std::exception& e) {
                termout.strerr << e.what() << endl;
            }
            if(cmd == 'R') {
                termout.strout << "(" << node_nr << (ret ? ",0,[" : ",1,[") << termresults.strout.str() << "])";
    
                switch(termresults.datatype) {
                  case REG_FORMAT_BOOLEAN: {
                          bool *ptr_in = (bool *)termresults.val;
                          bool *ptr_out = (bool *)termout.val;
                          for(unsigned int i=0;i<termresults.nof_vals;i++) {
                              ptr_out[idx*termresults.nof_vals+i] = ptr_in[i];
                          }
                      }
                      break;
                  case REG_FORMAT_INTEGER: {
                          int *ptr_in = (int *)termresults.val;
                          int *ptr_out = (int *)termout.val;
                          for(unsigned int i=0;i<termresults.nof_vals;i++) {
                              ptr_out[idx*termresults.nof_vals+i] = ptr_in[i];
                          }
                      }
                      break;
                  case REG_FORMAT_INT16: {
                          short *ptr_in = (short *)termresults.val;
                          short *ptr_out = (short *)termout.val;
                          for(unsigned int i=0;i<termresults.nof_vals;i++) {
                              ptr_out[idx*termresults.nof_vals+i] = ptr_in[i];
                          }
                      }
                      break;
                  case REG_FORMAT_FLOAT: {
                          float *ptr_in = (float *)termresults.val;
                          float *ptr_out = (float *)termout.val;
                          for(unsigned int i=0;i<termresults.nof_vals;i++) {
                              ptr_out[idx*termresults.nof_vals+i] = ptr_in[i];
                          }
                      }
                      break;
                  case REG_FORMAT_STRING: {
                          char *ptr_in = (char *)termresults.val;
                          char *ptr_out = (char *)termout.val;
                          ptr_out += (idx * SIZE1STRING);
                          strcpy(ptr_out, ptr_in);
                      }
                      break;
                }
    
    
            } else if(cmd == 'W') {
                termout.strout << "(" << node_nr << "," << (ret ? "0)" : "1)");
            }
        }
    
        termout.strout << "]";
        if(nodes.size() == 0) {
            termout.strerr << "no nodes";
            retval = false;
        }
    
        return retval;
    }
    
    bool Fpga::is_fpga(const string addr)
    {
        bool retval = false;
        std::stringstream strs(addr);
        std::string token;
        std::vector<std::string> tokens;
    
        while (std::getline(strs, token, '_')) {
            tokens.push_back(token);
        }
        if(tokens.size() > 1) {
            if(tokens[0] == "fpga") {
                retval = true;
            }
        }
        return retval;
    }