program fpga made parallel

This commit is contained in:
2019-03-29 17:59:06 +01:00
parent ed9dc3b386
commit 969551ae37
6 changed files with 242 additions and 247 deletions

View File

@ -1,9 +1,9 @@
Path: slsDetectorPackage/slsDetectorServers/jungfrauDetectorServer Path: slsDetectorPackage/slsDetectorServers/jungfrauDetectorServer
URL: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git URL: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git
Repository Root: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git Repository Root: origin git@github.com:slsdetectorgroup/slsDetectorPackage.git
Repsitory UUID: 5a4122ae7c8dae1572e9db336de70183956e58c7 Repsitory UUID: ed9dc3b386898603d74a489528292139d47aac1a
Revision: 31 Revision: 32
Branch: refactor Branch: program
Last Changed Author: Dhanya_Thattil Last Changed Author: Erik_Frojdh
Last Changed Rev: 4481 Last Changed Rev: 4488
Last Changed Date: 2019-03-28 08:18:03.000000002 +0100 ../slsDetectorServer/slsDetectorFunctionList.h Last Changed Date: 2019-03-29 14:42:42.000000002 +0100 ../slsDetectorServer/slsDetectorServer_funcs.c

View File

@ -1,6 +1,6 @@
#define GITURL "git@github.com:slsdetectorgroup/slsDetectorPackage.git" #define GITURL "git@github.com:slsdetectorgroup/slsDetectorPackage.git"
#define GITREPUUID "5a4122ae7c8dae1572e9db336de70183956e58c7" #define GITREPUUID "ed9dc3b386898603d74a489528292139d47aac1a"
#define GITAUTH "Dhanya_Thattil" #define GITAUTH "Erik_Frojdh"
#define GITREV 0x4481 #define GITREV 0x4488
#define GITDATE 0x20190328 #define GITDATE 0x20190329
#define GITBRANCH "refactor" #define GITBRANCH "program"

View File

@ -1,12 +1,5 @@
#ifndef MULTI_SLS_DETECTOR_H #pragma once
#define MULTI_SLS_DETECTOR_H
/**
@libdoc The multiSlsDetector class is used to operate several slsDetectors in
parallel.
* @short This is the base class for multi detector system functionalities
* @author Anna Bergamaschi
*/
#include "SharedMemory.h" #include "SharedMemory.h"
#include "error_defs.h" #include "error_defs.h"
#include "gitInfoLib.h" #include "gitInfoLib.h"
@ -2002,11 +1995,6 @@ class multiSlsDetector : public virtual slsDetectorDefs {
*/ */
void startProcessingThread(); void startProcessingThread();
// /**
// * Static function to call processing thread
// */
// static void* startProcessData(void *n);
/** /**
* Check if processing thread is ready to join main thread * Check if processing thread is ready to join main thread
* @returns true if ready, else false * @returns true if ready, else false
@ -2025,6 +2013,15 @@ class multiSlsDetector : public virtual slsDetectorDefs {
*/ */
int kbhit(); int kbhit();
/**
* Convert raw file
* @param fname name of pof file
* @param fpgasrc pointer in memory to read pof to
* @returns file size
*/
std::vector<char> readPofFile(const std::string &fname);
/** Multi detector Id */ /** Multi detector Id */
const int multiId; const int multiId;
@ -2083,4 +2080,3 @@ class multiSlsDetector : public virtual slsDetectorDefs {
void *pCallbackArg{nullptr}; void *pCallbackArg{nullptr};
}; };
#endif

View File

