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
|
// -*- C++ -*-
//
// Package: EventFilter/L1TRawToDigi
// Class: L1TRawToDigi
//
/**\class L1TRawToDigi L1TRawToDigi.cc EventFilter/L1TRawToDigi/plugins/L1TRawToDigi.cc
Description: [one line class summary]
Implementation:
[Notes on implementation]
*/
//
// Original Author: Matthias Wolf
// Created: Mon, 10 Feb 2014 14:29:40 GMT
//
//
// system include files
#include <iostream>
#include <iomanip>
#include <memory>
#include <optional>
// user include files
#include "FWCore/Framework/interface/Frameworkfwd.h"
#include "FWCore/Framework/interface/stream/EDProducer.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/MakerMacros.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/Utilities/interface/InputTag.h"
#include "DataFormats/FEDRawData/interface/FEDHeader.h"
#include "DataFormats/FEDRawData/interface/FEDNumbering.h"
#include "DataFormats/FEDRawData/interface/FEDRawDataCollection.h"
#include "DataFormats/FEDRawData/interface/FEDTrailer.h"
#include "EventFilter/L1TRawToDigi/interface/AMC13Spec.h"
#include "EventFilter/L1TRawToDigi/interface/Block.h"
#include "PackingSetupFactory.h"
#include "EventFilter/L1TRawToDigi/plugins/implementations_stage2/L1TStage2Layer2Constants.h"
namespace l1t {
class L1TRawToDigi : public edm::stream::EDProducer<> {
public:
explicit L1TRawToDigi(const edm::ParameterSet&);
~L1TRawToDigi() override;
static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
private:
void produce(edm::Event&, const edm::EventSetup&) override;
// ----------member data ---------------------------
edm::EDGetTokenT<FEDRawDataCollection> fedData_;
std::vector<int> fedIds_;
unsigned int minFeds_;
unsigned int fwId_;
unsigned int dmxFwId_;
bool fwOverride_;
std::unique_ptr<PackingSetup> prov_;
// header and trailer sizes in chars
int slinkHeaderSize_;
int slinkTrailerSize_;
int amcHeaderSize_;
int amcTrailerSize_;
int amc13HeaderSize_;
int amc13TrailerSize_;
bool tmtCheck_;
bool ctp7_mode_;
bool mtf7_mode_;
bool debug_;
int warnsa_;
int warnsb_;
};
} // namespace l1t
std::ostream& operator<<(std::ostream& o, const l1t::BlockHeader& h) {
o << "L1T Block Header " << h.getID() << " with size " << h.getSize();
return o;
};
namespace l1t {
L1TRawToDigi::L1TRawToDigi(const edm::ParameterSet& config)
: fedIds_(config.getParameter<std::vector<int>>("FedIds")),
minFeds_(config.getParameter<unsigned int>("MinFeds")),
fwId_(config.getParameter<unsigned int>("FWId")),
dmxFwId_(config.getParameter<unsigned int>("DmxFWId")),
fwOverride_(config.getParameter<bool>("FWOverride")),
tmtCheck_(config.getParameter<bool>("TMTCheck")),
ctp7_mode_(config.getUntrackedParameter<bool>("CTP7")),
mtf7_mode_(config.getUntrackedParameter<bool>("MTF7")) {
fedData_ = consumes<FEDRawDataCollection>(config.getParameter<edm::InputTag>("InputLabel"));
if (ctp7_mode_ and mtf7_mode_) {
throw cms::Exception("L1TRawToDigi") << "Can only use one unpacking mode concurrently!";
}
prov_ = PackingSetupFactory::get()->make(config.getParameter<std::string>("Setup"));
prov_->registerProducts(producesCollector());
slinkHeaderSize_ = config.getUntrackedParameter<int>("lenSlinkHeader");
slinkTrailerSize_ = config.getUntrackedParameter<int>("lenSlinkTrailer");
amcHeaderSize_ = config.getUntrackedParameter<int>("lenAMCHeader");
amcTrailerSize_ = config.getUntrackedParameter<int>("lenAMCTrailer");
amc13HeaderSize_ = config.getUntrackedParameter<int>("lenAMC13Header");
amc13TrailerSize_ = config.getUntrackedParameter<int>("lenAMC13Trailer");
debug_ = config.getUntrackedParameter<bool>("debug");
warnsa_ = 0;
warnsb_ = 0;
}
L1TRawToDigi::~L1TRawToDigi() {}
//
// member functions
//
// ------------ method called to produce the data ------------
void L1TRawToDigi::produce(edm::Event& event, const edm::EventSetup& setup) {
using namespace edm;
std::unique_ptr<UnpackerCollections> coll = prov_->getCollections(event);
edm::Handle<FEDRawDataCollection> feds = event.getHandle(fedData_);
if (!feds.isValid()) {
LogError("L1T") << "Cannot unpack: no FEDRawDataCollection found";
return;
}
unsigned valid_count = 0;
for (const auto& fedId : fedIds_) {
const FEDRawData& l1tRcd = feds->FEDData(fedId);
LogDebug("L1T") << "Found FEDRawDataCollection with ID " << fedId << " and size " << l1tRcd.size();
if ((int)l1tRcd.size() < slinkHeaderSize_ + slinkTrailerSize_ + amc13HeaderSize_ + amc13TrailerSize_ +
amcHeaderSize_ + amcTrailerSize_) {
if (l1tRcd.size() > 0) {
LogError("L1T") << "Cannot unpack: invalid L1T raw data (size = " << l1tRcd.size() << ") for ID " << fedId
<< ". Returning empty collections!";
} else if (warnsa_ < 5) {
warnsa_++;
LogInfo("L1T") << "During unpacking, encountered empty L1T raw data (size = " << l1tRcd.size()
<< ") for FED ID " << fedId << ".";
}
continue;
} else {
valid_count++;
}
const unsigned char* data = l1tRcd.data();
FEDHeader header(data);
if (header.check()) {
LogDebug("L1T") << "Found SLink header:"
<< " Trigger type " << header.triggerType() << " L1 event ID " << header.lvl1ID()
<< " BX Number " << header.bxID() << " FED source " << header.sourceID() << " FED version "
<< header.version();
} else {
LogWarning("L1T") << "Did not find a SLink header!";
}
FEDTrailer trailer(data + (l1tRcd.size() - slinkTrailerSize_));
if (trailer.check()) {
LogDebug("L1T") << "Found SLink trailer:"
<< " Length " << trailer.fragmentLength() << " CRC " << trailer.crc() << " Status "
<< trailer.evtStatus() << " Throttling bits " << trailer.ttsBits();
} else {
LogWarning("L1T") << "Did not find a SLink trailer!";
}
// FIXME Hard-coded firmware version for first 74x MC campaigns.
// Will account for differences in the AMC payload, MP7 payload,
// and unpacker setup.
bool legacy_mc = fwOverride_ && ((fwId_ >> 24) == 0xff);
amc13::Packet packet;
if (!packet.parse((const uint64_t*)data,
(const uint64_t*)(data + slinkHeaderSize_),
(l1tRcd.size() - slinkHeaderSize_ - slinkTrailerSize_) / 8,
header.lvl1ID(),
header.bxID(),
legacy_mc,
mtf7_mode_)) {
LogError("L1T") << "Could not extract AMC13 Packet.";
return;
}
for (auto& amc : packet.payload()) {
if (amc.size() == 0)
continue;
auto payload64 = amc.data();
const uint32_t* start = reinterpret_cast<const uint32_t*>(&payload64.front());
// Want to have payload size in 32 bit words, but AMC measures
// it in 64 bit words → factor 2.
const uint32_t* end = start + (payload64.size() * 2);
std::unique_ptr<Payload> payload;
if (ctp7_mode_) {
LogDebug("L1T") << "Using CTP7 mode";
// CTP7 uses userData in AMC header
payload = std::make_unique<CTP7Payload>(start, end, amc.header());
} else if (mtf7_mode_) {
LogDebug("L1T") << "Using MTF7 mode";
payload = std::make_unique<MTF7Payload>(start, end);
} else {
LogDebug("L1T") << "Using MP7 mode";
payload = std::make_unique<MP7Payload>(start, end, legacy_mc);
}
unsigned fw = payload->getAlgorithmFWVersion();
unsigned board = amc.blockHeader().getBoardID();
unsigned amc_no = amc.blockHeader().getAMCNumber();
// Let parameterset value override FW version
if (fwOverride_) {
if (fedId == 1360)
fw = fwId_;
else if (fedId == 1366)
fw = dmxFwId_;
}
auto unpackers = prov_->getUnpackers(fedId, board, amc_no, fw);
// getBlock() returns a non-null optional on success
std::optional<Block> block;
while ((block = payload->getBlock())) {
// only unpack the Calo Layer 2 MP TMT node if it has processed this BX
unsigned tmtId = board - l1t::stage2::layer2::mp::offsetBoardId + 1;
unsigned bxId = header.bxID();
unsigned unpackTMT = (!tmtCheck_ || ((tmtId - 1) == ((bxId - 1 + 3) % 9)));
unsigned isCaloL2TMT =
(fedId == l1t::stage2::layer2::fedId && (amc_no != l1t::stage2::layer2::demux::amcSlotNum));
if (!isCaloL2TMT || unpackTMT) {
if (debug_) {
std::cout << ">>> block to unpack <<<" << std::endl
<< "hdr: " << std::hex << std::setw(8) << std::setfill('0') << block->header().raw()
<< std::dec << " (ID " << block->header().getID() << ", size " << block->header().getSize()
<< ", CapID 0x" << std::hex << std::setw(2) << std::setfill('0') << block->header().getCapID()
<< ")" << std::dec << std::endl;
for (const auto& word : block->payload()) {
if (debug_)
std::cout << "data: " << std::hex << std::setw(8) << std::setfill('0') << word << std::dec
<< std::endl;
}
}
auto unpacker = unpackers.find(block->header().getID());
block->amc(amc.header());
if (unpacker == unpackers.end()) {
LogDebug("L1T") << "Cannot find an unpacker for"
<< "\n\tblock: ID " << block->header().getID() << ", size " << block->header().getSize()
<< "\n\tAMC: # " << amc_no << ", board ID 0x" << std::hex << board << std::dec
<< "\n\tFED ID " << fedId << ", and FW ID " << fw;
// TODO Handle error
} else if (!unpacker->second->unpack(*block, coll.get())) {
LogDebug("L1T") << "Error unpacking data for block ID " << block->header().getID() << ", AMC # " << amc_no
<< ", board ID " << board << ", FED ID " << fedId << ", and FW ID " << fw << "!";
// TODO Handle error
}
}
}
}
}
if (valid_count < minFeds_) {
if (warnsb_ < 5) {
warnsb_++;
LogWarning("L1T") << "Unpacked " << valid_count << " non-empty FED IDs but minimum is set to " << minFeds_
<< "\n";
}
}
}
namespace {
edm::ParameterSetDescription makeDesc(std::vector<int> const& fedIDs,
unsigned int fwid,
std::string const& setup,
edm::InputTag const& label) {
edm::ParameterSetDescription desc;
// These parameters are part of the L1T/HLT interface, avoid changing if possible:
desc.add<std::vector<int>>("FedIds", fedIDs)->setComment("required parameter: default value is invalid");
desc.add<std::string>("Setup", setup)->setComment("required parameter: default value is invalid");
// These parameters have well defined default values and are not currently
// part of the L1T/HLT interface. They can be cleaned up or updated at will:
desc.add<unsigned int>("FWId", fwid)
->setComment(
"Ignored unless FWOverride is true. Calo Stage1: 32 bits: if the first eight bits are 0xff, will read "
"the "
"74x MC format.\n");
desc.add<unsigned int>("DmxFWId", 0)
->setComment(
"Ignored unless FWOverride is true. Calo Stage1: 32 bits: if the first eight bits are 0xff, will read "
"the 74x MC format.\n");
desc.add<bool>("FWOverride", false)->setComment("Firmware version should be taken as FWId parameters");
desc.add<bool>("TMTCheck", true)->setComment("Flag for turning on/off Calo Layer 2 TMT node check");
desc.addUntracked<bool>("CTP7", false);
desc.addUntracked<bool>("MTF7", false);
desc.add<edm::InputTag>("InputLabel", label);
desc.addUntracked<int>("lenSlinkHeader", 8);
desc.addUntracked<int>("lenSlinkTrailer", 8);
desc.addUntracked<int>("lenAMCHeader", 8);
desc.addUntracked<int>("lenAMCTrailer", 0);
desc.addUntracked<int>("lenAMC13Header", 8);
desc.addUntracked<int>("lenAMC13Trailer", 8);
desc.addUntracked<bool>("debug", false)->setComment("turn on verbose output");
desc.add<unsigned int>("MinFeds", 0)
->setComment("optional parameter: warn if less than MinFeds non-empty FED ids unpacked.");
return desc;
}
} // namespace
// ------------ method fills 'descriptions' with the allowed parameters for the module ------------
void L1TRawToDigi::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
descriptions.addDefault(makeDesc({}, 0, "", edm::InputTag("rawDataCollector")));
descriptions.add("l1tRawToDigi", makeDesc({1352}, 1, "stage2::CaloSetup", edm::InputTag("l1tDigiToRaw")));
}
} // namespace l1t
using namespace l1t;
//define this as a plug-in
DEFINE_FWK_MODULE(L1TRawToDigi);
|