ATLAS Offline Software
Loading...
Searching...
No Matches
CpmSubBlockV1.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6#include "CpmSubBlockV1.h"
7
8namespace LVL1BS {
9
10// Constant definitions
11
13
15
29
33
42
43
48
52
53// Clear all data
54
56{
58 m_ttData.clear();
59 m_hitData.clear();
60 m_chanPresent.assign(m_channels, 0);
61}
62
63// Store CPM header
64
65void CpmSubBlockV1::setCpmHeader(const int version, const int format,
66 const int slice, const int crate,
67 const int module, const int timeslices)
68{
70}
71
72// Store trigger tower data
73
74void CpmSubBlockV1::fillTowerData(const int slice, const int channel,
75 const int em, const int had,
76 const int emErr, const int hadErr)
77{
78 if (channel < m_channels && (em || emErr || had || hadErr)) {
80 int dat = em;
81 int err = emErr;
82 for (int pinOffset = 0; pinOffset < 2; ++pinOffset) {
83 if (dat || err) {
84 const int pin = 2 * (channel/s_wordsPerPin) + pinOffset;
85 const int pair = (channel % s_wordsPerPin) / 2;
86 const int pos = pin * s_pairsPerPin + pair;
87 const int ix = index(slice) * m_channels + pos;
88 uint32_t word = m_ttData[ix];
89 if (channel % 2 == 0) {
90 word |= (dat & s_ttDataMask) << s_ttDataABit;
91 word |= (err & 0x1) << s_parityABit;
92 word |= ((err >> 1) & 0x1) << s_linkDownABit;
93 } else {
94 word |= (dat & s_ttDataMask) << s_ttDataBBit;
95 word |= (err & 0x1) << s_parityBBit;
96 word |= ((err >> 1) & 0x1) << s_linkDownBBit;
97 }
98 word |= pair << s_pairBit;
99 word |= pin << s_fpgaBit;
100 word |= s_ttWordId << s_dataIdBit;
101 m_ttData[ix] = word;
102 }
103 dat = had;
104 err = hadErr;
105 }
106 m_chanPresent[channel] = 1;
107 }
108}
109
110// Store hit counts
111
112void CpmSubBlockV1::setHits(const int slice, const unsigned int hit0,
113 const unsigned int hit1)
114{
115 if (hit0 || hit1) {
116 resize(m_hitData, 2);
117 const int ix = index(slice)*2;
118 unsigned int hits = hit0;
119 for (int indicator = 0; indicator < 2; ++indicator) {
120 if (hits) {
121 uint32_t word = (hits & s_threshMask);
122 word |= indicator << s_indicatorBit;
123 word |= s_threshWordId << s_dataIdBit;
124 m_hitData[ix + indicator] = word;
125 }
126 hits = hit1;
127 }
128 }
129}
130
131// Return Em data for given channel
132
133int CpmSubBlockV1::emData(const int slice, const int channel) const
134{
135 return data(slice, channel, 0);
136}
137
138// Return Had data for given channel
139
140int CpmSubBlockV1::hadData(const int slice, const int channel) const
141{
142 return data(slice, channel, 1);
143}
144
145// Return Em error for given channel
146
147int CpmSubBlockV1::emError(const int slice, const int channel) const
148{
149 return error(slice, channel, 0);
150}
151
152// Return Had error for given channel
153
154int CpmSubBlockV1::hadError(const int slice, const int channel) const
155{
156 return error(slice, channel, 1);
157}
158
159// Return first hit counts word
160
161unsigned int CpmSubBlockV1::hits0(const int slice) const
162{
163 return hits(slice, 0);
164}
165
166// Return second hit counts word
167
168unsigned int CpmSubBlockV1::hits1(const int slice) const
169{
170 return hits(slice, 1);
171}
172
173// Return number of timeslices
174
176{
177 int slices = slices1();
178 if (slices == 0 && format() == NEUTRAL) {
179 slices = dataWords() / s_glinkBitsPerSlice;
180 }
181 if (slices == 0) slices = 1;
182 return slices;
183}
184
185// Packing/Unpacking routines
186
188{
189 bool rc = false;
190 switch (version()) {
191 case 1:
192 switch (format()) {
193 case NEUTRAL:
194 rc = packNeutral();
195 break;
196 case UNCOMPRESSED:
198 break;
199 default:
200 break;
201 }
202 break;
203 default:
204 break;
205 }
206 return rc;
207}
208
210{
211 bool rc = false;
212 switch (version()) {
213 case 1:
214 switch (format()) {
215 case NEUTRAL:
216 rc = unpackNeutral();
217 break;
218 case UNCOMPRESSED:
220 break;
221 default:
223 break;
224 }
225 break;
226 default:
228 break;
229 }
230 return rc;
231}
232
233// Return data for given channel and pin offset
234
235int CpmSubBlockV1::data(const int slice, const int channel,
236 const int offset) const
237{
238 int dat = 0;
239 if (slice >= 0 && slice < timeslices() &&
240 channel >= 0 && channel < m_channels && !m_ttData.empty()) {
241 const int pin = 2 * (channel/s_wordsPerPin) + offset;
242 const int pair = (channel % s_wordsPerPin) / 2;
243 const int pos = pin * s_pairsPerPin + pair;
244 const int ix = index(slice) * m_channels + pos;
245 const uint32_t word = m_ttData[ix];
246 if (channel % 2 == 0) {
247 dat = (word >> s_ttDataABit) & s_ttDataMask;
248 } else dat = (word >> s_ttDataBBit) & s_ttDataMask;
249 }
250 return dat;
251}
252
253// Return error for given channel and pin offset
254
255int CpmSubBlockV1::error(const int slice, const int channel,
256 const int offset) const
257{
258 int err = 0;
259 if (slice >= 0 && slice < timeslices() &&
260 channel >= 0 && channel < m_channels && !m_ttData.empty()) {
261 const int pin = 2 * (channel/s_wordsPerPin) + offset;
262 const int pair = (channel % s_wordsPerPin) / 2;
263 const int pos = pin * s_pairsPerPin + pair;
264 const int ix = index(slice) * m_channels + pos;
265 const uint32_t word = m_ttData[ix];
266 if (channel % 2 == 0) {
267 err = (word >> s_parityABit) & 0x1;
268 err |= ((word >> s_linkDownABit) & 0x1) << 1;
269 } else {
270 err = (word >> s_parityBBit) & 0x1;
271 err |= ((word >> s_linkDownBBit) & 0x1) << 1;
272 }
273 }
274 return err;
275}
276
277// Return hit counts with given offset
278
279unsigned int CpmSubBlockV1::hits(const int slice, const int offset) const
280{
281 unsigned int hit = 0;
282 if (slice >= 0 && slice < timeslices() && !m_hitData.empty()) {
283 hit = m_hitData[index(slice)*2 + offset] & s_threshMask;
284 }
285 return hit;
286}
287
288// Return data index appropriate to format
289
290int CpmSubBlockV1::index(const int slice) const
291{
292 return (format() == NEUTRAL) ? slice : 0;
293}
294
295// Resize a data vector according to format
296
297void CpmSubBlockV1::resize(std::vector<uint32_t>& vec, int channels)
298{
299 if (vec.empty()) {
300 int size = channels;
301 if (format() == NEUTRAL) size *= timeslices();
302 vec.resize(size);
303 }
304}
305
306// Pack neutral data
307
309{
311 resize(m_hitData, 2);
312 const int slices = timeslices();
313 for (int slice = 0; slice < slices; ++slice) {
314 const unsigned int hit0 = hits0(slice);
315 const unsigned int hit1 = hits1(slice);
316 for (int pin = 0; pin < s_glinkPins; ++pin) {
317 // Trigger tower data
318 for (int pair = 0; pair < s_pairsPerPin; ++pair) {
319 for (int i = 0; i < 2; ++i) {
320 const int channel = s_wordsPerPin*(pin/2) + 2*pair + i;
321 if ((pin & 0x1)) { // Odd pins Had, even Em
322 packerNeutral(pin, hadData(slice, channel), s_ttBits);
323 packerNeutral(pin, hadError(slice, channel), s_errBits);
324 } else {
325 packerNeutral(pin, emData(slice, channel), s_ttBits);
326 packerNeutral(pin, emError(slice, channel), s_errBits);
327 }
328 }
329 }
330 // Hits and Bunch Crossing number
331 if (pin < s_hitWords) {
332 packerNeutral(pin, hit0 >> pin*s_hitBits, s_hitBits);
333 } else if (pin < 2*s_hitWords) {
334 packerNeutral(pin, hit1 >> (pin - s_hitWords)*s_hitBits, s_hitBits);
335 } else {
337 s_hitBits);
338 }
339 // G-Link parity
341 }
342 }
343 return true;
344}
345
346// Pack uncompressed data
347
349{
350 // Trigger tower data
351 std::vector<uint32_t>::const_iterator pos;
352 for (pos = m_ttData.begin(); pos != m_ttData.end(); ++pos) {
353 if (*pos) packer(*pos, s_wordLength);
354 }
355
356 // Hits data
357 for (pos = m_hitData.begin(); pos != m_hitData.end(); ++pos) {
358 if (*pos) packer(*pos, s_wordLength);
359 }
360 packerFlush();
361 return true;
362}
363
364// Unpack neutral data
365
367{
369 resize(m_hitData, 2);
370 const int slices = timeslices();
371 for (int slice = 0; slice < slices; ++slice) {
372 unsigned int hit0 = 0;
373 unsigned int hit1 = 0;
374 int bunchCrossing = 0;
375 for (int pin = 0; pin < s_glinkPins; ++pin) {
376 // Trigger tower data
377 for (int pair = 0; pair < s_pairsPerPin; ++pair) {
378 for (int i = 0; i < 2; ++i) {
379 const int channel = s_wordsPerPin*(pin/2) + 2*pair + i;
380 int em = 0;
381 int had = 0;
382 int emErr = 0;
383 int hadErr = 0;
384 if ((pin & 0x1)) { // Odd pins Had, even Em
385 em = emData(slice, channel);
386 had = unpackerNeutral(pin, s_ttBits);
387 emErr = emError(slice, channel);
388 hadErr = unpackerNeutral(pin, s_errBits);
389 } else {
390 em = unpackerNeutral(pin, s_ttBits);
391 had = hadData(slice, channel);
392 emErr = unpackerNeutral(pin, s_errBits);
393 hadErr = hadError(slice, channel);
394 }
395 fillTowerData(slice, channel, em, had, emErr, hadErr);
396 }
397 }
398 // Hits and Bunch Crossing number
399 if (pin < s_hitWords) {
400 hit0 |= unpackerNeutral(pin, s_hitBits) << pin*s_hitBits;
401 } else if (pin < 2*s_hitWords) {
402 hit1 |= unpackerNeutral(pin, s_hitBits) << (pin - s_hitWords)*s_hitBits;
403 } else {
405 << (pin - 2*s_hitWords)*s_hitBits;
406 }
407 // G-Link parity error
409 }
410 setHits(slice, hit0, hit1);
412 }
413 const bool rc = unpackerSuccess();
415 return rc;
416}
417
418// Unpack uncompressed data
419
421{
423 resize(m_hitData, 2);
424 unpackerInit();
425 uint32_t word = unpacker(s_wordLength);
426 while (unpackerSuccess()) {
427 const int id = dataId(word);
428 bool err = false;
429 // Trigger tower data
430 if (id == s_ttWordId) {
431 const int ix = (word >> s_pairBit) & s_pairPinMask;
432 if (ix < m_channels && m_ttData[ix] == 0) {
433 m_ttData[ix] = word;
434 const int pin = ix/4;
435 const int pair = ix%4;
436 const int channel = s_wordsPerPin*(pin/2) + 2*pair;
437 m_chanPresent[channel] = 1;
438 m_chanPresent[channel+1] = 1;
439 } else err = true;
440 // Hits
441 } else {
442 const int indicator = (word >> s_indicatorBit) & 0x1;
443 if (m_hitData[indicator] == 0) m_hitData[indicator] = word;
444 else err = true;
445 }
446 if (err) {
448 return false;
449 }
450 word = unpacker(s_wordLength);
451 }
452 return true;
453}
454
455} // end namespace
std::vector< size_t > vec
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t rc
static const int s_parityBBit
static const int s_linkDownBBit
unsigned int hits0(int slice) const
Return e/gamma hit counts.
bool packUncompressed()
Pack uncompressed data.
void setHits(int slice, unsigned int hit0, unsigned int hit1)
Store hit counts.
static const int s_pairBit
unsigned int hits1(int slice) const
Return tau hit counts.
static const int s_glinkBitsPerSlice
int dataId(uint32_t word) const
Return data WordID.
unsigned int hits(int slice, int offset) const
Return hit counts with given offset.
bool pack()
Pack data.
static const int s_dataIdBit
int index(int slice) const
Return data index appropriate to format.
int emData(int slice, int channel) const
Return Em data for given channel.
static const int s_ttDataBBit
static const uint32_t s_threshWordId
static const int s_hitBits
static const int s_wordsPerPin
std::vector< uint32_t > m_hitData
Hit counts.
static const uint32_t s_threshMask
static const uint32_t s_pairPinMask
void clear()
Clear all data.
static const int s_ttWordId
static const int s_fpgaBit
static const uint32_t s_dataIdMask
int emError(int slice, int channel) const
Return Em error for given channel.
int data(int slice, int channel, int offset) const
Return data for given channel and pin offset.
void setCpmHeader(int version, int format, int slice, int crate, int module, int timeslices)
Store CPM header.
void resize(std::vector< uint32_t > &vec, int channels)
Resize a data vector according to format.
std::vector< uint32_t > m_ttData
Trigger tower data.
void fillTowerData(int slice, int channel, int em, int had, int emErr, int hadErr)
Store trigger tower data.
int hadError(int slice, int channel) const
Return Had error for given channel.
bool packNeutral()
Pack neutral data.
int timeslices() const
Return number of timeslices.
int error(int slice, int channel, int offset) const
Return error for given channel and pin offset.
static const int s_ttDataABit
static const int s_ttBits
static const int s_parityABit
bool unpack()
Unpack data.
static const uint32_t s_ttDataMask
int m_channels
Number of Trigger tower channels per module.
static const int s_pairsPerPin
static const int s_hitWords
bool unpackNeutral()
Unpack neutral data.
static const int s_errBits
static const int s_indicatorBit
int hadData(int slice, int channel) const
Return Had data for given channel.
std::vector< int > m_chanPresent
Channel present flags vector.
static const int s_linkDownABit
static const int s_wordLength
Data word length.
bool unpackUncompressed()
Unpack uncompressed data.
static const int s_wordIdVal
CPM header word ID.
static const int s_glinkPins
void packer(uint32_t datum, int nbits)
Pack given data into given number of bits.
uint32_t unpacker(int nbits)
Unpack given number of bits of data.
void setUnpackErrorCode(int code)
Set the unpacking error code.
bool unpackerSuccess() const
Return unpacker success flag.
void setHeader(int wordId, int version, int format, int seqno, int crate, int module, int slices2, int slices1)
Store header data.
bool unpackerNeutralParityError(int pin)
Unpack and test G-Link parity bit for given pin.
int dataWords() const
Return number of data words.
void clear()
Clear all data.
void packerNeutralParity(int pin)
Pack current G-Link parity bit for given pin.
void packerFlush()
Flush the current data word padded with zeros.
uint32_t unpackerNeutral(int pin, int nbits)
Unpack given number of bits of neutral data for given pin.
int bunchCrossing() const
Return the Bunch Crossing number (neutral format only)
void unpackerInit()
Initialise unpacker.
void packerNeutral(int pin, uint32_t datum, int nbits)
Pack given neutral data from given pin.
void setBunchCrossing(int bc)
Set the Bunch Crossing number (neutral format only)
STL class.
Definition index.py:1
setEventNumber uint32_t