@ -1,13 +1,4 @@
#ifndef SLS_DETECTOR_H #pragma once
#define SLS_DETECTOR_H
/**
*
* @short complete detector functionalities for a single module detector.
* The slsDetector class takes care of the communication with the
* detector and all kind actions related with a single detector controller
* @author Anna Bergamaschi
*/
#include "ClientSocket.h" #include "ClientSocket.h"
#include "SharedMemory.h" #include "SharedMemory.h"
@ -17,6 +8,7 @@
class ClientInterface; class ClientInterface;
#include <cmath> #include <cmath>
#include <vector>
class multiSlsDetector; class multiSlsDetector;
class ServerInterface; class ServerInterface;
@ -1286,11 +1278,11 @@ class slsDetector : public virtual slsDetectorDefs{
int setStoragecellStart(int pos = -1); int setStoragecellStart(int pos = -1);
/** /**
* Programs FPGA with pof file (Jungfrau) * Programs FPGA with pof file (Jungfrau, CTB, Moench)
* @param fname file name * @param buffer programming file in memory
* @returns OK or FAIL * @returns OK or FAIL
*/ */
int programFPGA(const std::string &fname); int programFPGA(std::vector<char> buffer);
/** /**
* Resets FPGA (Jungfrau) * Resets FPGA (Jungfrau)
@ -1826,4 +1818,3 @@ class slsDetector : public virtual slsDetectorDefs{
}; };
#endif

View File

@ -2597,13 +2597,16 @@ int multiSlsDetector::setStoragecellStart(int pos, int detPos) {
} }
int multiSlsDetector::programFPGA(const std::string &fname, int detPos) { int multiSlsDetector::programFPGA(const std::string &fname, int detPos) {
// read pof file
std::vector<char> buffer = readPofFile(fname);
// single // single
if (detPos >= 0) { if (detPos >= 0) {
return detectors[detPos]->programFPGA(fname); return detectors[detPos]->programFPGA(buffer);
} }
// multi // multi
auto r = serialCall(&slsDetector::programFPGA, fname); auto r = parallelCall(&slsDetector::programFPGA, buffer);
return sls::allEqualTo(r, static_cast<int>(OK)) ? OK : FAIL; return sls::allEqualTo(r, static_cast<int>(OK)) ? OK : FAIL;
} }
@ -3986,10 +3989,6 @@ void multiSlsDetector::startProcessingThread() {
dataProcessingThread = std::thread(&multiSlsDetector::processData, this); dataProcessingThread = std::thread(&multiSlsDetector::processData, this);
} }
// void* multiSlsDetector::startProcessData(void *n) {
// ((multiSlsDetector*)n)->processData();
// return n;
// }
void multiSlsDetector::processData() { void multiSlsDetector::processData() {
if (setReceiverOnline() == OFFLINE_FLAG) { if (setReceiverOnline() == OFFLINE_FLAG) {
@ -4050,3 +4049,107 @@ int multiSlsDetector::kbhit() {
select(STDIN_FILENO + 1, &fds, nullptr, nullptr, &tv); select(STDIN_FILENO + 1, &fds, nullptr, nullptr, &tv);
return FD_ISSET(STDIN_FILENO, &fds); return FD_ISSET(STDIN_FILENO, &fds);
} }
std::vector<char> multiSlsDetector::readPofFile(const std::string &fname) {
FILE_LOG(logDEBUG1) << "Programming FPGA with file name:" << fname;
size_t filesize = 0;
// check if it exists
struct stat st;
if (stat(fname.c_str(), &st)) {
throw RuntimeError("Program FPGA: Programming file does not exist");
}
// open src
FILE *src = fopen(fname.c_str(), "rb");
if (src == nullptr) {
throw RuntimeError("Program FPGA: Could not open source file for programming: " +
fname);
}
// create temp destination file
char destfname[] = "/tmp/SLS_DET_MCB.XXXXXX";
int dst = mkstemp(destfname); // create temporary file and open it in r/w
if (dst == -1) {
fclose(src);
throw RuntimeError(
std::string("Could not create destination file in /tmp for programming: ") +
destfname);
}
// convert src to dst rawbin
FILE_LOG(logDEBUG1) << "Converting " << fname << " to " << destfname;
{
int filepos, x, y, i;
// Remove header (0...11C)
for (filepos = 0; filepos < 0x11C; ++filepos) {
fgetc(src);
}
// Write 0x80 times 0xFF (0...7F)
{
char c = 0xFF;
for (filepos = 0; filepos < 0x80; ++filepos) {
write(dst, &c, 1);
}
}
// Swap bits and write to file
for (filepos = 0x80; filepos < 0x1000000; ++filepos) {
x = fgetc(src);
if (x < 0) {
break;
}
y = 0;
for (i = 0; i < 8; ++i) {
y = y | (((x & (1 << i)) >> i) << (7 - i)); // This swaps the bits
}
write(dst, &y, 1);
}
if (filepos < 0x1000000) {
throw RuntimeError("Could not convert programming file. EOF before end of flash");
}
}
if (fclose(src)) {
throw RuntimeError("Program FPGA: Could not close source file");
}
if (close(dst)) {
throw RuntimeError("Program FPGA: Could not close destination file");
}
FILE_LOG(logDEBUG1) << "File has been converted to " << destfname;
// loading dst file to memory
FILE *fp = fopen(destfname, "r");
if (fp == nullptr) {
throw RuntimeError("Program FPGA: Could not open rawbin file");
}
if (fseek(fp, 0, SEEK_END)) {
throw RuntimeError("Program FPGA: Seek error in rawbin file");
}
filesize = ftell(fp);
if (filesize <= 0) {
throw RuntimeError("Program FPGA: Could not get length of rawbin file");
}
rewind(fp);
std::vector<char> buffer(filesize, 0);
if (fread(buffer.data(), sizeof(char), filesize, fp) != filesize) {
throw RuntimeError("Program FPGA: Could not read rawbin file");
}
if (fclose(fp)) {
throw RuntimeError("Program FPGA: Could not close destination file after converting");
}
unlink(destfname); // delete temporary file
FILE_LOG(logDEBUG1) << "Successfully loaded the rawbin file to program memory";
FILE_LOG(logINFO) << "Read file into memory";
return buffer;
}

View File

@ -3386,221 +3386,126 @@ int slsDetector::setStoragecellStart(int pos) {
return retval; return retval;
} }
int slsDetector::programFPGA(const std::string &fname) { int slsDetector::programFPGA(std::vector<char> buffer) {
// TODO! make exception safe! // validate type
// now malloced memory can leak switch(detector_shm()->myDetectorType) {
// only jungfrau implemented (client processing, so check now) case JUNGFRAU:
if (detector_shm()->myDetectorType != JUNGFRAU && case CHIPTESTBOARD:
detector_shm()->myDetectorType != CHIPTESTBOARD && case MOENCH:
detector_shm()->myDetectorType != MOENCH) { break;
throw RuntimeError("Program FPGA is not implemented for this detector"); default:
} throw RuntimeError("Program FPGA is not implemented for this detector");
FILE_LOG(logDEBUG1) << "Programming FPGA with file name:" << fname; }
size_t filesize = 0;
char *fpgasrc = nullptr;
// check if it exists size_t filesize = buffer.size();
{
struct stat st;
if (stat(fname.c_str(), &st)) {
throw RuntimeError("Program FPGA: Programming file does not exist");
}
}
{ // send program from memory to detector
// open src int fnum = F_PROGRAM_FPGA;
FILE *src = fopen(fname.c_str(), "rb"); int ret = FAIL;
if (src == nullptr) { char mess[MAX_STR_LENGTH] = {0};
throw RuntimeError("Program FPGA: Could not open source file for programming: " + FILE_LOG(logINFO) << "Sending programming binary to detector " << detector_shm()->hostname;
fname);
}
// create temp destination file if (detector_shm()->onlineFlag == ONLINE_FLAG) {
char destfname[] = "/tmp/SLS_DET_MCB.XXXXXX"; auto client = DetectorSocket(detector_shm()->hostname, detector_shm()->controlPort);
int dst = mkstemp(destfname); // create temporary file and open it in r/w client.sendData(&fnum, sizeof(fnum));
if (dst == -1) { client.sendData(&filesize, sizeof(filesize));
fclose(src); client.receiveData(&ret, sizeof(ret));
throw RuntimeError( // opening error
std::string("Could not create destination file in /tmp for programming: ") + if (ret == FAIL) {
destfname); client.receiveData(mess, sizeof(mess));
} throw RuntimeError("Detector " + std::to_string(detId) +
" returned error: " + std::string(mess));
}
// convert src to dst rawbin // erasing flash
FILE_LOG(logDEBUG1) << "Converting " << fname << " to " << destfname; if (ret != FAIL) {
{ FILE_LOG(logINFO) << "This can take awhile. Please be patient...";
int filepos, x, y, i; FILE_LOG(logINFO) << detId << "Erasing Flash:";
// Remove header (0...11C) printf("%d%%\r", 0);
for (filepos = 0; filepos < 0x11C; ++filepos) { std::cout << std::flush;
fgetc(src); // erasing takes 65 seconds, printing here (otherwise need threads
} // in server-unnecessary)
// Write 0x80 times 0xFF (0...7F) const int ERASE_TIME = 65;
{ int count = ERASE_TIME + 1;
char c = 0xFF; while (count > 0) {
for (filepos = 0; filepos < 0x80; ++filepos) { usleep(1 * 1000 * 1000);
write(dst, &c, 1); --count;
} printf("%d%%\r", (int)(((double)(ERASE_TIME - count) / ERASE_TIME) * 100));
} std::cout << std::flush;
// Swap bits and write to file }
for (filepos = 0x80; filepos < 0x1000000; ++filepos) { printf("\n");
x = fgetc(src); FILE_LOG(logINFO) << detId << "Writing to Flash:";
if (x < 0) { printf("%d%%\r", 0);
break; std::cout << std::flush;
} }
y = 0;
for (i = 0; i < 8; ++i) {
y = y | (((x & (1 << i)) >> i) << (7 - i)); // This swaps the bits
}
write(dst, &y, 1);
}
if (filepos < 0x1000000) {
throw RuntimeError("Could not convert programming file. EOF before end of flash");
}
}
if (fclose(src)) {
throw RuntimeError("Program FPGA: Could not close source file");
}
if (close(dst)) {
throw RuntimeError("Program FPGA: Could not close destination file");
}
FILE_LOG(logDEBUG1) << "File has been converted to " << destfname;
// loading dst file to memory // sending program in parts of 2mb each
FILE *fp = fopen(destfname, "r"); size_t unitprogramsize = 0;
if (fp == nullptr) { int currentPointer = 0;
throw RuntimeError("Program FPGA: Could not open rawbin file"); size_t totalsize = filesize;
} while (ret != FAIL && (filesize > 0)) {
if (fseek(fp, 0, SEEK_END)) {
throw RuntimeError("Program FPGA: Seek error in rawbin file");
}
filesize = ftell(fp);
if (filesize <= 0) {
throw RuntimeError("Program FPGA: Could not get length of rawbin file");
}
rewind(fp);
fpgasrc = (char *)malloc(filesize + 1); //<------------------- MALLOC!
if (fpgasrc == nullptr) {
throw RuntimeError("Program FPGA: Could not allocate size of program");
}
if (fread(fpgasrc, sizeof(char), filesize, fp) != filesize) {
free(fpgasrc);
throw RuntimeError("Program FPGA: Could not read rawbin file");
}
if (fclose(fp)) { unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb
free(fpgasrc); if (unitprogramsize > filesize) { // less than 2mb
throw RuntimeError("Program FPGA: Could not close destination file after converting"); unitprogramsize = filesize;
} }
unlink(destfname); // delete temporary file FILE_LOG(logDEBUG1) << "unitprogramsize:" << unitprogramsize
FILE_LOG(logDEBUG1) << "Successfully loaded the rawbin file to program memory"; << "\t filesize:" << filesize;
}
// send program from memory to detector client.sendData(&buffer[currentPointer], unitprogramsize);
int fnum = F_PROGRAM_FPGA; client.receiveData(&ret, sizeof(ret));
int ret = FAIL; if (ret != FAIL) {
char mess[MAX_STR_LENGTH] = {0}; filesize -= unitprogramsize;
FILE_LOG(logDEBUG1) << "Sending programming binary to detector"; currentPointer += unitprogramsize;
if (detector_shm()->onlineFlag == ONLINE_FLAG) { // print progress
auto client = DetectorSocket(detector_shm()->hostname, detector_shm()->controlPort); printf("%d%%\r", (int)(((double)(totalsize - filesize) / totalsize) * 100));
client.sendData(&fnum, sizeof(fnum)); std::cout << std::flush;
client.sendData(&filesize, sizeof(filesize)); } else {
client.receiveData(&ret, sizeof(ret)); printf("\n");
// opening error client.receiveData(mess, sizeof(mess));
if (ret == FAIL) { throw RuntimeError("Detector " + std::to_string(detId) +
client.receiveData(mess, sizeof(mess)); " returned error: " + std::string(mess));
free(fpgasrc); }
throw RuntimeError("Detector " + std::to_string(detId) + }
" returned error: " + std::string(mess)); printf("\n");
}
// erasing flash // check ending error
if (ret != FAIL) { if ((ret == FAIL) && (strstr(mess, "not implemented") == nullptr) &&
FILE_LOG(logINFO) << "This can take awhile. Please be patient..."; (strstr(mess, "locked") == nullptr) && (strstr(mess, "-update") == nullptr)) {
FILE_LOG(logINFO) << "Erasing Flash:"; client.receiveData(&ret, sizeof(ret));
printf("%d%%\r", 0); if (ret == FAIL) {
std::cout << std::flush; client.receiveData(mess, sizeof(mess));
// erasing takes 65 seconds, printing here (otherwise need threads throw RuntimeError("Detector " + std::to_string(detId) +
// in server-unnecessary) " returned error: " + std::string(mess));
const int ERASE_TIME = 65; }
int count = ERASE_TIME + 1; }
while (count > 0) {
usleep(1 * 1000 * 1000);
--count;
printf("%d%%\r", (int)(((double)(ERASE_TIME - count) / ERASE_TIME) * 100));
std::cout << std::flush;
}
printf("\n");
FILE_LOG(logINFO) << "Writing to Flash:";
printf("%d%%\r", 0);
std::cout << std::flush;
}
// sending program in parts of 2mb each if (ret == FORCE_UPDATE) {
size_t unitprogramsize = 0; updateDetector();
int currentPointer = 0; }
size_t totalsize = filesize;
while (ret != FAIL && (filesize > 0)) {
unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb // remapping stop server
if (unitprogramsize > filesize) { // less than 2mb if ((ret == FAIL) && (strstr(mess, "not implemented") == nullptr) &&
unitprogramsize = filesize; (strstr(mess, "locked") == nullptr) && (strstr(mess, "-update") == nullptr)) {
} fnum = F_RESET_FPGA;
FILE_LOG(logDEBUG1) << "unitprogramsize:" << unitprogramsize int stopret = FAIL;
<< "\t filesize:" << filesize; auto stop = DetectorSocket(detector_shm()->hostname, detector_shm()->stopPort);
stop.sendData(&fnum, sizeof(fnum));
client.sendData(fpgasrc + currentPointer, unitprogramsize); stop.receiveData(&stopret, sizeof(stopret));
client.receiveData(&ret, sizeof(ret)); if (stopret == FAIL) {
if (ret != FAIL) { client.receiveData(mess, sizeof(mess));
filesize -= unitprogramsize; throw RuntimeError("Detector " + std::to_string(detId) +
currentPointer += unitprogramsize; " returned error: " + std::string(mess));
}
// print progress }
printf("%d%%\r", (int)(((double)(totalsize - filesize) / totalsize) * 100)); }
std::cout << std::flush; FILE_LOG(logINFO) << "You can now restart the detector " + std::to_string(detId) +
} else { " in normal mode.";
printf("\n"); return ret;
client.receiveData(mess, sizeof(mess));
free(fpgasrc);
throw RuntimeError("Detector returned error: " + std::string(mess));
}
}
printf("\n");
// check ending error
if ((ret == FAIL) && (strstr(mess, "not implemented") == nullptr) &&
(strstr(mess, "locked") == nullptr) && (strstr(mess, "-update") == nullptr)) {
client.receiveData(&ret, sizeof(ret));
if (ret == FAIL) {
client.receiveData(mess, sizeof(mess));
free(fpgasrc);
throw RuntimeError("Detector returned error: " + std::string(mess));
}
}
if (ret == FORCE_UPDATE) {
updateDetector();
}
// remapping stop server
if ((ret == FAIL) && (strstr(mess, "not implemented") == nullptr) &&
(strstr(mess, "locked") == nullptr) && (strstr(mess, "-update") == nullptr)) {
fnum = F_RESET_FPGA;
int stopret = FAIL;
auto stop = DetectorSocket(detector_shm()->hostname, detector_shm()->stopPort);
stop.sendData(&fnum, sizeof(fnum));
stop.receiveData(&stopret, sizeof(stopret));
if (stopret == FAIL) {
client.receiveData(mess, sizeof(mess));
free(fpgasrc);
throw RuntimeError("Detector returned error: " + std::string(mess));
}
}
}
FILE_LOG(logINFO) << "You can now restart the detector servers in normal mode.";
free(fpgasrc);
return ret;
} }
int slsDetector::resetFPGA() { int slsDetector::resetFPGA() {
int fnum = F_RESET_FPGA; int fnum = F_RESET_FPGA;
int ret = FAIL; int ret = FAIL;