Select Git revision

Pieter Donker authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
fpga.cpp 26.45 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 <stdexcept>
#include <iostream>
#include <exception>
#include <unistd.h>
#include "fpga.h"
#include "../tools/mmap.h"
#include "../tools/util.h"
#include<iostream>
#include<fstream>
using namespace std;
extern int debug;
Periph_fpga::Periph_fpga(UCP *ucp,
const string expected_design_name,
const uint expected_firmware_version, const bool enabled)
{
my_expected_design_name = expected_design_name;
my_expected_firmware_version = expected_firmware_version;
my_current_status = "offline";
my_current_fw_version = "-.-";
my_current_temp = -1.;
Enabled = enabled;
if (Enabled) {
registerMap = new RegisterMap(read_reg_map(ucp));
}
else {
registerMap = new RegisterMap();
}
// Add composite registers:
registerMap->add_register("fpga/system", 0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/name", 0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/stamps", 0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/note", 0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/firmware_version", 0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/hardware_version", 0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INT16);
registerMap->add_register("fpga/temp", 0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/status", 0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/enable_mask_RW", 0, 1, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_BOOLEAN);
registerMap->add_register("fpga/rbf", 0, 0, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/flash_init", 0, 0, 0xffffffff, 0, "WO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/flash_erase", 0, 0, 0xffffffff, 0, "WO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/flash_pages", 0, 0, 0xffffffff, 0, "WO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/flash_page", 0, 0, 0xffffffff, 0, "WO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/flash_prot", 0, 0, 0xffffffff, 0, "WO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/epcs_wait_busy", 0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
registerMap->add_register("fpga/epcs_mmdp_data", 0, 0, 0xffffffff, 0, "WO", "COMP", 0, REG_FORMAT_STRING);
uint32_t scrap_span = registerMap->getSpan("mm/0/RAM_SCRAP/data");
registerMap->add_register("fpga/scrap_R", 0, scrap_span, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INTEGER);
registerMap->add_register("fpga/scrap_RW", 0, scrap_span, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_INTEGER);
uint32_t weights_span = 187392/16;
registerMap->add_register("fpga/weights_R", 0, weights_span, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INT16);
registerMap->add_register("fpga/weights_RW", 0, weights_span, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_INT16);
registerMap->print_screen();
// Test FPGA by reading system info:
try {
TermOutput termout;
read_system_info(ucp, termout);
} catch (exception& e) {
cerr << "Test Periph_fpga::Periph_fpga:read_system_info(): " << e.what() << endl;
}
// rbf_wf.open ("/tmp/rbf.dat", ofstream::out | ofstream::binary );
// if (!rbf_wf) {
// cerr << "Cannot open file!" << endl;
// exit(-1);
// }
Flash_fact_sector_start = 0;
Flash_fact_sector_end = 159;
Flash_user_sector_start = 160;
Flash_user_sector_end = 319;
Flash_pages_per_sector = 1024;
Flash_page_size_bytes = 256;
Flash_page_start = Flash_user_sector_start * Flash_pages_per_sector;
Flash_select = 1; // default is user
#define FLASH_EPCS_REG_ADDR 0
#define FLASH_EPCS_REG_RDEN 1
#define FLASH_EPCS_REG_READ 2
#define FLASH_EPCS_REG_WRITE 3
#define FLASH_EPCS_REG_SECTOR_ERASE 4
#define FLASH_EPCS_REG_BUSY 5
#define FLASH_EPCS_REG_UNPROTECT 6
cout << "Periph_fpga::scrapram_size=" << scrap_span << endl;
Scrap_RW_copy.resize(scrap_span);
cout << "Periph_fpga::weights_size=" << weights_span << endl;
Weights_RW_copy.resize(weights_span);
}
Periph_fpga::~Periph_fpga()
{
// rbf_wf.close();
if (registerMap != NULL) delete registerMap;
}
bool Periph_fpga::Read(UCP *ucp, const string addr_str, uint32_t *data_ptr)
{
bool ret;
if (!Enabled) {
throw runtime_error("disabled "+addr_str);
}
uint32_t addr = registerMap->getAddr((addr_str));
registerMap->getReadPermission((addr_str));
uint32_t nvalues = registerMap->getSpan((addr_str));
uint32_t mask = registerMap->getMask((addr_str));
uint32_t shift = registerMap->getShift((addr_str));
bool isfifo = registerMap->type_isfifo((addr_str));
ret = ucp->readRegister(addr, nvalues, data_ptr, isfifo);
if (ret && (shift != 0 || mask != 0xffffffff)) {
for (uint32_t i=0; i<nvalues; i++) {
data_ptr[i] &= mask;
data_ptr[i] = data_ptr[i] >> shift;
}
}
return ret;
}
bool Periph_fpga::Write(UCP *ucp, const string addr_str, const uint32_t nvalues,
uint32_t *data_ptr)
{
if (!Enabled) {
throw runtime_error("disabled " + addr_str);
}
uint32_t addr = registerMap->getValidAddr((addr_str), nvalues);
registerMap->getWritePermission((addr_str));
uint32_t shift = registerMap->getShift((addr_str));
uint32_t mask = registerMap->getMask((addr_str));
bool isfifo = registerMap->type_isfifo((addr_str));
if (shift != 0 || mask != 0xffffffff) {
for (uint32_t i=0; i<nvalues; i++) {
data_ptr[i] = data_ptr[i] << shift;
data_ptr[i] &= mask;
}
}
return ucp->writeRegister(addr,nvalues,data_ptr,isfifo);
}
bool Periph_fpga::read_fpga_status(TermOutput& termout, int format)
{
termout.strout << "\"" << my_current_status << "\"";
if (my_current_status == "online") {
termout.val[0] = 1;
}
else {
termout.val[0] = 0;
}
termout.nof_vals = 1;
termout.datatype = format;
return true;
}
bool Periph_fpga::write_fpga_enable_mask(const char *data)
{
Enabled = (bool)*data;
return true;
}
bool Periph_fpga::read_fpga_enable_mask(TermOutput& termout, int format)
{
termout.strout << "\"" << Enabled << "\"";
termout.val[0] = Enabled;
termout.nof_vals = 1;
termout.datatype = format;
return true;
}
bool Periph_fpga::read_fpga_temp(TermOutput& termout)
{
termout.strout << "\"" << my_current_temp << "\"";
return true;
}
/*
"""Peripheral system_info
Register map:
31 24 23 16 15 8 7 0 wi
|-----------------|-----------------|-----------------|-----------------|
| use_phy[7:0] | 1
|-----------------------------------------------------------------------|
| system_info[31:0] | 0
|-----------------------------------------------------------------------|
system_info[23:20] = firmware version high[3:0]
system_info[19:16] = firmware version low[3:0]
system_info[10] = cs_sim (= g_sim, 0 on HW, 1 in VHDL simulation)
system_info[9:8] = hardware version [1:0] (= 0 for UniBoard 1A and 1B)
system_info[7:0] = node id[7;0]
*/
bool Periph_fpga::read_system_info(UCP *ucp, TermOutput& termout)
{
uint32_t data;
bool retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/info", &data);
string design_name = read_design_name(ucp);
termout.strout << design_name << ", ";
// FIXME: get rid of magic constants in masks, should be in CCFG:
uint firmware_version = (data & 0x00F00000) >> 20;
uint firmware_subversion = (data & 0x000F0000) >> 16;
termout.strout << firmware_version << "." << firmware_subversion;
my_current_fw_version = to_string(firmware_version) + "." + to_string(firmware_subversion);
my_current_hw_version = (data & 0x0000300) >> 8;
if (design_name == my_expected_design_name && firmware_version >= my_expected_firmware_version) {
my_current_status = "online";
retval = true;
}
else {
retval = false;
termout.strerr << "Unexpected design_name / firmware_version" << endl;
cerr << "Warning: Node configuration mismatch!! (read_design_name/version=" << design_name
<< "/" << firmware_version << "), expected=" << my_expected_design_name
<< "/" << my_expected_firmware_version << ")" << endl;
//syslog(LOG_WARNING,"Node configuration mismatch!! (read_design_name/version=%s/%d, expected=%s/%d)\n",
// design_name.c_str(), firmware_version,
// my_expected_design_name.c_str(), my_expected_firmware_version);
my_current_status = "offline";
registerMap->setAllPermission_NA();
}
return retval;
}
bool Periph_fpga::read(UCP *ucp, TermOutput& termout, const string addr,
const string type, char *data, const uint nvalues,
const int format)
{
bool retval = false;
termout.datatype = format;
if (type == "mm") {
uint32_t *data_ptr = (uint32_t *)data;
retval = Read(ucp, addr, data_ptr);
if (retval) {
for (uint i=0; i<nvalues; i++) {
if (i > 0) {
termout.strout << ",";
}
termout.strout << data_ptr[i];
}
}
termout.datatype = format;
}
else { // "fpga/..."
if (addr == "fpga/system") {
retval = read_system_info(ucp, termout);
}
else if (addr == "fpga/name") {
string str = read_design_name(ucp);
termout.strout << str;
termout.nof_vals = str.size();
termout.datatype = format;
strcpy(termout.val, str.c_str());
retval = true;
}
else if (addr == "fpga/stamps") {
retval = read_stamps(ucp, termout, format);
termout.datatype = format;
}
else if (addr == "fpga/note") {
termout.strout << read_design_note(ucp);
termout.datatype = format;
retval = true;
}
else if (addr == "fpga/firmware_version") {
retval = read_firmware_version(ucp, termout, format);
}
else if (addr == "fpga/hardware_version") {
retval = read_hardware_version(ucp, termout, format);
}
else if (addr == "fpga/temp") {
retval = read_fpga_temperature(ucp, termout, format);
}
else if (addr == "fpga/epcs_wait_busy") {
retval = wait_while_epcs_busy(ucp, 1000);
}
else if (addr == "fpga/status") {
retval = read_fpga_status(termout, format);
}
else if (addr == "fpga/enable_mask_RW") {
retval = read_fpga_enable_mask(termout, format);
}
else if (addr == "fpga/scrap_RW") {
retval = read_fpga_scrap_RW(termout, format);
}
else if (addr == "fpga/scrap_R") {
retval = read_fpga_scrap_R(ucp, termout, format);
}
else if (addr == "fpga/weights_RW") {
retval = read_fpga_weights_RW(termout, format);
}
else if (addr == "fpga/weights_R") {
retval = read_fpga_weights_R(ucp, termout, format);
}
else {
throw runtime_error("address " + addr + " not found!");
}
}
//cout << "Periph_fpga::read, addr=" << addr << ", datatype=" << format << "/" << termout.datatype << endl;
return retval;
}
bool Periph_fpga::write(UCP *ucp, const string addr, const string type,
char *data, const uint nvalues, const int format)
{
bool retval = false;
uint32_t *data_ptr = (uint32_t *)data;
if (type == "mm") {
retval = Write(ucp, addr, nvalues, data_ptr);
}
else { // "fpga/..."
// if (addr == "fpga/rbf") {
// char *data_ptr=(char *)data;
// cout << "writing: " << len*sizeof(uint32_t) << " bytes" << endl;
// rbf_wf.write(data_ptr, len*sizeof(uint32_t));
// retval = true;
// } else
if (addr == "fpga/flash_init") {
Flash_select = data_ptr[0];
if (Flash_select == 0) { // factory
Flash_page_start = Flash_fact_sector_start * Flash_pages_per_sector;
}
else { // user
Flash_page_start = Flash_user_sector_start * Flash_pages_per_sector;
}
}
else if (addr == "fpga/flash_erase") {
flash_erase(ucp);
}
else if (addr == "fpga/flash_pages") {
retval = flash_pages(ucp, data_ptr, nvalues);
}
else if (addr == "fpga/flash_page") {
retval = flash_page(ucp, data_ptr, nvalues);
}
else if (addr == "fpga/flash_prot") {
retval = flash_prot(ucp, data_ptr);
}
else if (addr == "fpga/epcs_mmdp_data") {
// write to FIFO
retval = Write(ucp, "mm/0/REG_MMDP_DATA/data", nvalues, data_ptr);
}
else if (addr == "fpga/enable_mask_RW") {
retval = write_fpga_enable_mask(data);
}
else if (addr == "fpga/scrap_RW") {
retval = write_fpga_scrap_RW(ucp, data_ptr, nvalues);
}
else if (addr == "fpga/weights_RW") {
retval = write_fpga_weights_RW(ucp, data_ptr, nvalues);
}
else {
throw runtime_error("address " + addr + " not found!");
}
}
return retval;
}
bool Periph_fpga::flash_prot(UCP *ucp, uint32_t *data)
{
bool retval = false;
uint32_t passphrase_protect = 0;
uint32_t passphrase_unprotect = 0xBEDA221E;
if (*data == 0) { // unprotect
retval = Write(ucp, "mm/0/REG_EPCS/unprotect", 1, &passphrase_unprotect);
}
else { // protect
retval = Write(ucp, "mm/0/REG_EPCS/unprotect", 1, &passphrase_protect);
}
return retval;
}
bool Periph_fpga::flash_page(UCP *ucp, uint32_t *data, const uint len)
{
bool retval = false;
wait_while_epcs_busy(ucp, 1);
// write address
uint32_t addr = Flash_page_start * Flash_page_size_bytes;
retval = Write(ucp, "mm/0/REG_EPCS/addr", 1, &addr);
// write to FIFO
retval = Write(ucp, "mm/0/REG_MMDP_DATA/data", len, data);
// write_write
uint32_t d = 1;
retval = Write(ucp, "mm/0/REG_EPCS/write", 1, &d);
return retval;
}
bool Periph_fpga::flash_pages(UCP *ucp, uint32_t *data, const uint len)
{
bool retval = false;
uint page_size_words = Flash_page_size_bytes / sizeof(uint32_t);
uint nof_pages = ceil_div(len, page_size_words);
cout << "Periph_fpga::flash_pages nof_pages=" << nof_pages << endl;
for (uint p=0; p<nof_pages; p++) {
retval = flash_page(ucp, &data[(p*page_size_words)], page_size_words);
Flash_page_start++;
}
return retval;
}
bool Periph_fpga::wait_while_epcs_busy(UCP *ucp, uint sleeptime)
{
uint32_t data;
bool retval;
//cout << "wait_while_epcs_busy:";
for (int i=0; i<100; i++) {
retval = Read(ucp, "mm/0/REG_EPCS/busy", &data);
if (!retval) break;
if (data == 0) break;
usleep(sleeptime);
//cout << "." << flush;
}
//cout << endl;
if (data != 0) {
retval = false; // still busy
}
return retval;
}
bool Periph_fpga::flash_erase_sector(UCP *ucp, uint32_t sector)
{
// We need to write any address in the target sector's address range to select that sector for erase.
// We'll use the base (lowest) address of the sectors for this: sector 0 starts at 0x0, sector 1 starts
// at 0x40000 etc.
bool retval = false;
uint32_t s,d;
vector<uint32_t> s_list = {0,0x10000,0x20000,0x30000};
cout << "erase flash sector: " << sector << endl;
for (uint i=0; i<s_list.size(); i++) {
s = sector * 0x40000 + s_list[i];
// write address
retval = Write(ucp, "mm/0/REG_EPCS/addr", 1, &s);
// sector erase
d = 1;
retval = Write(ucp, "mm/0/REG_EPCS/sector_erase", 1, &d);
wait_while_epcs_busy(ucp, 50000);
}
return retval;
}
bool Periph_fpga::flash_erase(UCP *ucp)
{
bool retval = false;
uint32_t start, end;
cout << "erase flash for bank: " << Flash_select << endl;
if (Flash_select == 0) { // factory
start = Flash_fact_sector_start;
end = Flash_fact_sector_end + 1;
}
else { // user
start = Flash_user_sector_start;
end = Flash_user_sector_end + 1;
}
for (uint32_t s=start; s<end; s++) {
retval = flash_erase_sector(ucp, s);
}
return retval;
}
string Periph_fpga::read_design_name(UCP *ucp)
{
uint32_t data[20];
memset((void *)data, 0, sizeof(data));
bool retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/design_name", data);
char *str_ptr = (char *)data;
string name = string(str_ptr);
//if (data != NULL) delete[] data;
return (retval ? name : "? (error)");
}
string Periph_fpga::read_design_note(UCP *ucp)
{
uint32_t data[20];
memset((void *)data, 0, sizeof(data));
bool retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/design_note", data);
char *str_ptr = (char *)data;
string note = string(str_ptr);
//if (data != NULL) delete[] data;
return (retval ? note : "? (error)");
}
bool Periph_fpga::read_hardware_version(UCP *ucp, TermOutput& termout, int format)
{
bool retval = true;
uint32_t data[20];
uint hw_version_nr;
string hw_version;
memset((void *)data, 0, sizeof(data));
retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/info_hw_version", data);
hw_version_nr = data[0];
if (hw_version_nr == 1) {
hw_version = "UniBoard2b";
}
else if (hw_version_nr == 2) {
hw_version = "UniBoard2c";
}
else {
hw_version = "Unknown";
}
termout.nof_vals = hw_version.size();
termout.datatype = format;
strcpy(termout.val, hw_version.c_str());
termout.strout << "hardware_version= " << hw_version << endl;
return retval;
}
bool Periph_fpga::read_firmware_version(UCP *ucp, TermOutput& termout, int format)
{
bool retval = true;
uint32_t data[20];
termout.datatype = format;
memset((void *)data, 0, sizeof(data));
retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/design_name", data);
if (retval == false) {
return retval;
}
char *str_ptr = (char *)data;
string design_name = string(str_ptr);
memset((void *)data, 0, sizeof(data));
retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/stamp_date", data);
if (retval == false) {
return retval;
}
string date = to_string(data[0]);
memset((void *)data, 0, sizeof(data));
retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/stamp_time", data);
if (retval == false) {
return retval;
}
string time = to_string(data[0]);
memset((void *)data, 0, sizeof(data));
retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/stamp_commit", data);
if (retval == false) {
return retval;
}
string revision = to_string(data[0]);
string firmware_version;
firmware_version = date.substr(0, 2) + "-" + date.substr(2, 2) + "-" + date.substr(4, 2);
firmware_version += "T";
firmware_version += time.substr(0, 2) + "." + time.substr(2, 2) + "." + time.substr(4, 2);
firmware_version += "_";
firmware_version += revision + "_" + design_name;
termout.nof_vals = firmware_version.size();
termout.datatype = format;
strcpy(termout.val, firmware_version.c_str());
termout.strout << "firmware_version= " << firmware_version << endl;
return retval;
}
bool Periph_fpga::read_stamps(UCP *ucp, TermOutput& termout, int format)
{
uint32_t data[20];
memset((void *)data, 0, sizeof(data));
bool retval = Read(ucp, "mm/0/PIO_SYSTEM_INFO/stamp_date", data);
termout.strout << "date=" << data[0] << " time=" << data[1] << " git=" << data[2] << endl;
termout.datatype = format;
return retval;
}
bool Periph_fpga::read_fpga_temperature(UCP *ucp, TermOutput& termout, int format)
{
bool retval = true;
uint32_t data[20];
memset((void *)data, 0, sizeof(data));
retval = Read(ucp, "mm/0/REG_FPGA_TEMP_SENS/temp", data);
// ADC to engineering
// see the constants: https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_alttemp_sense.pdf
// page 10
float temp = ((693. * (float)data[0]) / 1024.) - 265;
termout.strout << temp;
float *temp_ptr = (float *)termout.val;
*temp_ptr = temp;
termout.nof_vals = 1;
termout.datatype = format;
my_current_temp = temp;
return retval;
}
bool Periph_fpga::read_fpga_scrap_R(UCP *ucp, TermOutput& termout, int format)
{
bool retval = true;
uint32_t nvalues = registerMap->getSpan("mm/0/RAM_SCRAP/data");
uint32_t *ptr = (uint32_t *)termout.val;
retval = Read(ucp, "mm/0/RAM_SCRAP/data", ptr);
for (uint i=0; i<nvalues; i++) {
if (i > 0) {
termout.strout << ",";
}
termout.strout << ptr[i];
}
termout.nof_vals = nvalues;
termout.datatype = format;
return retval;
}
bool Periph_fpga::write_fpga_scrap_RW(UCP *ucp, uint32_t *data, uint nvalues)
{
cout << "Periph_fpga::write_fpga_scrap " << nvalues << " values" << endl;
uint32_t nvalues_chk = registerMap->getSpan("mm/0/RAM_SCRAP/data");
if (nvalues > nvalues_chk) {
nvalues = nvalues_chk;
}
for (uint i=0; i<nvalues; i++) {
Scrap_RW_copy[i] = data[i];
cout << data[i] << " ";
}
cout << endl;
bool retval = Write(ucp, "mm/0/RAM_SCRAP/data", nvalues, data);
return retval;
}
bool Periph_fpga::read_fpga_scrap_RW(TermOutput& termout, int format)
{
bool retval = true;
uint32_t *ptr = (uint32_t *)termout.val;
for (uint i=0; i<Scrap_RW_copy.size(); i++) {
ptr[i] = Scrap_RW_copy[i];
if (i>0) {
termout.strout << ",";
}
termout.strout << ptr[i];
}
termout.nof_vals = Scrap_RW_copy.size();
termout.datatype = format;
return retval;
}
bool Periph_fpga::read_fpga_weights_R(UCP *ucp, TermOutput& termout, int format)
{
bool retval = true;
uint32_t nvalues_scrap = registerMap->getSpan("mm/0/RAM_SCRAP/data");
uint nblocks = 48; // 11712/244=48
uint32_t *data_scrap = new uint32_t[nvalues_scrap];
short *ptr = (short *)termout.val;
for (uint i=0; i<nblocks; i++) {
retval = Read(ucp, "mm/0/RAM_SCRAP/data", data_scrap);
for (uint j=0; j<nvalues_scrap; j+=2) {
uint32_t ds = data_scrap[j];
*ptr++ = (short)(ds & 0xffff);
*ptr++ = (short)(ds >> 16);
}
}
termout.nof_vals = registerMap->getSpan("fpga/weights_R");
termout.datatype = format;
delete[] data_scrap;
return retval;
}
bool Periph_fpga::write_fpga_weights_RW(UCP *ucp, const uint32_t *data, uint nvalues)
{
bool retval = false;
uint32_t nvalues_scrap = registerMap->getSpan("mm/0/RAM_SCRAP/data");
uint32_t nvalues_weights = registerMap->getSpan("fpga/weights_R");
uint nblocks = 48; // 11712/244=48
if (nvalues > nvalues_weights) {
nvalues = nvalues_weights;
}
uint32_t *data_scrap = new uint32_t[nvalues_scrap];
for (uint i=0; i<nvalues; i++) {
Weights_RW_copy[i] = (short)data[i];
}
const uint32_t *ptr = data;
uint si=0;
for (uint i=0; i<nblocks; i++) {
for (uint j=0; j<nvalues_scrap; j++) {
uint32_t ds;
if (si >= nvalues) {
break;
}
ds = *ptr++; si++;
if (si >= nvalues) {
break;
}
ds |= ((*ptr++) << 16);
si++;
data_scrap[j] = ds;
}
retval = Write(ucp, "mm/0/RAM_SCRAP/data", nvalues_scrap, data_scrap);
}
delete[] data_scrap;
return retval;
}
bool Periph_fpga::read_fpga_weights_RW(TermOutput& termout, int format)
{
bool retval = true;
short *ptr = (short *)termout.val;
for (uint i=0; i<Weights_RW_copy.size(); i++) {
ptr[i] = Weights_RW_copy[i];
}
termout.nof_vals = Weights_RW_copy.size();
termout.datatype = format;
return retval;
}
bool Periph_fpga::write_wdi_override(UCP *ucp, TermOutput& termout)
{
uint32_t data = 0xB007FAC7;
return Write(ucp, "mm/0/PIO_WDI/wdi_override", 1, &data);
}
RegisterMap Periph_fpga::read_reg_map(UCP *ucp)
{
RegisterMap reg;
uint32_t nvalues = REG_ADDR_ROM_SYSTEM_SPAN;
uint32_t addr = REG_ADDR_ROM_SYSTEM;
uint32_t *data = new uint32_t[nvalues * sizeof(uint32_t)];
if (data == NULL) {
cerr << "malloc error" << endl;
}
memset((void *)data, 0, nvalues * sizeof(uint32_t));
if (!ucp->readRegister(addr, nvalues, data)) {
if (data != NULL) {
delete[] data;
}
cerr << "ucp.readRegister failed" << endl;
return reg;
}
for (uint i=0; i<nvalues; i++) {
/*
cout << "data[" << dec << i << "]=0x" << hex << setw(8) << setfill('0') << data[i] << " ";
for (int j=0;j<4;j++) {
char c = (char)(data[i]>>(8*j)) ;
if (c=='\0') printf("\\0"); else cout << c;
}
cout << endl;
*/
data[i] = ntohl(data[i]);
}
char *str_ptr = (char *)data;
string reg_map_str(str_ptr);
cout << "Periph_fpga::read_reg_map:\n" << reg_map_str << endl;
if (data != NULL) {
delete[] data;
}
istringstream iss_regmap(reg_map_str);
return mmap_to_regmap(iss_regmap);
}