Skip to content
Snippets Groups Projects
Select Git revision
  • 74a8e2bad4464e1ca24b788c1f5f0199e4f7dbd0
  • 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 18.30 KiB
    /* *************************************************************************
    * Copyright 2020
    * ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
    * P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * 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.
    * *********************************************************************** */
    
    /* *************************************************************************
    * Author:
    * . Leon Hiemstra
    * . Pieter Donker
    * Purpose:
    * . opc-ua to ucp translator
    * Description:
    * . class with fpga registers available for opc-ua server
    * *********************************************************************** */
    
    #ifndef _REENTRANT
    #error ACK! You need to compile with _REENTRANT defined since this uses threads
    #endif
    
    #include <cstdio>
    #include <stdexcept>
    #include <iostream>
    #include <sstream>
    #include <exception>
    
    #include "constants.h"
    #include "fpga.h"
    #include "tools/parse.h"
    
    using namespace std;
    
    // Everything addressed with FPGA_...
    
    extern int debug;
    
    Fpga::Fpga(list<class Node*>& nodelist)
    {
        FPGA = nodelist;
        pointMap = new CPointMap();
    
        // Add points:
        vector<int> nodes = get_all_nodes();
    
        pointMap->add_register("FPGA_mask_R",                                    "fpga/enable_mask",                            nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_mask_RW",                                   "fpga/enable_mask",                            nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_status_R",                                  "fpga/status",                                 nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_temp_R",                                    "fpga/temp",                                   nodes.size(), 1, "RO", REG_FORMAT_DOUBLE,  1);
        pointMap->add_register("FPGA_version_R",                                 "fpga/name",                                   nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
        pointMap->add_register("FPGA_firmware_version_R",                        "fpga/firmware_version",                       nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
        pointMap->add_register("FPGA_hardware_version_R",                        "fpga/hardware_version",                       nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
        pointMap->add_register("FPGA_sst_offload_selector_R",                    "fpga/sst_offload_selector",                   nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_sst_offload_selector_RW",                   "fpga/sst_offload_selector",                   nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_sst_offload_enable_R",                      "fpga/sst_offload_enable",                     nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_sst_offload_enable_RW",                     "fpga/sst_offload_enable",                     nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_sst_offload_hdr_eth_destination_mac_R",     "fpga/sst_offload_hdr_eth_destination_mac",    nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
        pointMap->add_register("FPGA_sst_offload_hdr_eth_destination_mac_RW",    "fpga/sst_offload_hdr_eth_destination_mac",    nodes.size(), 1, "RW", REG_FORMAT_STRING,  1);
        pointMap->add_register("FPGA_sst_offload_hdr_ip_destination_address_R",  "fpga/sst_offload_hdr_ip_destination_address", nodes.size(), 1, "RO", REG_FORMAT_STRING,  1);
        pointMap->add_register("FPGA_sst_offload_hdr_ip_destination_address_RW", "fpga/sst_offload_hdr_ip_destination_address", nodes.size(), 1, "RW", REG_FORMAT_STRING,  1);
        pointMap->add_register("FPGA_sst_offload_hdr_udp_destination_port_R",    "fpga/sst_offload_hdr_udp_destination_port",   nodes.size(), 1, "RO", REG_FORMAT_UINT16,  1);
        pointMap->add_register("FPGA_sst_offload_hdr_udp_destination_port_RW",   "fpga/sst_offload_hdr_udp_destination_port",   nodes.size(), 1, "RW", REG_FORMAT_UINT16,  1);
        pointMap->add_register("FPGA_processing_enable_R",                       "fpga/processing_enable",                      nodes.size(), 1, "RO", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_processing_enable_RW",                      "fpga/processing_enable",                      nodes.size(), 1, "RW", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_sdp_info_station_id_R",                     "fpga/sdp_info_station_id",                    nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_station_id_RW",                    "fpga/sdp_info_station_id",                    nodes.size(), 1, "RW", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_observation_id_R",                 "fpga/sdp_info_observation_id",                nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_observation_id_RW",                "fpga/sdp_info_observation_id",                nodes.size(), 1, "RW", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_nyquist_sampling_zone_index_R",    "fpga/sdp_info_nyquist_sampling_zone_index",   nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_nyquist_sampling_zone_index_RW",   "fpga/sdp_info_nyquist_sampling_zone_index",   nodes.size(), 1, "RW", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_antenna_band_index_R",             "fpga/sdp_info_antenna_band_index",            nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_f_adc_R",                          "fpga/sdp_info_f_adc",                         nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_fsub_type_R",                      "fpga/sdp_info_fsub_type",                     nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
        pointMap->add_register("FPGA_sdp_info_block_period_R",                   "fpga/sdp_info_block_period",                  nodes.size(), 1, "RO", REG_FORMAT_UINT32,  1);
    
        pointMap->add_register("FPGA_wg_enable_R",                               "fpga/wg_enable",                              nodes.size(), C_S_pn, "RO", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_wg_enable_RW",                              "fpga/wg_enable",                              nodes.size(), C_S_pn, "RW", REG_FORMAT_BOOLEAN, 1);
        pointMap->add_register("FPGA_wg_amplitude_R",                            "fpga/wg_amplitude",                           nodes.size(), C_S_pn, "RO", REG_FORMAT_DOUBLE,  1);
        pointMap->add_register("FPGA_wg_amplitude_RW",                           "fpga/wg_amplitude",                           nodes.size(), C_S_pn, "RW", REG_FORMAT_DOUBLE,  1);
        pointMap->add_register("FPGA_wg_phase_R",                                "fpga/wg_phase",                               nodes.size(), C_S_pn, "RO", REG_FORMAT_DOUBLE,  1);
        pointMap->add_register("FPGA_wg_phase_RW",                               "fpga/wg_phase",                               nodes.size(), C_S_pn, "RW", REG_FORMAT_DOUBLE,  1);
        pointMap->add_register("FPGA_wg_frequency_R",                            "fpga/wg_frequency",                           nodes.size(), C_S_pn, "RO", REG_FORMAT_DOUBLE,  1);
        pointMap->add_register("FPGA_wg_frequency_RW",                           "fpga/wg_frequency",                           nodes.size(), C_S_pn, "RW", REG_FORMAT_DOUBLE,  1);
    
        pointMap->add_register("FPGA_bsn_monitor_input_bsn_R",                   "fpga/bsn_monitor_input_bsn",                  nodes.size(), 1, "RO", REG_FORMAT_INT64,  1);
        pointMap->add_register("FPGA_bsn_monitor_input_nof_packets_R",           "fpga/bsn_monitor_input_nof_packets",          nodes.size(), 1, "RO", REG_FORMAT_INT32,  1);
        pointMap->add_register("FPGA_bsn_monitor_input_nof_valid_R",             "fpga/bsn_monitor_input_nof_valid",            nodes.size(), 1, "RO", REG_FORMAT_INT32,  1);
        pointMap->add_register("FPGA_bsn_monitor_input_nof_err_R",               "fpga/bsn_monitor_input_nof_err",              nodes.size(), 1, "RO", REG_FORMAT_INT32,  1);
        
        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]);
            CPointMap *regmap = node->get_RegisterMap();
            scrap_span_next = regmap->getDataSize("fpga/scrap");
            if (scrap_span_next > scrap_span_prev) {
                scrap_span = scrap_span_next;
            }
            scrap_span_prev = scrap_span_next;
        }
        cout << "scrap_span=" << scrap_span << endl;
        pointMap->add_register("FPGA_scrap_R",                                   "fpga/scrap",                                  nodes.size(), scrap_span, "RO", REG_FORMAT_UINT32, 1);
        pointMap->add_register("FPGA_scrap_RW",                                  "fpga/scrap",                                  nodes.size(), scrap_span, "RW", REG_FORMAT_UINT32, 1);
        
        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]);
            CPointMap *regmap = node->get_RegisterMap();
            weights_span_next = regmap->getDataSize("fpga/weights");
            if (weights_span_next > weights_span_prev) {
                weights_span = weights_span_next;
            }
            weights_span_prev = weights_span_next;
        }
        cout << "weights_span=" << weights_span << endl;
        pointMap->add_register("FPGA_weights_R",                                 "fpga/weights",                                nodes.size(), weights_span, "RO", REG_FORMAT_INT16, 1);
        pointMap->add_register("FPGA_weights_RW",                                "fpga/weights",                                nodes.size(), weights_span, "RW", REG_FORMAT_INT16, 1);
    }
    
    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");
    }
    
    vector<int> Fpga::get_all_nodes(void)
    {
        vector<int> nodes;
        for (auto node : FPGA) {
            nodes.push_back(node->GetGlobalNr());
        }
        return nodes;
    }
    
    vector<bool> Fpga::get_all_enabled_nodes(void)
    {
        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();
    }
    
    CPointMap * Fpga::get_pointMap(void)
    {
        return pointMap;
    }
    
    bool Fpga::point(TermOutput& termout, const char cmd, const string addr,
                     const unsigned int *data, CMData& cm, const int nvalues)
    {
        bool ret, retval = false;
        uint retcnt = 0;
    
        termout.clear();
        string relative_addr = pointMap->getRelativeName(addr);
        string type = "fpga";
        string instance = "";
    
        try {
            if (cmd == 'R') {
                pointMap->getReadPermission(addr);
            }
            else if (cmd == 'W') {
                pointMap->getWritePermission(addr);
            }
        } catch (exception& e) {
            cerr << "Fpga::point: " << addr << " error: " << e.what() << endl;
            return false;
        }
    
        int format = pointMap->getFormat(addr);
    
        vector<int> nodes = get_all_nodes();
    
        TermOutput termresults;
    
        if (cmd == 'R') {
            retval = true;
        }
        else if (cmd == 'W') {
            if (nvalues < (int)pointMap->getDataSize(addr)) {
                return false;
            }
            retval = true;
        }
    
        for (uint idx = 0; idx<nodes.size(); idx++) {
            auto node = select_node(nodes[idx]);
            // if (node->getEnabled() == false) { continue; }
    
            CPointMap *regmap = node->get_RegisterMap();
            int span = regmap->getDataSize(relative_addr);
            
            int nof_values = nvalues;
            if (nvalues < 0 || nvalues > span) {
                nof_values = span;
            }
    
            ret = false;
            bool done = false;
            try {
                if ((cmd == 'W') && (cm.getFormat() == FORMAT_STRING)) {
                    uint *data2 = new uint[20];
                    memset((void *)data2, 0, sizeof(data2));
                    cout << "str=" << cm.getStr(idx) << " len=" << cm.getStrLen(idx) << endl;
                    memcpy((void *)data2, (void *)cm.getStrPtr(idx), cm.getStrLen(idx));
                    nof_values = cm.getStrLen(idx);
                    if ((ret = node->exec_cmd(cmd, relative_addr, type, instance,
                                              data2, nof_values, format))) {
                        retcnt++;
                        done = true;
                    }
                    delete[] data2;
                }
                if (!done) {
                    uint didx = 0;
                    if (cmd == 'W') {
                        didx = idx * nof_values;
                    }
                    if ((ret = node->exec_cmd(cmd, relative_addr, type, instance,
                                              &data[didx], nof_values*sizeof(unsigned int), format))) {
                        retcnt++;
                    }
                }
            } catch (exception& e) {
                cerr << e.what() << endl;
            }
    
        }
        retval = (retcnt == nodes.size());
        if (!retval) {
            return false;
        }
    
        termout.nof_vals = pointMap->getNodesSize(addr) * pointMap->getDataSize(addr);
        termout.datatype = pointMap->getFormat(addr);
    
        for (uint idx=0; idx<nodes.size(); idx++) {
            auto node = select_node(nodes[idx]);
    
            ret = false;
            termresults.clear();
            try {
                if ((ret = node->exec_reply(termresults))) {
                    retcnt++;
                }
            } catch (exception& e) {
                cerr << e.what() << endl;
            }
            if (cmd == 'R') {
                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_INT64: {
                        int64_t *ptr_in = (int64_t *)termresults.val;
                        int64_t *ptr_out = (int64_t *)termout.val;
                        for (uint i=0; i<termresults.nof_vals; i++) {
                            ptr_out[idx * termresults.nof_vals + i] = ptr_in[i];
                        }
                    } break;
                    case REG_FORMAT_UINT64: {
                        uint64_t *ptr_in = (uint64_t *)termresults.val;
                        uint64_t *ptr_out = (uint64_t *)termout.val;
                        for (uint i=0; i<termresults.nof_vals; i++) {
                            ptr_out[idx * termresults.nof_vals + i] = ptr_in[i];
                        }
                    } break;
                    case REG_FORMAT_INT32: {
                        int32_t *ptr_in = (int32_t *)termresults.val;
                        int32_t *ptr_out = (int32_t *)termout.val;
                        for (uint i=0; i<termresults.nof_vals; i++) {
                            ptr_out[idx * termresults.nof_vals + i] = ptr_in[i];
                        }
                    } break;
                    case REG_FORMAT_UINT32: {
                        uint32_t *ptr_in = (uint32_t *)termresults.val;
                        uint32_t *ptr_out = (uint32_t *)termout.val;
                        for (uint i=0; i<termresults.nof_vals; i++) {
                            ptr_out[idx * termresults.nof_vals + i] = ptr_in[i];
                        }
                    } break;
                    case REG_FORMAT_INT16: {
                        int16_t *ptr_in = (int16_t *)termresults.val;
                        int16_t *ptr_out = (int16_t *)termout.val;
                        for (uint i=0; i<termresults.nof_vals; i++) {
                            ptr_out[idx * termresults.nof_vals + i] = ptr_in[i];
                        }
                    } break;
                    case REG_FORMAT_UINT16: {
                        uint16_t *ptr_in = (uint16_t *)termresults.val;
                        uint16_t *ptr_out = (uint16_t *)termout.val;
                        for (uint 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_DOUBLE: {
                        double *ptr_in = (double *)termresults.val;
                        double *ptr_out = (double *)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;
                    default: {
                        cout << "fpga-r320, Not supported datatype (" << termresults.datatype << " in " << addr << endl;
                    } break;
                }
            }
            else if (cmd == 'W') {
                // nothing
            }
        }
    
        if (nodes.size() == 0) {
            cerr << "no nodes";
            retval = false;
        }
    
        return retval;
    }
    
    bool Fpga::is_fpga(const string addr)
    {
        bool retval = false;
        stringstream strs(addr);
        string token;
        vector<string> tokens;
    
        while (getline(strs, token, '_')) {
            tokens.push_back(token);
        }
        if (tokens.size() > 1) {
            if (tokens[0] == "FPGA") {
                retval = true;
            }
        }
        return retval;
    }