ATLAS Offline Software
Loading...
Searching...
No Matches
CpmRoiByteStreamV1Tool.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 <numeric>
7#include <set>
8#include <utility>
9
11
12#include "GaudiKernel/IInterface.h"
13#include "GaudiKernel/MsgStream.h"
14#include "GaudiKernel/StatusCode.h"
15
17
18#include "CpmRoiSubBlockV1.h"
20#include "L1CaloUserHeader.h"
21
23
24namespace LVL1BS {
25
26// Interface ID
27
28static const InterfaceID IID_ICpmRoiByteStreamV1Tool("CpmRoiByteStreamV1Tool",
29 1, 1);
30
35
36// Constructor
37
39 const std::string& name,
40 const IInterface* parent)
41 : AthAlgTool(type, name, parent),
42 m_errorTool("LVL1BS::L1CaloErrorByteStreamTool/L1CaloErrorByteStreamTool"),
43 m_crates(4), m_modules(14),
44 m_subDetector (eformat::TDAQ_CALO_CLUSTER_PROC_ROI)
45{
46 declareInterface<CpmRoiByteStreamV1Tool>(this);
47
48 declareProperty("ErrorTool", m_errorTool,
49 "Tool to collect errors for monitoring");
50 declareProperty("CrateOffsetHw", m_crateOffsetHw = 8,
51 "Offset of CP crate numbers in bytestream");
52 declareProperty("CrateOffsetSw", m_crateOffsetSw = 0,
53 "Offset of CP crate numbers in RDOs");
54
55 // Properties for reading bytestream only
56 declareProperty("ROBSourceIDs", m_sourceIDsProp,
57 "ROB fragment source identifiers");
58 declareProperty("ROBSourceIDsRoIB", m_sourceIDsRoIBProp,
59 "ROB fragment source identifiers for RoIBs");
60
61 // Properties for writing bytestream only
62 declareProperty("DataVersion", m_version = 1,
63 "Format version number in sub-block header");
64 declareProperty("DataFormat", m_dataFormat = 1,
65 "Format identifier (0-1) in sub-block header");
66 declareProperty("SlinksPerCrate", m_slinks = 1,
67 "The number of S-Links per crate");
68 declareProperty("CrateMin", m_crateMin = 0,
69 "Minimum crate number, allows partial output");
70 declareProperty("CrateMax", m_crateMax = m_crates-1,
71 "Maximum crate number, allows partial output");
72
73}
74
75// Destructor
76
80
81// Initialize
82
83
85{
86 ATH_MSG_INFO ("Initializing " << name());
87
88 ATH_CHECK( m_errorTool.retrieve() );
89 ATH_CHECK( m_byteStreamCnvSvc.retrieve() );
90
91 return StatusCode::SUCCESS;
92}
93
94// Convert ROB fragments to CPM RoIs
95
97 const IROBDataProviderSvc::VROBFRAG& robFrags,
98 DataVector<LVL1::CPMRoI>* const roiCollection) const
99{
100 const bool debug = msgLvl(MSG::DEBUG);
101 if (debug) msg(MSG::DEBUG);
102
103 // Sub-block for neutral format
104 CpmRoiSubBlockV1 subBlock;
105
106 // Loop over ROB fragments
107
108 int robCount = 0;
109 std::set<uint32_t> dupCheck;
110 std::set<uint32_t> dupRoiCheck;
111 ROBIterator rob = robFrags.begin();
112 ROBIterator robEnd = robFrags.end();
113 for (; rob != robEnd; ++rob) {
114
115 if (debug) {
116 ++robCount;
117 msg() << "Treating ROB fragment " << robCount << endmsg;
118 }
119
120 // Skip fragments with ROB status errors
121
122 uint32_t robid = (*rob)->source_id();
123 if ((*rob)->nstatus() > 0) {
124 ROBPointer robData;
125 (*rob)->status(robData);
126 if (*robData != 0) {
127 m_errorTool->robError(robid, *robData);
128 if (debug) msg() << "ROB status error - skipping fragment" << endmsg;
129 continue;
130 }
131 }
132
133 // Skip duplicate fragments
134
135 if (!dupCheck.insert(robid).second) {
137 if (debug) msg() << "Skipping duplicate ROB fragment" << endmsg;
138 continue;
139 }
140
141 // Unpack ROD data (slinks)
142
143 RODPointer payloadBeg;
144 RODPointer payload;
145 RODPointer payloadEnd;
146 (*rob)->rod_data(payloadBeg);
147 payloadEnd = payloadBeg + (*rob)->rod_ndata();
148 payload = payloadBeg;
149 if (payload == payloadEnd) {
150 if (debug) msg() << "ROB fragment empty" << endmsg;
151 continue;
152 }
153
154 // Check identifier
155 const uint32_t sourceID = (*rob)->rod_source_id();
156 if (m_srcIdMap.getRobID(sourceID) != robid ||
157 m_srcIdMap.subDet(sourceID) != m_subDetector ||
158 m_srcIdMap.daqOrRoi(sourceID) != 1 ||
159 (m_srcIdMap.slink(sourceID) != 0 && m_srcIdMap.slink(sourceID) != 2) ||
160 m_srcIdMap.crate(sourceID) < m_crateOffsetHw ||
161 m_srcIdMap.crate(sourceID) >= m_crateOffsetHw + m_crates) {
163 if (debug) {
164 msg() << "Wrong source identifier in data: "
165 << MSG::hex << sourceID << MSG::dec << endmsg;
166 }
167 continue;
168 }
169
170 // Check minor version
171 const int minorVersion = (*rob)->rod_version() & 0xffff;
172 if (minorVersion > m_srcIdMap.minorVersionPreLS1()) {
173 if (debug) msg() << "Skipping post-LS1 data" << endmsg;
174 continue;
175 }
176 const int rodCrate = m_srcIdMap.crate(sourceID);
177 if (debug) {
178 msg() << "Treating crate " << rodCrate
179 << " slink " << m_srcIdMap.slink(sourceID) << endmsg;
180 }
181
182 // First word may be User Header
183 if (L1CaloUserHeader::isValid(*payload)) {
184 L1CaloUserHeader userHeader(*payload);
185 userHeader.setVersion(minorVersion);
186 const int headerWords = userHeader.words();
187 if (headerWords != 1 ) {
189 if (debug) msg() << "Unexpected number of user header words: "
190 << headerWords << endmsg;
191 continue;
192 }
193 for (int i = 0; i < headerWords; ++i) ++payload;
194 }
195
196 // Loop over sub-blocks if there are any
197
198 unsigned int rodErr = L1CaloSubBlock::ERROR_NONE;
199 while (payload != payloadEnd) {
200
202 subBlock.clear();
203 payload = subBlock.read(payload, payloadEnd);
204 if (debug) {
205 msg() << "CPM RoI sub-block: Crate " << subBlock.crate()
206 << " Module " << subBlock.module() << endmsg;
207 }
208 // Unpack sub-block
209 if (subBlock.dataWords() && !subBlock.unpack()) {
210 if (debug) {
211 std::string errMsg(subBlock.unpackErrorMsg());
212 msg() << "CPM RoI sub-block unpacking failed: " << errMsg << endmsg;
213 }
214 rodErr = subBlock.unpackErrorCode();
215 break;
216 }
217 const int numChips = 8;
218 const int numLocs = 2;
219 for (int chip = 0; chip < numChips; ++chip) {
220 for (int loc = 0; loc < numLocs; ++loc) {
221 const LVL1::CPMRoI roi = subBlock.roi(chip, loc);
222 if (roi.hits() || roi.error()) {
223 roiCollection->push_back(new LVL1::CPMRoI(roi));
224 }
225 }
226 }
227 } else {
228 // Just RoI word
229 LVL1::CPMRoI roi;
230 if (roi.setRoiWord(*payload)) {
231 if (roi.crate() != rodCrate - m_crateOffsetHw) {
232 if (debug) msg() << "Inconsistent RoI crate number: "
233 << roi.crate() << endmsg;
235 break;
236 }
237 if (roi.cpm() == 0 || roi.cpm() > m_modules) {
238 if (debug) msg() << "Invalid CPM number: "
239 << roi.cpm() << endmsg;
241 break;
242 }
243 const uint32_t location = (*payload) & 0xfffc0000;
244 if (dupRoiCheck.insert(location).second) {
245 if (roi.hits() || roi.error()) {
246 roiCollection->push_back(new LVL1::CPMRoI(*payload));
247 }
248 } else {
249 if (debug) msg() << "Duplicate RoI word "
250 << MSG::hex << *payload << MSG::dec << endmsg;
252 break;
253 }
254 } else {
255 if (debug) msg() << "Invalid RoI word "
256 << MSG::hex << *payload << MSG::dec << endmsg;
258 break;
259 }
260 ++payload;
261 }
262 }
263 if (rodErr != L1CaloSubBlock::ERROR_NONE)
264 m_errorTool->rodError(robid, rodErr);
265 }
266
267 return StatusCode::SUCCESS;
268}
269
270// Convert CPM RoI to bytestream
271
273 const DataVector<LVL1::CPMRoI>* const roiCollection) const
274{
275 const bool debug = msgLvl(MSG::DEBUG);
276 if (debug) msg(MSG::DEBUG);
277
278 // Get the event assembler
279
281 ATH_CHECK( m_byteStreamCnvSvc->getFullEventAssembler (fea,
282 "CpmRoiByteStreamV1") );
283 uint16_t minorVersion = m_srcIdMap.minorVersionPreLS1();
284 fea->setRodMinorVersion(minorVersion);
285
286 // Pointer to ROD data vector
287
289
290 // Sub-block for neutral format
291 CpmRoiSubBlockV1 subBlock;
292
293 // Set up the container map
294
295 // CPM RoI map
296 CpmRoiMap roiMap;
297 setupCpmRoiMap(roiCollection, roiMap);
298 CpmRoiMap::const_iterator mapIter = roiMap.begin();
299 CpmRoiMap::const_iterator mapIterEnd = roiMap.end();
300
301 // Loop over data
302
303 const bool neutralFormat = m_dataFormat == L1CaloSubBlock::NEUTRAL;
304 const int modulesPerSlink = m_modules / m_slinks;
305 for (int crate = m_crateMin; crate <= m_crateMax; ++crate) {
306 const int hwCrate = crate + m_crateOffsetHw;
307
308 // CPM modules are numbered 1 to m_modules
309 for (int module=1; module <= m_modules; ++module) {
310 const int mod = module - 1;
311
312 // Pack required number of modules per slink
313
314 if (mod%modulesPerSlink == 0) {
315 const int daqOrRoi = 1;
316 const int slink = (m_slinks == 2) ? 2*(mod/modulesPerSlink)
317 : mod/modulesPerSlink;
318 if (debug) {
319 msg() << "Treating crate " << hwCrate
320 << " slink " << slink << endmsg
321 << "Data Version/Format: " << m_version
322 << " " << m_dataFormat << endmsg;
323 }
324 const uint32_t rodIdCpm = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
326 theROD = fea->getRodData(rodIdCpm);
327 if (neutralFormat) {
328 const L1CaloUserHeader userHeader;
329 theROD->push_back(userHeader.header());
330 }
331 }
332 if (debug) msg() << "Module " << module << endmsg;
333
334 // Create a sub-block (Neutral format only)
335
336 if (neutralFormat) {
337 subBlock.clear();
338 subBlock.setRoiHeader(m_version, hwCrate, module);
339 }
340
341 // Find CPM RoIs for this module
342
343 for (; mapIter != mapIterEnd; ++mapIter) {
344 const LVL1::CPMRoI* const roi = mapIter->second;
345 if (roi->crate() < crate) continue;
346 if (roi->crate() > crate) break;
347 if (roi->cpm() < module) continue;
348 if (roi->cpm() > module) break;
349 if (roi->hits() || roi->error()) {
350 if (neutralFormat) subBlock.fillRoi(*roi);
351 else theROD->push_back(roi->roiWord());
352 }
353 }
354
355 // Pack and write the sub-block
356
357 if (neutralFormat) {
358 if ( !subBlock.pack()) {
359 msg(MSG::ERROR) << "CPMRoI sub-block packing failed" << endmsg;
360 return StatusCode::FAILURE;
361 }
362 if (debug) {
363 msg() << "CPMRoI sub-block data words: "
364 << subBlock.dataWords() << endmsg;
365 }
366 subBlock.write(theROD);
367 }
368 }
369 }
370
371 return StatusCode::SUCCESS;
372}
373
374// Return reference to vector with all possible Source Identifiers
375
376std::vector<uint32_t> CpmRoiByteStreamV1Tool::makeSourceIDs (bool roiDaq) const
377{
378 std::vector<uint32_t> sourceIDs;
379
380 if (roiDaq) {
382 }
383 else {
385 }
386
387 if (sourceIDs.empty()) {
388 const int maxCrates = m_crates + m_crateOffsetHw;
389 const int maxSlinks = m_srcIdMap.maxSlinks();
390 for (int hwCrate = m_crateOffsetHw; hwCrate < maxCrates; ++hwCrate)
391 {
392 for (int slink = 0; slink < maxSlinks; ++slink)
393 {
394 const int daqOrRoi = 1;
395 const uint32_t rodId = m_srcIdMap.getRodID(hwCrate, slink, daqOrRoi,
397 const uint32_t robId = m_srcIdMap.getRobID(rodId);
398 if (roiDaq)
399 {
400 if (slink < 2) sourceIDs.push_back(robId);
401 }
402 else if (slink >= 2) sourceIDs.push_back(robId);
403 }
404 }
405
406 }
407 return sourceIDs;
408}
409
410const std::vector<uint32_t>& CpmRoiByteStreamV1Tool::sourceIDs(
411 const std::string& sgKey) const
412{
413 const std::string flag("RoIB");
414 const std::string::size_type pos = sgKey.find(flag);
415 const bool roiDaq =
416 (pos == std::string::npos || pos != sgKey.length() - flag.length());
417
418 if (roiDaq) {
419 static const std::vector<uint32_t> sourceIDs = makeSourceIDs(roiDaq);
420 return sourceIDs;
421 }
422 else {
423 static const std::vector<uint32_t> sourceIDsRoIB = makeSourceIDs(roiDaq);
424 return sourceIDsRoIB;
425 }
426}
427
428// Set up CPM RoI map
429
431 const roiCollection,
432 CpmRoiMap& roiMap) const
433{
434 roiMap.clear();
435 if (roiCollection) {
436 CpmRoiCollection::const_iterator pos = roiCollection->begin();
437 CpmRoiCollection::const_iterator pose = roiCollection->end();
438 for (; pos != pose; ++pos) {
439 const LVL1::CPMRoI* const roi = *pos;
440 const uint32_t key = roi->roiWord();
441 roiMap.insert(std::make_pair(key, roi));
442 }
443 }
444}
445
446} // end namespace
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
const bool debug
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
Derived DataVector<T>.
Definition DataVector.h:795
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
value_type push_back(value_type pElem)
Add an element to the end of the collection.
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
Template class for assembling a full atlas raw event from subfragments.
void setRodMinorVersion(uint16_t m)
change the ROD minor version
std::vector< uint32_t > RODDATA
ROD data as a vector of unsigned int.
RODDATA * getRodData(uint32_t id)
get a block of ROD data
std::vector< const ROBF * > VROBFRAG
std::vector< uint32_t > makeSourceIDs(bool roiDaq) const
int m_version
Property: Sub_block header version.
StatusCode convert(const IROBDataProviderSvc::VROBFRAG &robFrags, DataVector< LVL1::CPMRoI > *roiCollection) const
Convert ROB fragments to CPM RoIs.
const int m_crates
Number of crates.
static const InterfaceID & interfaceID()
AlgTool InterfaceID.
int m_crateOffsetSw
Property: Software crate number offset.
const L1CaloSrcIdMap m_srcIdMap
Source ID converter.
int m_crateMin
Property: Minimum crate number when writing out bytestream.
ToolHandle< LVL1BS::L1CaloErrorByteStreamTool > m_errorTool
Property: Error collection tool.
const int m_modules
Number of CPM modules per crate.
virtual StatusCode initialize() override
OFFLINE_FRAGMENTS_NAMESPACE::PointerType RODPointer
void setupCpmRoiMap(const CpmRoiCollection *roiCollection, CpmRoiMap &roiMap) const
Set up CPM RoI map.
const std::vector< uint32_t > & sourceIDs(const std::string &sgKey) const
Return reference to vector with all possible Source Identifiers.
std::vector< uint32_t > m_sourceIDsProp
Property: ROB source IDs.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType ROBPointer
ServiceHandle< IByteStreamCnvSvc > m_byteStreamCnvSvc
int m_dataFormat
Property: Data compression format.
std::map< uint32_t, const LVL1::CPMRoI * > CpmRoiMap
const eformat::SubDetector m_subDetector
Sub-detector type.
CpmRoiByteStreamV1Tool(const std::string &type, const std::string &name, const IInterface *parent)
std::vector< uint32_t > m_sourceIDsRoIBProp
Property: ROB source IDs for RoIB.
int m_slinks
Property: Number of slinks per crate when writing out bytestream.
DataVector< LVL1::CPMRoI > CpmRoiCollection
int m_crateMax
Property: Maximum crate number when writing out bytestream.
IROBDataProviderSvc::VROBFRAG::const_iterator ROBIterator
int m_crateOffsetHw
Property: Hardware crate number offset.
Sub-Block class for CPM RoI data (neutral format).
void clear()
Clear all data.
LVL1::CPMRoI roi(int chip, int loc) const
Return RoI for given chip and location (left/right)
void fillRoi(LVL1::CPMRoI roi)
Store RoI.
void setRoiHeader(int version, int crate, int module)
Store header.
int unpackErrorCode() const
Return the unpacking error code.
int dataWords() const
Return number of data words.
static SubBlockWordType wordType(uint32_t word)
Word identification.
void write(FullEventAssembler< L1CaloSrcIdMap >::RODDATA *theROD) const
Output complete packed sub-block to ROD vector.
std::string unpackErrorMsg() const
Return the unpacking error message for printing.
OFFLINE_FRAGMENTS_NAMESPACE::PointerType read(const OFFLINE_FRAGMENTS_NAMESPACE::PointerType beg, const OFFLINE_FRAGMENTS_NAMESPACE::PointerType end)
Input complete packed sub-block from ROD array.
L1Calo User Header class.
static bool isValid(uint32_t word)
Test for valid header word.
void setVersion(int minorVersion)
Set version flag.
int words() const
Return number of header words (should be one)
uint32_t header() const
Return packed header.
uint32_t roiWord() const
Return packed RoI word.
int crate() const
Return crate number (0-1)
int hits() const
Return hit thresholds map.
int cpm() const
Return CPM number (1-14)
bool setRoiWord(uint32_t roiWord)
Set RoI word with ID check.
Definition CPMRoI.cxx:57
int error() const
Return error flags (bit 0 Saturation, bit 1 Parity)
static const InterfaceID IID_ICpmRoiByteStreamV1Tool("CpmRoiByteStreamV1Tool", 1, 1)