1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|
#include "EventFilter/GctRawToDigi/plugins/GctRawToDigi.h"
// System headers
#include <vector>
#include <sstream>
#include <iostream>
// Framework headers
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/Framework/interface/MakerMacros.h"
// Raw data collection headers
#include "DataFormats/FEDRawData/interface/FEDNumbering.h"
#include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
// GCT Format Translators
#include "EventFilter/GctRawToDigi/src/GctFormatTranslateMCLegacy.h"
#include "EventFilter/GctRawToDigi/src/GctFormatTranslateV35.h"
#include "EventFilter/GctRawToDigi/src/GctFormatTranslateV38.h"
// Unpack collections class
#include "EventFilter/GctRawToDigi/src/GctUnpackCollections.h"
// Namespace resolution
using std::cout;
using std::dec;
using std::endl;
using std::hex;
using std::string;
using std::vector;
GctRawToDigi::GctRawToDigi(const edm::ParameterSet& iConfig)
: inputLabel_(iConfig.getParameter<edm::InputTag>("inputLabel")),
fedId_(iConfig.getUntrackedParameter<int>("gctFedId", FEDNumbering::MINTriggerGCTFEDID)),
hltMode_(iConfig.getParameter<bool>("hltMode")),
numberOfGctSamplesToUnpack_(iConfig.getParameter<unsigned>("numberOfGctSamplesToUnpack")),
numberOfRctSamplesToUnpack_(iConfig.getParameter<unsigned>("numberOfRctSamplesToUnpack")),
unpackSharedRegions_(iConfig.getParameter<bool>("unpackSharedRegions")),
formatVersion_(iConfig.getParameter<unsigned>("unpackerVersion")),
checkHeaders_(iConfig.getUntrackedParameter<bool>("checkHeaders", false)),
verbose_(iConfig.getUntrackedParameter<bool>("verbose", false)),
formatTranslator_(nullptr),
errors_(nullptr),
errorCounters_(MAX_ERR_CODE + 1), // initialise with the maximum error codes!
unpackFailures_(0) {
LogDebug("GCT") << "GctRawToDigi will unpack FED Id " << fedId_;
// If the GctFormatTranslate version has been forced from config file, instantiate the relevant one.
/*** THIS OBVIOUSLY STINKS - NEED TO REPLACE WITH SOMETHING BETTER THAN MASSIVE IF-ELSE SOON ***/
/*** WHEN THIS MESS IS REMOVED REMEMBER THAT THE V38 FORMAT TRANSLATE HAS A DIFERENT CTOR TO THE OTHERS ***/
if (formatVersion_ == 0) {
edm::LogInfo("GCT")
<< "The required GCT Format Translator will be automatically determined from the first S-Link packet header.";
} else if (formatVersion_ == 1) {
edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateMCLegacy";
formatTranslator_ = new GctFormatTranslateMCLegacy(hltMode_, unpackSharedRegions_);
} else if (formatVersion_ == 2) {
edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateV35";
formatTranslator_ = new GctFormatTranslateV35(hltMode_, unpackSharedRegions_);
} else if (formatVersion_ == 3) {
edm::LogInfo("GCT") << "You have selected to use GctFormatTranslateV38";
formatTranslator_ = new GctFormatTranslateV38(
hltMode_, unpackSharedRegions_, numberOfGctSamplesToUnpack_, numberOfRctSamplesToUnpack_);
} else {
edm::LogWarning("GCT")
<< "You have requested a version of GctFormatTranslate that does not exist! Will attempt to auto-detect "
"the required GCT Format Translator from the first S-Link packet header instead.";
}
if (hltMode_) {
edm::LogInfo("GCT") << "HLT unpack mode selected: HLT unpack optimisations will be used.";
}
if (unpackSharedRegions_) {
edm::LogInfo("GCT") << "You have selected to unpack shared RCT calo regions - be warned: "
"this is for commissioning purposes only!";
}
/** Register Products **/
// GCT input collections
produces<L1GctFibreCollection>();
produces<L1CaloEmCollection>();
produces<L1CaloRegionCollection>();
// GCT internal collections
produces<L1GctInternEmCandCollection>();
produces<L1GctInternJetDataCollection>();
produces<L1GctInternEtSumCollection>();
produces<L1GctInternHFDataCollection>();
produces<L1GctInternHtMissCollection>();
// GCT output collections
produces<L1GctEmCandCollection>("isoEm");
produces<L1GctEmCandCollection>("nonIsoEm");
produces<L1GctJetCandCollection>("cenJets");
produces<L1GctJetCandCollection>("forJets");
produces<L1GctJetCandCollection>("tauJets");
produces<L1GctHFBitCountsCollection>();
produces<L1GctHFRingEtSumsCollection>();
produces<L1GctEtTotalCollection>();
produces<L1GctEtHadCollection>();
produces<L1GctEtMissCollection>();
produces<L1GctHtMissCollection>();
produces<L1GctJetCountsCollection>(); // Deprecated (empty collection still needed by GT)
// Error collection
produces<L1TriggerErrorCollection>();
consumes<FEDRawDataCollection>(inputLabel_);
}
GctRawToDigi::~GctRawToDigi() {
// do anything here that needs to be done at destruction time
// (e.g. close files, deallocate resources etc.)
delete formatTranslator_;
}
void GctRawToDigi::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.add<bool>("unpackSharedRegions", false);
desc.add<unsigned int>("numberOfGctSamplesToUnpack", 1);
desc.add<unsigned int>("numberOfRctSamplesToUnpack", 1);
desc.add<bool>("hltMode", false);
desc.add<edm::InputTag>("inputLabel", edm::InputTag("rawDataCollector"));
static const char* const kComment =
" \n"
" value | Unpacker/RAW Format Version \n"
"-----------|---------------------------------------------------------------------------- \n"
" 0 | Auto-detects RAW Format in use - the recommended option \n"
" 1 | Force usage of the Monte-Carlo Legacy unpacker (unpacks DigiToRaw events) \n"
" 2 | Force usage of the RAW Format V35 unpacker \n"
" 3 | Force usage of the RAW Format V38 unpacker \n";
desc.add<unsigned int>("unpackerVersion", 0)->setComment(kComment);
desc.addUntracked<int>("gctFedId", 745);
desc.addUntracked<bool>("checkHeaders", false), desc.addUntracked<bool>("verbose", false);
descriptions.add("gctRawToDigi", desc);
}
//
// member functions
//
// ------------ method called to produce the data ------------
void GctRawToDigi::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
using namespace edm;
// Instantiate all the collections the unpacker needs; puts them in event when this object goes out of scope.
std::unique_ptr<GctUnpackCollections> colls(new GctUnpackCollections(iEvent));
errors_ = colls->errors();
// get raw data collection
edm::Handle<FEDRawDataCollection> feds;
iEvent.getByLabel(inputLabel_, feds);
// if raw data collection is present, do the unpacking
if (feds.isValid()) {
const FEDRawData& gctRcd = feds->FEDData(fedId_);
LogDebug("GCT") << "Upacking FEDRawData of size " << std::dec << gctRcd.size();
// check for empty events
if (gctRcd.size() < 16) {
LogDebug("GCT") << "Cannot unpack: empty/invalid GCT raw data (size = " << gctRcd.size()
<< "). Returning empty collections!";
addError(1);
return;
}
// If no format translator yet set, need to auto-detect from header.
// If auto format detection fails, we have no concrete format
// translator instantiated... set error and bail
if (!formatTranslator_) {
if (!autoDetectRequiredFormatTranslator(gctRcd.data()))
return;
}
// reset collection of block headers
blockHeaders_.clear();
// do the unpacking
unpack(gctRcd, iEvent, colls.get());
// check headers, if enabled
if (checkHeaders_)
checkHeaders();
// dump summary in verbose mode
if (verbose_) {
doVerboseOutput(blockHeaders_, colls.get());
}
}
}
void GctRawToDigi::unpack(const FEDRawData& d, edm::Event& e, GctUnpackCollections* const colls) {
// We should now have a valid formatTranslator pointer
formatTranslator_->setUnpackCollections(colls);
const unsigned char* data = d.data(); // The 8-bit wide raw-data array.
// Data offset - starts at 16 as there is a 64-bit S-Link header followed
// by a 64-bit software-controlled header (for pipeline format version
// info that is not yet used).
unsigned dPtr = 16;
const unsigned dEnd = d.size() - 8; // End of payload is at (packet size - final slink header)
// read blocks
for (unsigned nb = 0; dPtr < dEnd; ++nb) {
if (nb >= MAX_BLOCKS) {
LogDebug("GCT") << "Reached block limit - bailing out from this event!";
addError(6);
break;
}
// read block header
GctBlockHeader blockHeader = formatTranslator_->generateBlockHeader(&data[dPtr]);
// unpack the block; dPtr+4 is to get to the block data.
if (!formatTranslator_->convertBlock(&data[dPtr + 4],
blockHeader)) // Record if we had an unpack problem then skip rest of event.
{
LogDebug("GCT") << "Encountered block unpack error - bailing out from this event!";
addError(4);
break;
}
// advance pointer
dPtr += 4 * (blockHeader.blockLength() * blockHeader.nSamples() +
1); // *4 because blockLen is in 32-bit words, +1 for header
// if verbose or checking block headers, store the header
if (verbose_ || checkHeaders_)
blockHeaders_.push_back(blockHeader);
}
}
// detect raw data format version from known raw data address
bool GctRawToDigi::autoDetectRequiredFormatTranslator(const unsigned char* d) {
LogDebug("GCT") << "About to auto-detect the required format translator from the firmware version header.";
const uint32_t* p32 = reinterpret_cast<const uint32_t*>(d);
unsigned firmwareHeader = p32[2];
/*** THIS OBVIOUSLY STINKS - NEED TO REPLACE WITH SOMETHING BETTER THAN MASSIVE IF-ELSE SOON ***/
/*** WHEN THIS MESS IS REMOVED REMEMBER THAT THE V38 FORMAT TRANSLATE HAS A DIFERENT CTOR TO THE OTHERS ***/
if (firmwareHeader >= 25 && firmwareHeader <= 35) {
edm::LogInfo("GCT") << "Firmware Version V" << firmwareHeader << " detected: GctFormatTranslateV" << firmwareHeader
<< " will be used to unpack.";
formatTranslator_ = new GctFormatTranslateV35(hltMode_, unpackSharedRegions_);
return true;
} else if (firmwareHeader == 38) {
edm::LogInfo("GCT") << "Firmware Version V" << firmwareHeader << " detected: GctFormatTranslateV" << firmwareHeader
<< " will be used to unpack.";
formatTranslator_ = new GctFormatTranslateV38(
hltMode_, unpackSharedRegions_, numberOfGctSamplesToUnpack_, numberOfRctSamplesToUnpack_);
return true;
} else if (firmwareHeader == 0x00000000) {
edm::LogInfo("GCT") << "Legacy Monte-Carlo data detected: GctFormatTranslateMCLegacy will be used to unpack.";
formatTranslator_ = new GctFormatTranslateMCLegacy(hltMode_, unpackSharedRegions_);
return true;
}
// these lines comments otherwise error is not reported!!!
// else if(firmwareHeader == 0xdeadffff) { /* Driver detected unknown firmware version. L1TriggerError code? */ }
// else if( firmwareHeader == 0xaaaaaaaa) { /* Before driver firmware version checks implemented. L1TriggerError code? */ }
else { /* Totally unknown firmware header */
LogDebug("GCT") << "Failed to determine unpacker to use from the firmware version header! "
"(firmware header = 0x"
<< hex << firmwareHeader << dec << ")";
addError(2);
return false;
}
}
void GctRawToDigi::checkHeaders() {
// TODO : loop over block headers found this event and check for consistency
}
void GctRawToDigi::doVerboseOutput(const GctBlockHeaderCollection& bHdrs,
const GctUnpackCollections* const colls) const {
std::ostringstream os;
os << "Found " << bHdrs.size() << " GCT block headers" << endl;
for (unsigned i = 0, size = bHdrs.size(); i < size; ++i) {
os << "GCT Raw Data Block : " << formatTranslator_->getBlockDescription(bHdrs[i]) << " : " << bHdrs[i] << endl;
}
os << *colls << endl;
edm::LogVerbatim("GCT") << os.str();
}
void GctRawToDigi::addError(const unsigned code) {
// check this isn't going to break error handling
if (code > MAX_ERR_CODE) {
LogDebug("GCT") << "Unknown error code : " << code;
return;
}
// print message on first instance of this error and if verbose flag set to true
if (errorCounters_.at(code) == 0 && verbose_) {
std::ostringstream os;
switch (code) {
case 0:
os << "Reserved error code - not in use";
break;
case 1:
os << "FED record empty or too short";
break;
case 2:
os << "Unknown raw data version";
break;
case 3:
os << "Detected unknown firmware version";
break;
case 4:
os << "Detected unknown data block";
break;
case 5:
os << "Block headers out of sync";
break;
case 6:
os << "Too many blocks";
break;
default:
os << "Unknown error code";
}
edm::LogError("GCT") << "Unpacking error " << code << " : " << os.str();
}
// increment error counter
++(errorCounters_.at(code));
// store error in event if possible
if (errors_ != nullptr) {
errors_->push_back(L1TriggerError(fedId_, code));
} else
LogDebug("GCT") << "Detected error (code=" << code << ") but no error collection available!";
}
// ------------ method called once each job just after ending the event loop ------------
void GctRawToDigi::endJob() {
unsigned total = 0;
std::ostringstream os;
for (unsigned i = 0; i <= MAX_ERR_CODE; ++i) {
total += errorCounters_.at(i);
os << "Error " << i << " (" << errorCounters_.at(i) << ")";
if (i < MAX_ERR_CODE) {
os << ", ";
}
}
if (total > 0 && verbose_) {
edm::LogError("GCT") << "Encountered " << total << " unpacking errors: " << os.str();
}
}
/// make this a plugin
DEFINE_FWK_MODULE(GctRawToDigi);
|