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