Select Git revision
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;
}