Project
Loading...
Searching...
No Matches
PixelDecoder.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <fairlogger/Logger.h>
16#include <iostream>
17
18using namespace o2::focal;
19
21{
22 mPixelData.clear();
23 mChipData.clear();
24}
25
26void PixelDecoder::decodeEvent(gsl::span<const o2::itsmft::GBTWord> payload)
27{
28 o2::InteractionRecord currentIR;
29 bool physicsTrigger = false;
30 mPixelData.clear();
31 std::shared_ptr<PixelLaneHandler> currenttrigger;
32 for (const auto& word : payload) {
33 if (word.isDataHeader()) {
34 // to be defined
35 }
36 if (word.isDataTrailer()) {
37 // to be defined
38 }
39 if (word.isDiagnosticWord()) {
40 // to be defined
41 }
42 if (word.isTriggerWord()) {
43 auto lastIR = currentIR;
44 currentIR.orbit = word.orbit;
45 currentIR.bc = word.bc;
46 if (word.triggerType & o2::trigger::PhT) {
47 physicsTrigger = true;
48 }
49 if (lastIR != currentIR || !currenttrigger) {
50 auto found = mPixelData.find(currentIR);
51 if (found == mPixelData.end()) {
52 currenttrigger = std::make_shared<PixelLaneHandler>();
53 mPixelData[currentIR] = currenttrigger;
54 } else {
55 currenttrigger = found->second;
56 }
57 }
58 }
59 if (word.isData()) {
60 auto* dataword = reinterpret_cast<const o2::itsmft::GBTData*>(&word);
61 auto payload = gsl::span<const uint8_t>(reinterpret_cast<const uint8_t*>(word.getW8()), 9);
62 int lane = -1;
63 if (word.isDataIB()) {
64 lane = dataword->getLaneIB();
65 } else if (word.isDataOB()) {
66 // lane = dataword->getLaneOB();
67 // MF treat as if they would be IB lanes
68 lane = dataword->getLaneIB();
69 }
70 if (lane >= PixelLaneHandler::NLANES) {
71 // Discarding lanes
72 continue;
73 }
74 currenttrigger->getLane(lane).append(payload);
75 }
76 }
77
78 mChipData.clear();
79
80 // std::cout << "Found " << mPixelData.size() << " triggers" << std::endl;
81 LOG(debug) << "Found " << mPixelData.size() << " triggers";
82 for (auto& [trigger, data] : mPixelData) {
83 // std::cout << "Found trigger " << trigger.asString() << std::endl;
84 LOG(debug) << "Found trigger " << trigger.asString();
85 std::vector<PixelChip> combinedChips;
86 int foundLanes = 0;
87 for (int ilane = 0; ilane < PixelLaneHandler::NLANES; ilane++) {
88 const auto& lane = data->getLane(ilane);
89 if (lane.getPayload().size()) {
90 // std::cout << "[Lane " << ilane << "] " << lane << std::endl;
91 LOG(debug) << "[Lane " << ilane << "] " << lane;
92 auto laneChips = decodeLane(ilane, lane.getPayload());
93 auto chipsBefore = combinedChips.size();
94 std::copy(laneChips.begin(), laneChips.end(), std::back_inserter(combinedChips));
95 // std::cout << "Merging combined chips, before " << chipsBefore << ", after " << combinedChips.size() << std::endl;
96 LOG(debug) << "Merging combined chips, before " << chipsBefore << ", after " << combinedChips.size();
97 foundLanes++;
98 }
99 }
100 // std::cout << "Trigger has " << combinedChips.size() << " chips from " << foundLanes << " lanes " << std::endl;
101 LOG(debug) << "Trigger has " << combinedChips.size() << " chips from " << foundLanes << " lanes ";
102 std::sort(combinedChips.begin(), combinedChips.end(), std::less<>());
103 for (auto& chip : combinedChips) {
104 // std::cout << "Chip " << static_cast<int>(chip.mChipID) << " [lane " << static_cast<int>(chip.mLaneID) << "], with " << chip.mHits.size() << " hit(s) ... " << std::endl;
105 LOG(debug) << "Chip " << static_cast<int>(chip.mChipID) << " [lane " << static_cast<int>(chip.mLaneID) << "], with " << chip.mHits.size() << " hit(s) ... ";
106 }
107 mChipData[trigger] = combinedChips;
108 }
109}
110
111PixelWord::PixelWordType PixelDecoder::getWordType(uint8_t payloadword)
112{
113 // native alpide words
114 if (payloadword == 0xff) {
116 } else if (payloadword == 0xf1) {
118 } else if (payloadword == 0xf0) {
120 } else if ((payloadword & 0xf0) == 0xa0) {
122 } else if ((payloadword & 0xf0) == 0xb0) {
124 } else if ((payloadword & 0xf0) == 0xe0) {
126 } else if ((payloadword & 0xe0) == 0xc0) {
128 } else if ((payloadword & 0xc0) == 0x40) {
130 } else if ((payloadword & 0xc0) == 0x00) {
132 }
134}
135
136uint16_t PixelDecoder::AlpideY(uint16_t address)
137{
138 return address / 2;
139}
140
141uint16_t PixelDecoder::AlpideX(uint8_t region, uint8_t encoder, uint16_t address)
142{
143 int x = region * 32 + encoder * 2;
144 if (address % 4 == 1) {
145 x++;
146 }
147 if (address % 4 == 2) {
148 x++;
149 }
150 return x;
151}
152
153std::vector<PixelChip> PixelDecoder::decodeLane(uint8_t laneID, gsl::span<const uint8_t> laneWords)
154{
155 bool done = false;
156 auto currentptr = laneWords.data();
157
158 uint8_t currentChipID;
159 uint8_t currentRegion;
160 uint16_t currentChipStatus;
161 std::vector<PixelHit> hits;
162 std::vector<PixelChip> decodedChips;
163 bool activeChip = false;
164 while (!done) {
165 if (!activeChip && (*currentptr == 0)) {
166 // skip 0 outside active chip
167 currentptr++;
168 if (currentptr - laneWords.data() >= laneWords.size()) {
169 done = true;
170 }
171 continue;
172 }
173 auto wordtype = getWordType(*currentptr);
174 std::size_t wordsize;
175 switch (wordtype) {
177 auto emptyword = reinterpret_cast<const PixelWord::ChipHeader*>(currentptr);
178 wordsize = sizeof(PixelWord::ChipHeader) / sizeof(uint8_t);
179 hits.clear();
180 auto chipID = emptyword->mChipID;
181 // std::cout << "Empty chip (" << std::bitset<4>(emptyword->mIdentifier) << ") " << int(emptyword->mChipID) << ", BC (" << int(emptyword->mBunchCrossing) << "), empty " << (emptyword->isEmptyFrame() ? "yes" : "no") << std::endl;
182 LOG(debug) << "Empty chip (" << std::bitset<4>(emptyword->mIdentifier) << ") " << int(emptyword->mChipID) << ", BC (" << int(emptyword->mBunchCrossing) << "), empty " << (emptyword->isEmptyFrame() ? "yes" : "no");
183 if (std::find_if(decodedChips.begin(), decodedChips.end(), [chipID, laneID](const PixelChip& chip) { return chip.mChipID == chipID && chip.mLaneID == laneID; }) == decodedChips.end()) {
184 // Add empty chip to decoded payload (if not yet present)
185 // std::cout << "Creating new empty frame" << std::endl;
186 LOG(debug) << "Creating new empty frame";
187 currentChipStatus = (emptyword->mIdentifier) << 8;
188 decodedChips.push_back({0, laneID, static_cast<uint8_t>(chipID), currentChipStatus, hits});
189 } else {
190 // std::cout << "Skipping existing empty frame" << std::endl;
191 LOG(debug) << "Skipping existing empty frame";
192 }
193 break;
194 }
196 auto chipheader = reinterpret_cast<const PixelWord::ChipHeader*>(currentptr);
197 wordsize = sizeof(PixelWord::ChipHeader) / sizeof(uint8_t);
198 hits.clear();
199 currentChipID = chipheader->mChipID;
200 activeChip = true;
201 currentChipStatus = (chipheader->mIdentifier) << 8;
202 // std::cout << "New chip (" << std::bitset<4>(chipheader->mIdentifier) << ") " << int(chipheader->mChipID) << ", BC (" << int(chipheader->mBunchCrossing) << "), empty " << (chipheader->isEmptyFrame() ? "yes" : "no") << std::endl;
203 LOG(debug) << "New chip (" << std::bitset<4>(chipheader->mIdentifier) << ") " << int(chipheader->mChipID) << ", BC (" << int(chipheader->mBunchCrossing) << "), empty " << (chipheader->isEmptyFrame() ? "yes" : "no");
204 break;
205 }
207 auto trailer = reinterpret_cast<const PixelWord::ChipTrailer*>(currentptr);
208 wordsize = sizeof(PixelWord::ChipTrailer) / sizeof(uint8_t);
209 currentChipStatus |= trailer->mReadoutFlags;
210 // -> Combine hits to chip
211 // -> Write hits to output container
212 // std::cout << "Finished chip (" << std::bitset<4>(trailer->mIdentifier) << ") " << int(currentChipID) << " with " << hits.size() << " hits .. (Readout flags " << std::bitset<4>(trailer->mReadoutFlags) << ")" << std::endl;
213 LOG(debug) << "Finished chip (" << std::bitset<4>(trailer->mIdentifier) << ") " << int(currentChipID) << " with " << hits.size() << " hits .. (Readout flags " << std::bitset<4>(trailer->mReadoutFlags) << ")";
214 auto found = std::find_if(decodedChips.begin(), decodedChips.end(), [currentChipID, laneID](const PixelChip& chip) { return chip.mChipID == currentChipID && chip.mLaneID == laneID; });
215 if (found != decodedChips.end()) {
216 auto hitsbefore = found->mHits.size();
217 std::copy(hits.begin(), hits.end(), std::back_inserter(found->mHits));
218 found->mStatusCode = currentChipStatus;
219 found->removeEmptyframe();
220 // std::cout << "Merging data with existing chip, Hits before: " << hitsbefore << ", after: " << found->mHits.size() << std::endl;
221 LOG(debug) << "Merging data with existing chip, Hits before: " << hitsbefore << ", after: " << found->mHits.size();
222 } else {
223 // std::cout << "Inserting new chip" << std::endl;
224 LOG(debug) << "Inserting new chip";
225 decodedChips.push_back({0, laneID, currentChipID, currentChipStatus, hits});
226 }
227 activeChip = false;
228 break;
229 }
231 auto regionheader = reinterpret_cast<const PixelWord::RegionHeader*>(currentptr);
232 wordsize = sizeof(PixelWord::RegionHeader) / sizeof(uint8_t);
233 currentRegion = regionheader->mRegion;
234 // std::cout << "New region (" << std::bitset<3>(regionheader->mIdentifier) << ") " << int(regionheader->mRegion) << std::endl;
235 LOG(debug) << "New region (" << std::bitset<3>(regionheader->mIdentifier) << ") " << int(regionheader->mRegion);
236 break;
237 }
239 PixelWord::DataShort datashort(currentptr);
240 // std::cout << "Found DataShort [" << std::bitset<16>(datashort.mData) << "] word (" << std::bitset<2>(datashort.mIdentifier) << ") with encoder " << std::bitset<4>(datashort.mEncoderID) << " and address " << std::bitset<10>(datashort.mAddress) << std::endl;
241 LOG(debug) << "Found DataShort [" << std::bitset<16>(datashort.mData) << "] word (" << std::bitset<2>(datashort.mIdentifier) << ") with encoder " << std::bitset<4>(datashort.mEncoderID) << " and address " << std::bitset<10>(datashort.mAddress);
242 wordsize = sizeof(PixelWord::DataShort) / sizeof(uint8_t);
243 hits.push_back({AlpideX(currentRegion, datashort.mEncoderID, datashort.mAddress), AlpideY(datashort.mAddress)});
244 break;
245 }
247 // Split word in 2 parts - DataShort and hitmap
248 PixelWord::DataShort datapart(currentptr);
249 auto hitmappart = reinterpret_cast<const PixelWord::Hitmap*>(currentptr + sizeof(PixelWord::DataShort));
250 // std::cout << "Found DataLong [" << std::bitset<16>(datapart.mData) << "] word (" << std::bitset<2>(datapart.mIdentifier) << ") with encoder " << std::bitset<4>(datapart.mEncoderID) << " and address " << std::bitset<10>(datapart.mAddress) << std::endl;
251 LOG(debug) << "Found DataLong [" << std::bitset<16>(datapart.mData) << "] word (" << std::bitset<2>(datapart.mIdentifier) << ") with encoder " << std::bitset<4>(datapart.mEncoderID) << " and address " << std::bitset<10>(datapart.mAddress);
252 wordsize = (sizeof(PixelWord::DataShort) + (sizeof(PixelWord::Hitmap))) / sizeof(uint8_t);
253 auto hitmap = hitmappart->getHitmap();
254 for (int bitID = 0; bitID < hitmap.size(); bitID++) {
255 if (hitmap.test(bitID)) {
256 auto address = datapart.mAddress + bitID + 1;
257 hits.push_back({AlpideX(currentRegion, datapart.mEncoderID, address), AlpideY(address)});
258 }
259 }
260 break;
261 }
263 // std::cout << "Found busy off" << std::endl;
264 wordsize = sizeof(PixelWord::BusyOff) / sizeof(uint8_t);
266 // std::cout << "Found busy on" << std::endl;
267 wordsize = sizeof(PixelWord::BusyOn) / sizeof(uint8_t);
269 // std::cout << "Found idle" << std::endl;
270 wordsize = sizeof(PixelWord::Idle) / sizeof(uint8_t);
271 default:
272 // std::cout << "Found unknown word" << std::endl;
273 wordsize = 1;
274 break;
275 };
276 currentptr += wordsize;
277 if (currentptr - laneWords.data() >= laneWords.size()) {
278 done = true;
279 }
280 }
281 // std::cout << "Lane " << laneID << ": Found " << decodedChips.size() << " chips ... " << std::endl;
282 LOG(debug) << "Lane " << laneID << ": Found " << decodedChips.size() << " chips ... ";
283 return decodedChips;
284}
Definition of the 32 Central Trigger System (CTS) Trigger Types defined in https://twiki....
bool done
std::ostringstream debug
void decodeEvent(gsl::span< const o2::itsmft::GBTWord > payload)
static constexpr std::size_t NLANES
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint GLuint64EXT address
Definition glcorearb.h:5846
GLboolean * data
Definition glcorearb.h:298
uint8_t itsSharedClusterMap uint8_t
constexpr uint32_t PhT
Definition Triggers.h:30
uint32_t orbit
LHC orbit.
uint16_t bc
bunch crossing ID of interaction
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"