Convert ROB fragments to trigger towers.
143{
147
148 const std::string
flag(
"Spare");
149 const std::string::size_type
pos = sgKey.find(flag);
150 bool spareChannels =
151 (
pos != std::string::npos &&
pos == (sgKey.length() -
flag.length()));
152 const std::string flag2("Muon");
153 const std::string::size_type pos2 = sgKey.find(flag2);
154 bool muonChannels =
155 (pos2 != std::string::npos && pos2 == (sgKey.length() - flag2.length()));
156 bool dataChannels = (!spareChannels && !muonChannels);
157
158
159
161 const int chanBitVecSize = maxChannels / 32;
162
164 std::lock_guard guard (
sd.m_mutex);
165
166 if (
sd.m_ttData.empty())
167 {
168 const int spareSize = maxChannels - 2 *
s_dataSize;
172 sd.m_ttSpare.reserve(spareSize);
173 sd.m_ttMuon.reserve(muonSize);
174 sd.m_ttPos.resize(maxChannels);
175 sd.m_chanLayer.resize(chanBitVecSize);
176 sd.m_dataChan.resize(chanBitVecSize);
177 sd.m_spareChan.resize(chanBitVecSize);
178 sd.m_muonChan.resize(chanBitVecSize);
179 sd.m_dataMod.resize(modBitVecSize);
180 sd.m_spareMod.resize(modBitVecSize);
181 sd.m_muonMod.resize(modBitVecSize);
183 TriggerTowerMap::iterator itt;
184 std::vector<int> dummyS;
185 std::vector<int> dummyL(1);
186 std::vector<int> dummyF(5);
187 int dataCount = 0;
188 int spareCount = 0;
189 for (
int crate = 0; crate <
s_crates; ++crate)
190 {
191 for (
int module = 0;
module < s_modules; ++
module)
192 {
193 const int index2 = (crate << 4) + module;
194 const int word2 =
index2 / 32;
195 const int bit2 =
index2 % 32;
197 {
198 const int index = (crate << 10) + (module << 6) +
channel;
199 const int word =
index / 32;
200 const int bit =
index % 32;
204 unsigned int key = 0;
206 {
207
209 itt = ttMap.find(key);
210 if (itt == ttMap.end())
211 {
212 LVL1::TriggerTower *
tt =
214 LVL1::TriggerTower(
phi,
eta, key,
215 dummyF, dummyL, dummyF, dummyL, 0, 0, 0,
216 dummyF, dummyL, dummyF, dummyL, 0, 0, 0);
217 sd.m_ttData.push_back(tt);
218 const int count = dataCount++;
220 ttMap.insert(std::make_pair(key,
count));
221 }
222 else
223 {
224 sd.m_ttPos[
index] = itt->second;
225 }
226 sd.m_chanLayer[word] |= (
layer << bit);
227 sd.m_dataChan[word] |= (1 << bit);
228 sd.m_dataMod[word2] |= (1 << bit2);
229 }
230 else
231 {
232
236 phi = 4 * pin + asic;
239 key = (crate << 24) | (type << 20) | (
module << 16) | (pin << 8) | asic;
240 LVL1::TriggerTower *
tt =
242 LVL1::TriggerTower(
phi,
eta, key,
243 dummyF, dummyL, dummyF, dummyL, 0, 0, 0,
244 dummyS, dummyS, dummyS, dummyS, 0, 0, 0);
245 sd.m_ttSpare.push_back(tt);
246 sd.m_ttPos[
index] = spareCount++;
247 sd.m_chanLayer[word] |= (
layer << bit);
248 sd.m_spareChan[word] |= (1 << bit);
249 sd.m_spareMod[word2] |= (1 << bit2);
250 if ((crate == 2 || crate == 3) && (module == 0))
251 {
252 sd.m_ttMuon.push_back(tt);
253 sd.m_muonChan[word] |= (1 << bit);
254 sd.m_muonMod[word2] |= (1 << bit2);
255 }
256 }
257 }
258 }
259 }
260 }
261
262
263
265 : spareChannels
271 : spareChannels
275 : spareChannels
278 const int colSize = dataChannels ? 2 * ttCol.size()
279 : ttCol.size();
280 sd.m_foundChan.assign(chanBitVecSize, 0);
281 int ttCount = 0;
282
283
284 std::vector<int>
lut;
285 std::vector<int> fadc;
286 std::vector<int> bcidLut;
287 std::vector<int> bcidFadc;
288
289
290
292
293 int robCount = 0;
294 std::set<uint32_t> dupCheck;
297 for (; rob != robEnd; ++rob)
298 {
299
301 {
302 ++robCount;
303 msg() <<
"Treating ROB fragment " << robCount <<
endmsg;
304 }
305
306
307
308 uint32_t robid = (*rob)->source_id();
309 if ((*rob)->nstatus() > 0)
310 {
312 (*rob)->status(robData);
313 if (*robData != 0)
314 {
316 if (
debug)
msg() <<
"ROB status error - skipping fragment" <<
endmsg;
317 continue;
318 }
319 }
320
321
322
323 if (!dupCheck.insert(robid).second)
324 {
327 continue;
328 }
329
330
331
335 (*rob)->rod_data(payloadBeg);
336 payloadEnd = payloadBeg + (*rob)->rod_ndata();
338 if (payload == payloadEnd)
339 {
341 continue;
342 }
343
344
345 const uint32_t sourceID = (*rob)->rod_source_id();
351 {
354 {
355 msg() <<
"Wrong source identifier in data: ROD "
356 << MSG::hex << sourceID << " ROB " << robid
358 }
359 continue;
360 }
361
362
363 const int minorVersion = (*rob)->rod_version() & 0xffff;
364 if (minorVersion >
m_srcIdMap.minorVersionPreLS1())
365 {
367 continue;
368 }
369 const int rodCrate =
m_srcIdMap.crate(sourceID);
371 {
372 msg() <<
"Treating crate " << rodCrate
374 }
375
376
378 {
381 continue;
382 }
383 L1CaloUserHeader userHeader(*payload);
384 userHeader.setVersion(minorVersion);
385 const int headerWords = userHeader.words();
386 if (headerWords != 1)
387 {
390 {
391 msg() <<
"Unexpected number of user header words: "
393 }
394 continue;
395 }
396 for (
int i = 0;
i < headerWords; ++
i) ++payload;
397
398 const int trigLut = userHeader.ppmLut();
399 const int trigFadc = userHeader.ppmFadc();
400
401 fadcBaseline = userHeader.lowerBound();
403 {
404 msg() <<
"Minor format version number: "
405 << MSG::hex << minorVersion << MSG::dec <<
endmsg
406 <<
"LUT triggered slice offset: " << trigLut <<
endmsg
407 <<
"FADC triggered slice offset: " << trigFadc <<
endmsg
408 <<
"FADC baseline lower bound: " << fadcBaseline <<
endmsg;
409 }
410 const int runNumber = (*rob)->rod_run_no() & 0xffffff;
411
412
413
414 int chanPerSubBlock = 0;
415 bool firstBlock = false;
418 if (payload != payloadEnd)
419 {
422 {
425 continue;
426 }
427 firstBlock = true;
429 if (
sd.m_ppmBlocks.empty())
430 {
431 sd.m_ppmBlocks.push_back(
new PpmSubBlockV1());
432 }
433 PpmSubBlockV1 *
const subBlock =
sd.m_ppmBlocks[0];
434 subBlock->clear();
435 payloadFirst = subBlock->read(payload, payloadEnd);
436 chanPerSubBlock = subBlock->channelsPerSubBlock();
437 if (chanPerSubBlock == 0)
438 {
439 m_errorTool->rodError(robid, subBlock->unpackErrorCode());
440 if (
debug)
msg() <<
"Unsupported version/data format: "
441 << subBlock->version() << "/"
442 << subBlock->format() <<
endmsg;
443 continue;
444 }
445 if (
debug)
msg() <<
"Channels per sub-block: "
446 << chanPerSubBlock <<
endmsg;
447 }
448 else
449 {
450 if (
debug)
msg() <<
"ROB fragment contains user header only" <<
endmsg;
451 continue;
452 }
453 const int numSubBlocks =
s_channels / chanPerSubBlock;
454 const int size =
sd.m_ppmBlocks.size();
455 if (numSubBlocks > size)
456 {
457 for (
int i = size;
i < numSubBlocks; ++
i)
458 {
459 sd.m_ppmBlocks.push_back(
new PpmSubBlockV1());
460 }
461 }
462
463
464
466 for (
int i = 0;
i < headerWords; ++
i) ++payload;
468 while (payload != payloadEnd)
469 {
470
471
472
473 int crate = 0;
475 int nPpmBlocks = 0;
476 for (int block = 0; block < numSubBlocks; ++block)
477 {
482 {
485 break;
486 }
489 {
491 {
492 msg() <<
"Unexpected channel sequence number: "
494 << block *chanPerSubBlock <<
endmsg;
495 }
497 break;
498 }
499 PpmSubBlockV1 *
const subBlock =
sd.m_ppmBlocks[block];
500 nPpmBlocks++;
501 if (firstBlock)
502 {
504 firstBlock = false;
505 }
506 else
507 {
508 subBlock->clear();
509 payload = subBlock->read(payload, payloadEnd);
510 }
511 if (block == 0)
512 {
513 crate = subBlock->crate();
514 module = subBlock->module();
516 {
518 }
519 if (crate != rodCrate)
520 {
522 {
523 msg() <<
"Inconsistent crate number in ROD source ID" <<
endmsg;
524 }
526 break;
527 }
528 }
529 else
530 {
531 if (subBlock->crate() != crate)
532 {
533 if (
debug)
msg() <<
"Inconsistent crate number in sub-blocks"
536 break;
537 }
538 if (subBlock->module() != module)
539 {
540 if (
debug)
msg() <<
"Inconsistent module number in sub-blocks"
543 break;
544 }
545 }
546 if (payload == payloadEnd && block != numSubBlocks - 1)
547 {
550 break;
551 }
552 }
554
555
556
557 bool isErrBlock = false;
558 if (payload != payloadEnd)
559 {
563 {
565 sd.m_errorBlock.clear();
566 isErrBlock = true;
567 payload =
sd.m_errorBlock.read(payload, payloadEnd);
568 if (
sd.m_errorBlock.crate() != crate)
569 {
570 if (
debug)
msg() <<
"Inconsistent crate number in error block"
573 break;
574 }
575 if (
sd.m_errorBlock.module() != module)
576 {
577 if (
debug)
msg() <<
"Inconsistent module number in error block"
580 break;
581 }
582 if (
sd.m_errorBlock.dataWords() && !
sd.m_errorBlock.unpack())
583 {
585 {
586 std::string errMsg(
sd.m_errorBlock.unpackErrorMsg());
587 msg() <<
"Unpacking error block failed: " << errMsg <<
endmsg;
588 }
589 rodErr =
sd.m_errorBlock.unpackErrorCode();
590 break;
591 }
592 }
593 }
594
595
596
597 const int index2 = (crate << 4) + module;
598 const int word2 =
index2 / 32;
599 const int bit2 =
index2 % 32;
600 if (!((colMod[word2] >> bit2) & 1)) continue;
601
602
603
604 for (int block = 0; block < nPpmBlocks; ++block)
605 {
606 PpmSubBlockV1 *
const subBlock =
sd.m_ppmBlocks[block];
607 subBlock->setLutOffset(trigLut);
608 subBlock->setFadcOffset(trigFadc);
610 subBlock->setFadcBaseline(fadcBaseline);
611 subBlock->setRunNumber(runNumber);
613 {
614 msg() <<
"Unpacking sub-block version/format/seqno: "
615 << subBlock->version() << "/" << subBlock->format() << "/"
616 << subBlock->seqno() <<
endmsg;
617 }
618 if (subBlock->dataWords() && !subBlock->unpack())
619 {
621 {
622 std::string errMsg(subBlock->unpackErrorMsg());
623 msg() <<
"Unpacking PPM sub-block failed: " << errMsg <<
endmsg;
624 }
625 rodErr = subBlock->unpackErrorCode();
626 break;
627 }
629 for (
int chan = 0;
chan < chanPerSubBlock; ++
chan)
630 {
631 const int channel = block * chanPerSubBlock +
chan;
632 const int index = (crate << 10) + (module << 6) +
channel;
633 const int word =
index / 32;
634 const int bit =
index % 32;
635 if (!((colChan[word] >> bit) & 1)) continue;
636 if (((
sd.m_foundChan[word] >> bit) & 1))
637 {
638 if (
debug)
msg() <<
"Duplicate data for crate/module/channel: "
642 break;
643 }
645 fadc.clear();
646 bcidLut.clear();
647 bcidFadc.clear();
648 subBlock->ppmData(channel, lut, fadc, bcidLut, bcidFadc);
649 if (
lut.size() <
size_t(trigLut + 1))
650 {
652 {
653 msg() <<
"Triggered LUT slice from header "
654 << "inconsistent with number of slices: "
655 << trigLut <<
", " <<
lut.size() <<
endmsg;
656 }
658 break;
659 }
660 if (fadc.size() < size_t(trigFadc + 1))
661 {
663 {
664 msg() <<
"Triggered FADC slice from header "
665 << "inconsistent with number of slices: "
666 << trigFadc <<
", " << fadc.size() <<
endmsg;
667 }
669 break;
670 }
671 LVL1::DataError errorBits(0);
672 if (isErrBlock)
673 {
675 sd.m_errorBlock.ppmError(channel));
677 sd.m_errorBlock.subStatus());
678 }
679 else
680 {
682 subBlock->ppmError(channel));
683 const PpmSubBlockV1 *const lastBlock =
684 sd.m_ppmBlocks[nPpmBlocks - 1];
686 lastBlock->subStatus());
687 }
688
689 if (subBlock->format() > 1 && subBlock->seqno() < 4)
690 {
693 }
694 const int error = errorBits.error();
695
696
697
699 {
700 msg(MSG::VERBOSE) <<
"channel/LUT/FADC/bcidLUT/bcidFADC/error: "
706 msg() << MSG::hex <<
error << MSG::dec <<
"/";
707 }
708 sd.m_foundChan[word] |= (1 << bit);
709 ++ttCount;
710 LVL1::TriggerTower *
tt = ttColRef[
sd.m_ttPos[
index]];
711 const int layer = ((
sd.m_chanLayer[word] >> bit) & 1);
712 if (layer == 0)
713 {
714 tt->addEM(fadc, lut, bcidFadc, bcidLut, error, trigLut, trigFadc);
715 }
716 else
717 {
718 tt->addHad(fadc, lut, bcidFadc, bcidLut, error, trigLut, trigFadc);
719 }
720 }
722 }
724 }
727 }
728
729
730
731 if (ttCount != colSize)
732 {
734 {
735 msg() <<
"Found " << ttCount <<
" channels, expected " << colSize <<
endmsg;
736 }
737 std::vector<int>
dummy(1);
738 for (int word = 0; word < chanBitVecSize; ++word)
739 {
740 if (
sd.m_foundChan[word] != colChan[word])
741 {
742 for (int bit = 0; bit < 32; ++bit)
743 {
744 if (((
sd.m_foundChan[word] >> bit) & 1) != ((colChan[word] >> bit) & 1))
745 {
746 const int index = word * 32 + bit;
747 LVL1::TriggerTower *
tt = ttColRef[
sd.m_ttPos[
index]];
748 const int layer = ((
sd.m_chanLayer[word] >> bit) & 1);
749 if (layer == 0)
750 {
751 tt->addEM(dummy, dummy, dummy, dummy, 0, 0, 0);
752 }
753 else if (dataChannels)
754 {
755 tt->addHad(dummy, dummy, dummy, dummy, 0, 0, 0);
756 }
757 }
758 }
759 }
760 }
761 }
762
763
764
766 {
767 TriggerTowerVector::iterator itr = ttCol.begin();
768 TriggerTowerVector::iterator itrE = ttCol.end();
769 for (; itr != itrE; ++itr)
770 {
771 if ((*itr)->emEnergy() || (dataChannels && (*itr)->hadEnergy()))
772 {
774 }
775 }
776 }
777 else
778 {
779 ttCollection->
assign(ttCol.begin(), ttCol.end());
780 }
781
782 return StatusCode::SUCCESS;
783}
value_type push_back(value_type pElem)
Add an element to the end of the collection.
void assign(InputIterator first, InputIterator last)
Assign from iterators.
static bool cmmBlock(uint32_t word)
Determine if header word corresponds to CMM.
static SubBlockWordType wordType(uint32_t word)
Word identification.
static bool errorBlock(uint32_t word)
Check if a header word is for an error block.
int count(std::string s, const std::string ®x)
count how many occurances of a regx are in a string