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.88 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 <cstdio>
#include <stdexcept>
#include <iostream>
#include <sstream>
#include <exception>
#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 RegisterMap();
// Add points:
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");
}
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();
}
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();
string relative_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;
}
// 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);
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 (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 (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;
default: {
printf("fpga-r320, Not supported datatype (%d)\n", termresults.datatype);
} 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;
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;
}