Commit 38252563 authored by Alejandro Homs Puron's avatar Alejandro Homs Puron Committed by operator for beamline
Browse files

Move geometry calculation code to Eiger::Geometry

* Add test_expand_4 program; update test infrastructure
parent 1cee9710
......@@ -209,5 +209,5 @@ endif()
## Tests
if(CAMERA_ENABLE_TESTS)
enable_testing()
#add_subdirectory(test)
add_subdirectory(test)
endif()
......@@ -36,6 +36,8 @@ namespace SlsDetector
#define EIGER_PACKET_DATA_LEN (4 * 1024)
#define MaxEigerNbPorts MaxFrameMapItemGroupSize
class Eiger : public Model
{
DEB_CLASS_NAMESPC(DebModCamera, "Eiger", "SlsDetector");
......@@ -53,7 +55,7 @@ class Eiger : public Model
class Correction : public LinkTask
{
DEB_CLASS_NAMESPC(DebModCamera, "Eiger::Correction",
DEB_CLASS_NAMESPC(DebModCamera, "Eiger::Correction",
"SlsDetector");
public:
Correction(Eiger *eiger);
......@@ -63,6 +65,139 @@ class Eiger : public Model
Eiger *m_eiger;
};
class Geometry
{
DEB_CLASS_NAMESPC(DebModCamera, "Eiger::Geometry",
"SlsDetector");
public:
typedef FrameMap::Mask Mask;
class Recv
{
DEB_CLASS_NAMESPC(DebModCamera, "Eiger::Geometry::Recv",
"SlsDetector");
public:
class Port;
struct Expand4Data {
char *src[MaxEigerNbPorts];
char *dst;
int len4;
Mask valid;
};
class Port
{
DEB_CLASS_NAMESPC(DebModCamera,
"Eiger::Geometry::Recv::Port",
"SlsDetector");
public:
Port(Recv *recv, int port);
void prepareAcq();
FrameDim getSrcFrameDim();
void copy(char *dst, char *src);
private:
friend class Recv;
struct CalcData {
int cw; // chip width
int lw; // line width
int po; // port offset
int to; // thread offset
};
Recv *m_recv;
int m_recv_idx;
int m_port;
bool m_top_half_recv;
bool m_port_idx;
bool m_raw;
bool m_pixel_depth_4;
CalcData m_src;
CalcData m_dst;
int m_pchips;
int m_copy_lines;
};
typedef std::vector<AutoPtr<Port> > PortList;
Recv(Geometry *eiger_geom, int idx);
int getNbPorts();
Port *getPort(int idx);
void setThreadProcessing(bool thread_proc)
{ m_thread_proc = thread_proc; }
void setNbProcessingThreads(int nb_proc_threads)
{ m_nb_proc_threads = nb_proc_threads; }
void prepareAcq();
void expandPixelDepth4(Expand4Data& data,
int thread_idx);
private:
friend class Port;
friend class Geometry;
Geometry *m_eiger_geom;
int m_idx;
PortList m_port_list;
int m_nb_proc_threads;
bool m_thread_proc;
};
typedef std::vector<AutoPtr<Recv> > RecvList;
Geometry();
void setNbRecvs(int nb_recv);
int getNbRecvs()
{ return m_recv_list.size(); }
Recv *getRecv(int idx)
{ return m_recv_list[idx]; }
int getNbEigerModules()
{ return getNbRecvs() / 2; }
void setRaw(bool raw)
{ m_raw = raw; }
bool getRaw()
{ return m_raw; }
void setImageType(ImageType image_type)
{ m_image_type = image_type; }
ImageType getImageType()
{ return m_image_type; }
void setPixelDepth(PixelDepth pixel_depth)
{ m_pixel_depth = pixel_depth; }
PixelDepth getPixelDepth()
{ return m_pixel_depth; }
bool isPixelDepth4()
{ return (m_pixel_depth == PixelDepth4); }
FrameDim getFrameDim(bool raw);
FrameDim getRecvFrameDim(bool raw);
int getInterModuleGap(int det);
void prepareAcq();
private:
friend class Recv;
friend class Recv::Port;
friend class Eiger;
bool m_raw;
ImageType m_image_type;
PixelDepth m_pixel_depth;
FrameDim m_recv_frame_dim;
RecvList m_recv_list;
};
Eiger(Camera *cam);
~Eiger();
......@@ -123,8 +258,6 @@ class Eiger : public Model
friend class Correction;
friend class CorrBase;
typedef FrameMap::Mask Mask;
class Recv : public Model::Recv
{
DEB_CLASS_NAMESPC(DebModCamera, "Eiger::Recv", "SlsDetector");
......@@ -143,26 +276,9 @@ class Eiger : public Model
private:
friend class Recv;
void copy2LimaBuffer(char *dst, char *src,
int thread_idx);
Recv *m_recv;
int m_recv_idx;
int m_port;
bool m_top_half_recv;
bool m_port_idx;
bool m_raw;
bool m_pixel_depth_4;
int m_slw; // source line width
int m_dlw; // dest line width
int m_scw; // source chip width
int m_dcw; // dest chip width
int m_pchips;
int m_copy_lines;
int m_spo; // source port offset
int m_dpo; // dest port offset
int m_sto; // source thread offset
int m_dto; // dest thread offset
Geometry::Recv::Port *m_geom;
int m_nb_buffers;
NumaSoftBufferAllocMgr m_buffer_alloc_mgr;
StdBufferCbMgr m_buffer_cb_mgr;
......@@ -182,18 +298,10 @@ class Eiger : public Model
char *bptr, int thread_idx);
private:
struct ExpandData {
int nb_ports;
char *src[MaxFrameMapItemGroupSize];
char *dst;
int len4;
Mask valid;
};
void expandPixelDepth4(ExpandData& data, int thread_idx);
Eiger *m_eiger;
int m_idx;
int m_nb_threads;
Geometry::Recv *m_geom;
int m_nb_proc_threads;
bool m_thread_proc;
volatile FrameType m_last_recv_frame;
volatile FrameType m_last_proc_frame;
......@@ -374,17 +482,11 @@ class Eiger : public Model
std::vector<BorderFactor> m_f;
};
bool isPixelDepth4()
{
PixelDepth pixel_depth;
getCamera()->getPixelDepth(pixel_depth);
return (pixel_depth == PixelDepth4);
}
int getNbEigerModules()
{ return getNbDetModules() / 2; }
{ return m_geom.getNbEigerModules(); }
void getRecvFrameDim(FrameDim& frame_dim, bool raw, bool geom);
const FrameDim& getRecvFrameDim()
{ return m_geom.m_recv_frame_dim; }
CorrBase *createBadRecvFrameCorr();
CorrBase *createChipBorderCorr(ImageType image_type);
......@@ -395,7 +497,8 @@ class Eiger : public Model
void removeAllCorr();
double getBorderCorrFactor(int det, int line);
int getInterModuleGap(int det);
int getInterModuleGap(int det)
{ return m_geom.getInterModuleGap(det); }
static const int ChipSize;
static const int ChipGap;
......@@ -418,7 +521,7 @@ class Eiger : public Model
static const LinScale ChipXfer2Buff;
static const LinScale ChipRealReadout;
FrameDim m_recv_frame_dim;
Geometry m_geom;
CorrList m_corr_list;
RecvList m_recv_list;
bool m_fixed_clock_div;
......
......@@ -1104,7 +1104,7 @@ int Camera::getNbBadFrames(int recv_idx)
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(recv_idx);
if ((recv_idx < -1) || (recv_idx >= m_recv_list.size()))
if ((recv_idx < -1) || (recv_idx >= int(m_recv_list.size())))
THROW_HW_ERROR(InvalidValue) << DEB_VAR1(recv_idx);
int nb_bad_frames;
if (recv_idx == -1) {
......
......@@ -63,7 +63,7 @@ void Eiger::CorrBase::prepareAcq()
if (!m_eiger)
THROW_HW_ERROR(InvalidValue) << "Correction already removed";
FrameDim& recv_dim = m_eiger->m_recv_frame_dim;
const FrameDim& recv_dim = m_eiger->getRecvFrameDim();
m_mod_frame_dim = recv_dim * Point(1, 2);
m_frame_size = m_mod_frame_dim.getSize() * Point(1, m_nb_eiger_modules);
m_inter_lines.resize(m_nb_eiger_modules);
......@@ -202,142 +202,114 @@ Data Eiger::Correction::process(Data& data)
return ret;
}
Eiger::Recv::Port::Port(Recv *recv, int port)
: m_recv(recv), m_recv_idx(m_recv->m_idx), m_port(port),
m_nb_buffers(1024), m_buffer_cb_mgr(m_buffer_alloc_mgr)
Eiger::Geometry::Recv::Port::Port(Recv *recv, int port)
: m_recv(recv), m_recv_idx(m_recv->m_idx), m_port(port)
{
DEB_CONSTRUCTOR();
DEB_PARAM() << DEB_VAR2(m_recv_idx, m_port);
m_top_half_recv = (m_recv_idx % 2 == 0);
}
void Eiger::Recv::Port::prepareAcq()
void Eiger::Geometry::Recv::Port::prepareAcq()
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR1(m_recv_idx);
Eiger *eiger = m_recv->m_eiger;
Geometry *geom = m_recv->m_eiger_geom;
m_pixel_depth_4 = eiger->isPixelDepth4();
eiger->getCamera()->getRawMode(m_raw);
m_pixel_depth_4 = (geom->m_pixel_depth == PixelDepth4);
m_raw = geom->m_raw;
const FrameDim& frame_dim = eiger->m_recv_frame_dim;
const FrameDim& frame_dim = geom->m_recv_frame_dim;
const Size& size = frame_dim.getSize();
int depth = frame_dim.getDepth();
m_dlw = size.getWidth() * depth;
m_dst.lw = size.getWidth() * depth;
int recv_size = frame_dim.getMemSize();
m_spo = 0;
m_dpo = recv_size * m_recv_idx;
m_src.po = 0;
m_dst.po = recv_size * m_recv_idx;
m_pchips = HalfModuleChips / NbRecvPorts;
m_scw = ChipSize * depth;
m_dcw = m_scw;
m_src.cw = ChipSize * depth;
m_dst.cw = m_src.cw;
if (m_pixel_depth_4)
m_scw /= 2;
m_slw = m_pchips * m_scw;
m_src.cw /= 2;
m_src.lw = m_pchips * m_src.cw;
m_copy_lines = ChipSize;
if (m_recv->m_thread_proc) {
Camera *cam = eiger->getCamera();
PixelDepthCPUAffinityMap aff_map;
cam->getPixelDepthCPUAffinityMap(aff_map);
PixelDepth pixel_depth;
cam->getPixelDepth(pixel_depth);
const RecvCPUAffinity& r = aff_map[pixel_depth].recv[m_recv_idx];
CPUAffinity buffer_aff = r.writers[m_port];
m_buffer_alloc_mgr.setCPUAffinityMask(buffer_aff);
int nb_concat_frames = 8;
int nb_buffers = m_nb_buffers / nb_concat_frames;
FrameDim fdim(m_slw, ChipSize, Bpp8);
m_buffer_cb_mgr.allocBuffers(nb_buffers, nb_concat_frames, fdim);
if (m_recv->m_nb_proc_threads > 1) {
if (m_raw)
m_copy_lines *= NbRecvPorts;
m_copy_lines /= m_recv->m_nb_threads;
m_sto = m_copy_lines * m_slw;
m_dto = m_copy_lines * m_dlw;
DEB_ALWAYS() << DEB_VAR3(m_copy_lines, m_sto, m_dto);
} else {
m_buffer_cb_mgr.releaseBuffers();
m_copy_lines /= m_recv->m_nb_proc_threads;
m_src.to = m_copy_lines * m_src.lw;
m_dst.to = m_copy_lines * m_dst.lw;
DEB_TRACE() << DEB_VAR3(m_copy_lines, m_src.to, m_dst.to);
}
if (m_raw) {
// vert. port concat.
m_dpo += ChipSize * m_dlw * m_port;
m_dst.po += ChipSize * m_dst.lw * m_port;
return;
} else {
// inter-chip horz. gap
m_dcw += ChipGap * depth;
m_dst.cw += ChipGap * depth;
// horz. port concat.
m_dpo += m_pchips * m_dcw * m_port;
m_dst.po += m_pchips * m_dst.cw * m_port;
}
int mod_idx = m_recv_idx / 2;
for (int i = 0; i < mod_idx; ++i)
m_dpo += eiger->getInterModuleGap(i) * m_dlw;
m_dst.po += geom->getInterModuleGap(i) * m_dst.lw;
if (m_top_half_recv) {
// top-half module: vert-flipped data
m_spo += (ChipSize - 1) * m_slw;
m_slw *= -1;
m_sto *= -1;
m_src.po += (ChipSize - 1) * m_src.lw;
m_src.lw *= -1;
m_src.to *= -1;
} else {
// bottom-half module: inter-chip vert. gap
m_dpo += (ChipGap / 2) * m_dlw;
m_dst.po += (ChipGap / 2) * m_dst.lw;
}
}
void Eiger::Recv::Port::processFrame(FrameType frame, char *dptr,
uint32_t dsize, char *bptr)
FrameDim Eiger::Geometry::Recv::Port::getSrcFrameDim()
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR3(frame, m_recv_idx, m_port);
bool valid_data = (dptr != NULL);
if (!m_recv->m_thread_proc || !valid_data) {
copy2LimaBuffer(bptr, dptr, 0);
return;
}
FrameType last_proc_frame = m_recv->m_last_proc_frame;
if (frame - last_proc_frame > m_nb_buffers) {
if (!m_recv->m_overrun) {
DEB_ERROR() << "OVERRUN: "
<< DEB_VAR5(last_proc_frame, frame,
m_recv_idx, m_port,
m_nb_buffers);
m_recv->m_overrun = true;
}
}
char *dest = (char *) m_buffer_cb_mgr.getFrameBufferPtr(frame);
const FrameDim& fdim = m_buffer_cb_mgr.getFrameDim();
int size = fdim.getMemSize();
memcpy(dest, dptr, size);
// This is not perfect, but should more or less work
m_recv->m_last_recv_frame = frame;
FrameDim fdim(abs(m_src.lw), ChipSize, Bpp8);
DEB_RETURN() << DEB_VAR1(fdim);
return fdim;
}
void Eiger::Recv::Port::copy2LimaBuffer(char *dst, char *src, int thread_idx)
void Eiger::Geometry::Recv::Port::copy(char *dst, char *src)
{
DEB_MEMBER_FUNCT();
bool valid_data = (src != NULL);
src += m_spo + thread_idx * m_sto;
dst += m_dpo + thread_idx * m_dto;
for (int i = 0; i < m_copy_lines; ++i, src += m_slw, dst += m_dlw) {
src += m_src.po;
dst += m_dst.po;
const int& lines = m_copy_lines;
if (m_raw) {
int size = m_src.lw * lines;
if (valid_data)
memcpy(dst, src, size);
else
memset(dst, 0xff, size);
return;
}
for (int i = 0; i < lines; ++i, src += m_src.lw, dst += m_dst.lw) {
char *s = src;
char *d = dst;
for (int j = 0; j < m_pchips; ++j, s += m_scw, d += m_dcw)
for (int j = 0; j < m_pchips; ++j, s += m_src.cw, d += m_dst.cw)
if (valid_data)
memcpy(d, s, m_scw);
memcpy(d, s, m_src.cw);
else
memset(d, 0xff, m_scw);
memset(d, 0xff, m_src.cw);
}
}
Eiger::Recv::Recv(Eiger *eiger, int idx)
: m_eiger(eiger), m_idx(idx), m_nb_threads(2)
Eiger::Geometry::Recv::Recv(Geometry *eiger_geom, int idx)
: m_eiger_geom(eiger_geom), m_idx(idx), m_nb_proc_threads(1)
{
DEB_CONSTRUCTOR();
DEB_PARAM() << DEB_VAR1(m_idx);
......@@ -348,109 +320,63 @@ Eiger::Recv::Recv(Eiger *eiger, int idx)
}
}
int Eiger::Recv::getNbPorts()
int Eiger::Geometry::Recv::getNbPorts()
{
DEB_MEMBER_FUNCT();
DEB_RETURN() << DEB_VAR1(NbRecvPorts);
return NbRecvPorts;
}
Eiger::Recv::Port *Eiger::Recv::getPort(int port_idx)
Eiger::Geometry::Recv::Port *Eiger::Geometry::Recv::getPort(int port_idx)
{
DEB_MEMBER_FUNCT();
return m_port_list[port_idx];
}
void Eiger::Recv::prepareAcq()
void Eiger::Geometry::Recv::prepareAcq()
{
DEB_MEMBER_FUNCT();
m_thread_proc = (m_eiger->isPixelDepth4() &&
m_eiger->m_expand_4_in_threads);
m_last_recv_frame = m_last_proc_frame = -1;
m_overrun = false;
PortList::iterator it, end = m_port_list.end();
for (it = m_port_list.begin(); it != end; ++it)
(*it)->prepareAcq();
}
void Eiger::Recv::processFileStart(uint32_t dsize)
void Eiger::Geometry::Recv::expandPixelDepth4(Expand4Data& data, int thread_idx)
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR2(m_idx, dsize);
}
int Eiger::Recv::getNbProcessingThreads()
{
DEB_MEMBER_FUNCT();
int nb_proc_threads = m_nb_threads;
DEB_RETURN() << DEB_VAR1(nb_proc_threads);
return nb_proc_threads;
}
DEB_PARAM() << DEB_VAR4(DEB_HEX((unsigned long) data.src[0]),
DEB_HEX((unsigned long) data.src[1]),
DEB_HEX((unsigned long) data.dst), data.len4);
void Eiger::Recv::processThread(const FrameData& frame_data, char *bptr,
int thread_idx)
{
DEB_MEMBER_FUNCT();
DEB_PARAM() << DEB_VAR3(frame_data.frame, m_idx, thread_idx);
if (!m_thread_proc)
return;
ExpandData data;
data.nb_ports = NbRecvPorts;
data.dst = bptr;
data.len4 = 0;
data.valid = frame_data.valid;
char **dptr = data.src;
FrameType frame = frame_data.frame;
PortList::iterator it, end = m_port_list.end();
for (it = m_port_list.begin(); it != end; ++it, ++dptr) {
StdBufferCbMgr& m = (*it)->m_buffer_cb_mgr;
if (data.len4 == 0) {
const FrameDim& fdim = m.getFrameDim();
data.len4 = (fdim.getMemSize() * NbRecvPorts /
m_nb_threads);
}
*dptr = (char *) m.getFrameBufferPtr(frame);
}
expandPixelDepth4(data, thread_idx);
// Again, should more or less work
m_last_proc_frame = frame;
}
void Eiger::Recv::expandPixelDepth4(ExpandData& data, int thread_idx)
{
DEB_MEMBER_FUNCT();
int nb_ports = data.nb_ports;
int nb_ports = getNbPorts();
Port *port = m_port_list[0];
int first_port = 0;
int sto = port->m_sto * thread_idx;
int sto = port->m_src.to * thread_idx;
bool raw = port->m_raw;
if (raw) {
const int port_size = port->m_slw * ChipSize;
const int port_size = port->m_src.lw * ChipSize;
first_port = sto / port_size;
sto %= port_size;
}
int pi;
for (pi = first_port; pi < nb_ports; ++pi) {
data.src[pi] += port->m_spo + sto;
data.src[pi] += port->m_src.po + sto;
unsigned long s = (unsigned long) data.src[pi];
if ((s & 15) != 0)
THROW_HW_ERROR(Error) << "Missaligned src: "
<< DEB_VAR1(DEB_HEX(s));
}
data.dst += port->m_dpo + port->m_dto * thread_idx;
data.dst += port->m_dst.po + port->m_dst.to * thread_idx;
unsigned long d = (unsigned long) data.dst;
int dest_misalign = (d & 15);
if (raw && dest_misalign)
THROW_HW_ERROR(Error) << "Missaligned dest: "
<< DEB_VAR1(DEB_HEX(d));
DEB_TRACE() << DEB_VAR4(thread_idx, first_port, sto, dest_misalign);
DEB_TRACE() << DEB_VAR4(DEB_HEX((unsigned long) data.src[0]),
DEB_HEX((unsigned long) data.src[1]),
DEB_HEX((unsigned long) data.dst), data.len4);
pi = first_port;
bool valid_data = data.valid.test(pi);
const int block_len = sizeof(__m128i);
......@@ -470,7 +396,7 @@ void Eiger::Recv::expandPixelDepth4(ExpandData& data, int thread_idx)
__m128i shift_l128, shift_r128;
__m128i m64_0 = _mm_set_epi64x(0, -1);
__m128i m64_1 = _mm_set_epi64x(-1, 0);
bool reverse = (port->m_slw < 0);
bool reverse = (port->m_src.lw < 0);
__m128i m0, prev;
int chip_count = 0;
......@@ -582,59 +508,272 @@ void Eiger::Recv::expandPixelDepth4(ExpandData& data, int thread_idx)
sync_dst128();