Belle II Software  release-08-01-10
TOPPackerModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 // Own header.
10 #include <top/modules/TOPPacker/TOPPackerModule.h>
11 
12 // TOP headers.
13 #include <top/RawDataTypes.h>
14 
15 // framework - DataStore
16 #include <framework/datastore/StoreArray.h>
17 #include <framework/datastore/StoreObjPtr.h>
18 
19 // framework aux
20 #include <framework/logging/Logger.h>
21 
22 // Dataobject classes
23 #include <top/dataobjects/TOPDigit.h>
24 #include <top/dataobjects/TOPRawDigit.h>
25 #include <rawdata/dataobjects/RawTOP.h>
26 #include <framework/dataobjects/EventMetaData.h>
27 
28 using namespace std;
29 
30 namespace Belle2 {
36  using namespace TOP;
37 
38  //-----------------------------------------------------------------
40  //-----------------------------------------------------------------
41 
42  REG_MODULE(TOPPacker);
43 
44  //-----------------------------------------------------------------
45  // Implementation
46  //-----------------------------------------------------------------
47 
48  TOPPackerModule::TOPPackerModule() : Module()
49  {
50  // set module description (e.g. insert text)
51  setDescription("Raw data packer for TOP");
53 
54  // Add parameters
55  addParam("inputDigitsName", m_inputDigitsName,
56  "name of TOPDigit store array", string(""));
57  addParam("inputRawDigitsName", m_inputRawDigitsName,
58  "name of TOPRawDigit store array", string(""));
59  addParam("outputRawDataName", m_outputRawDataName,
60  "name of RawTOP store array", string(""));
61  addParam("format", m_format,
62  "data format (draft, FE, production)", string("production"));
63 
64  }
65 
67  {
68  }
69 
71  {
72 
73  if (m_format == "draft") {
74  m_dataType = TOP::RawDataType::c_Draft;
76  digits.isRequired();
77  } else if (m_format == "FE") {
78  m_dataType = TOP::RawDataType::c_Type0Ver16;
80  rawDigits.isRequired();
81  } else if (m_format == "production") {
82  m_dataType = TOP::RawDataType::c_ProductionDebug01;
84  rawDigits.isRequired();
85  } else {
86  B2ERROR("TOPPacker: unknown data format."
87  << LogVar("format", m_format));
88  }
89 
91  rawData.registerInDataStore();
92 
93  // check if front end mappings are available
94  const auto& mapper = m_topgp->getFrontEndMapper();
95  if (!mapper.isValid()) B2ERROR("No front-end mapping available for TOP");
96 
97  }
98 
100  {
101  }
102 
104  {
105 
106  switch (m_dataType) {
107  case TOP::RawDataType::c_Type0Ver16:
108  packType0Ver16();
109  break;
110  case TOP::RawDataType::c_ProductionDebug01:
112  break;
113  case TOP::RawDataType::c_Draft:
115  break;
116  default:
117  B2ERROR("TOPPacker: data format unknown or not implemented");
118  }
119 
120  }
121 
122 
124  {
125  }
126 
128  {
129  }
130 
131 
133  {
134  StoreObjPtr<EventMetaData> evtMetaData;
137 
138  const auto& mapper = m_topgp->getFrontEndMapper();
139  int mapSize = mapper.getMapSize();
140  if (mapSize == 0) return;
141 
142  vector<const TOPDigit*>* sortedDigits = new vector<const TOPDigit*>[mapSize];
143 
144  for (const auto& digit : digits) {
145  int moduleID = digit.getModuleID();
146  int boardstack = digit.getChannel() / 128;
147  const auto* feemap = mapper.getMap(moduleID, boardstack);
148  if (!feemap) {
149  B2ERROR("TOPPacker: no front-end map available."
150  << LogVar("moduleID", moduleID)
151  << LogVar("boardstack", boardstack));
152  continue;
153  }
154  sortedDigits[feemap->getIndex()].push_back(&digit);
155  }
156 
157  auto subBits = m_topgp->getGeometry()->getNominalTDC().getSubBits();
158  int sampleDivisions = 0x1 << subBits;
159 
160  for (const auto& copperID : mapper.getCopperIDs()) {
161  vector<int> Buffer[4];
162  for (int finesse = 0; finesse < 4; finesse++) {
163  const auto* feemap = mapper.getMapFromCopper(copperID, finesse);
164  if (!feemap) continue;
165  unsigned scrodID = feemap->getScrodID();
166  unsigned dataFormat = static_cast<unsigned>(TOP::RawDataType::c_Draft);
167  Buffer[finesse].push_back(scrodID + (dataFormat << 16));
168  for (const auto& digit : sortedDigits[feemap->getIndex()]) {
169  double rawTime = digit->getRawTime();
170  unsigned tdc = int(rawTime * sampleDivisions) & 0xFFFF;
171  unsigned chan = digit->getChannel() % 128;
172  unsigned flags = (unsigned) digit->getHitQuality();
173  Buffer[finesse].push_back(tdc + (chan << 16) + (flags << 24));
174  }
175  }
176  RawCOPPERPackerInfo info;
177  info.exp_num = evtMetaData->getExperiment();
178  // run number : 14bits, subrun # : 8bits
179  info.run_subrun_num = (evtMetaData->getRun() << 8) +
180  (evtMetaData->getSubrun() & 0xFF);
181  info.eve_num = evtMetaData->getEvent();
182  info.node_id = TOP_ID + copperID;
183  info.tt_ctime = 0;
184  info.tt_utime = 0;
185  info.b2l_ctime = 0;
186  info.hslb_crc16_error_bit = 0;
187  info.truncation_mask = 0;
188  info.type_of_data = 0;
189 
190  auto* raw = rawData.appendNew();
191  raw->PackDetectorBuf(Buffer[0].data(), Buffer[0].size(),
192  Buffer[1].data(), Buffer[1].size(),
193  Buffer[2].data(), Buffer[2].size(),
194  Buffer[3].data(), Buffer[3].size(),
195  info);
196  }
197  delete [] sortedDigits;
198  }
199 
200 
202  {
203  StoreObjPtr<EventMetaData> evtMetaData;
206 
207  const auto& mapper = m_topgp->getFrontEndMapper();
208  int mapSize = mapper.getMapSize();
209  if (mapSize == 0) return;
210 
211  auto* sortedDigits = new vector<const TOPRawDigit*>[mapSize];
212 
213  for (const auto& digit : digits) {
214  auto scrodID = digit.getScrodID();
215  const auto* feemap = mapper.getMap(scrodID);
216  if (!feemap) {
217  B2ERROR("TOPPacker: no front-end map available."
218  << LogVar("scrodID", scrodID));
219  continue;
220  }
221  sortedDigits[feemap->getIndex()].push_back(&digit);
222  }
223 
224  for (const auto& copperID : mapper.getCopperIDs()) {
225  vector<int> Buffer[4];
226  for (int finesse = 0; finesse < 4; finesse++) {
227  const auto* feemap = mapper.getMapFromCopper(copperID, finesse);
228  if (!feemap) continue;
229  unsigned scrodID = feemap->getScrodID();
230  unsigned dataFormat = static_cast<unsigned>(TOP::RawDataType::c_Type0Ver16);
231 
232  // production data v2.1 (data_format_v2_1.xlsx from Lynn 06/26/2016)
233  unsigned head = (dataFormat << 16) | (0xA << 12) | (scrodID & 0x0FFF);
234  Buffer[finesse].push_back(head);
235  unsigned Nhits = 0;
236  for (const auto& digit : sortedDigits[feemap->getIndex()]) {
237  unsigned word1 =
238  (digit->getCarrierNumber() << 30) |
239  ((digit->getASICNumber() & 0x3) << 28) |
240  ((digit->getASICChannel() & 0x7) << 25) |
241  ((digit->getASICWindow() & 0x1FF) << 16) |
242  (0xB << 12) |
243  ((digit->getTFine() & 0xF) << 8);
244  Buffer[finesse].push_back(word1);
245  unsigned word2 =
246  ((digit->getValuePeak() & 0x1FFF) << 16) |
247  (digit->getIntegral() & 0xFFFF);
248  Buffer[finesse].push_back(word2);
249  unsigned word3 =
250  ((digit->getValueRise0() & 0x1FFF) << 16) |
251  (digit->getValueRise1() & 0x1FFF);
252  Buffer[finesse].push_back(word3);
253  unsigned word4 =
254  ((digit->getValueFall0() & 0x1FFF) << 16) |
255  (digit->getValueFall1() & 0x1FFF);
256  Buffer[finesse].push_back(word4);
257  unsigned word5 =
258  (digit->getSampleRise() << 24) |
259  ((digit->getDeltaSamplePeak() & 0xF) << 20) |
260  ((digit->getDeltaSampleFall() & 0xF) << 16);
261  short checkSum = -(sumShorts(word1) + sumShorts(word2) + sumShorts(word3) +
262  sumShorts(word4) + sumShorts(word5));
263  word5 |= (checkSum & 0xFFFF);
264  Buffer[finesse].push_back(word5);
265  Nhits++;
266  }
267  unsigned tail = (0x5 << 9) | (Nhits & 0x1FF);
268  Buffer[finesse].push_back(tail);
269  }
270  RawCOPPERPackerInfo info;
271  info.exp_num = evtMetaData->getExperiment();
272  // run number : 14bits, subrun # : 8bits
273  info.run_subrun_num = (evtMetaData->getRun() << 8) +
274  (evtMetaData->getSubrun() & 0xFF);
275  info.eve_num = evtMetaData->getEvent();
276  info.node_id = TOP_ID + copperID;
277  info.tt_ctime = 0;
278  info.tt_utime = 0;
279  info.b2l_ctime = 0;
280  info.hslb_crc16_error_bit = 0;
281  info.truncation_mask = 0;
282  info.type_of_data = 0;
283 
284  auto* raw = rawData.appendNew();
285  raw->PackDetectorBuf(Buffer[0].data(), Buffer[0].size(),
286  Buffer[1].data(), Buffer[1].size(),
287  Buffer[2].data(), Buffer[2].size(),
288  Buffer[3].data(), Buffer[3].size(),
289  info);
290  }
291  delete [] sortedDigits;
292  }
293 
294 
296  {
297  StoreObjPtr<EventMetaData> evtMetaData;
300 
301  const auto& mapper = m_topgp->getFrontEndMapper();
302  int mapSize = mapper.getMapSize();
303  if (mapSize == 0) return;
304 
305  auto* sortedDigits = new vector<const TOPRawDigit*>[mapSize];
306 
307  for (const auto& digit : digits) {
308  auto scrodID = digit.getScrodID();
309  const auto* feemap = mapper.getMap(scrodID);
310  if (!feemap) {
311  B2ERROR("TOPPacker: no front-end map available."
312  << LogVar("scrodID", scrodID));
313  continue;
314  }
315  sortedDigits[feemap->getIndex()].push_back(&digit);
316  }
317 
318  unsigned revo9count = 0;
319  unsigned phase = 0;
320  if (digits.getEntries() > 0) {
321  revo9count = digits[0]->getRevo9Counter();
322  phase = digits[0]->getPhase();
323  }
324 
325  for (const auto& copperID : mapper.getCopperIDs()) {
326  vector<int> Buffer[4];
327  for (int finesse = 0; finesse < 4; finesse++) {
328  const auto* feemap = mapper.getMapFromCopper(copperID, finesse);
329  if (!feemap) continue;
330  unsigned scrodID = feemap->getScrodID();
331  unsigned format = static_cast<unsigned>(TOP::RawDataType::c_ProductionDebug01);
332 
333  unsigned head0 = (format << 16) | (0xA << 12) | (scrodID & 0x0FFF);
334  Buffer[finesse].push_back(head0);
335 
336  unsigned numWordsCore = sortedDigits[feemap->getIndex()].size() * 5 + 1;
337  unsigned head1 = ((phase & 0xF) << 12) | (numWordsCore & 0xFFF);
338  Buffer[finesse].push_back(head1);
339 
340  unsigned head2 = revo9count & 0xFFFF;
341  Buffer[finesse].push_back(head2);
342 
343  unsigned head3 = 0;
344  Buffer[finesse].push_back(head3);
345 
346  unsigned Nhits = 0;
347  for (const auto& digit : sortedDigits[feemap->getIndex()]) {
348  unsigned checkSum = 0; // IPv4 checksum
349  unsigned word0 =
350  (digit->getCarrierNumber() << 30) |
351  ((digit->getASICNumber() & 0x3) << 28) |
352  ((digit->getASICChannel() & 0x7) << 25) |
353  ((digit->getASICWindow() & 0x1FF) << 16) |
354  (0xB << 12) |
355  ((digit->getTFine() & 0xF) << 8);
356  checkSum += (word0 & 0xFFFF) + ((word0 >> 16) & 0xFFFF);
357  Buffer[finesse].push_back(word0);
358  unsigned word1 =
359  ((digit->getValuePeak() & 0x1FFF) << 16) |
360  (digit->getIntegral() & 0xFFFF);
361  checkSum += (word1 & 0xFFFF) + ((word1 >> 16) & 0xFFFF);
362  Buffer[finesse].push_back(word1);
363  unsigned word2 =
364  ((digit->getValueRise0() & 0x1FFF) << 16) |
365  (digit->getValueRise1() & 0x1FFF);
366  checkSum += (word2 & 0xFFFF) + ((word2 >> 16) & 0xFFFF);
367  Buffer[finesse].push_back(word2);
368  unsigned word3 =
369  ((digit->getValueFall0() & 0x1FFF) << 16) |
370  (digit->getValueFall1() & 0x1FFF);
371  checkSum += (word3 & 0xFFFF) + ((word3 >> 16) & 0xFFFF);
372  Buffer[finesse].push_back(word3);
373  unsigned word4 =
374  (digit->getSampleRise() << 24) |
375  ((digit->getDeltaSamplePeak() & 0xF) << 20) |
376  ((digit->getDeltaSampleFall() & 0xF) << 16);
377  checkSum += (word4 & 0xFFFF) + ((word4 >> 16) & 0xFFFF);
378  while ((checkSum >> 16) > 0) {
379  checkSum = (checkSum & 0xFFFF) + (checkSum >> 16);
380  }
381  word4 |= ((~checkSum) & 0xFFFF);
382  Buffer[finesse].push_back(word4);
383  Nhits++;
384  }
385  unsigned tail = (0x5 << 9) | (Nhits & 0x1FF);
386  Buffer[finesse].push_back(tail);
387  }
388 
389  RawCOPPERPackerInfo info;
390  info.exp_num = evtMetaData->getExperiment();
391  // run number : 14bits, subrun # : 8bits
392  info.run_subrun_num = (evtMetaData->getRun() << 8) +
393  (evtMetaData->getSubrun() & 0xFF);
394  info.eve_num = evtMetaData->getEvent();
395  info.node_id = TOP_ID + copperID;
396  info.tt_ctime = 0;
397  info.tt_utime = 0;
398  info.b2l_ctime = 0;
399  info.hslb_crc16_error_bit = 0;
400  info.truncation_mask = 0;
401  info.type_of_data = 0;
402 
403  auto* raw = rawData.appendNew();
404  raw->PackDetectorBuf(Buffer[0].data(), Buffer[0].size(),
405  Buffer[1].data(), Buffer[1].size(),
406  Buffer[2].data(), Buffer[2].size(),
407  Buffer[3].data(), Buffer[3].size(),
408  info);
409  }
410  delete [] sortedDigits;
411  }
412 
414 } // end Belle2 namespace
415 
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
struct to contain header information used by RawCOPPERFormat::Packer()
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
const TOPNominalTDC & getNominalTDC() const
Returns nominal time-to-digit conversion parameters.
Definition: TOPGeometry.h:218
unsigned getSubBits() const
Returns number of bits per sample.
std::string m_format
data format
std::string m_inputDigitsName
name of TOPDigit store array
unsigned short sumShorts(unsigned int x) const
sum both 16-bit words of 32-bit integer
TOP::RawDataType m_dataType
enum for data format
std::string m_outputRawDataName
name of RawTOP store array
std::string m_inputRawDigitsName
name of TOPRawDigit store array
TOP::TOPGeometryPar * m_topgp
geometry
int getMapSize() const
Return size of the map.
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
const FrontEndMapper & getFrontEndMapper() const
Returns front-end mapper (mapping of SCROD's to positions within TOP modules)
Class to store variables with their name which were sent to the logging service.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
virtual void initialize() override
Initialize the Module.
void packProductionDraft()
Pack in format: c_Draft (tentative production format) this format was never implemented in firmware!
void packProductionDebug()
Pack in format: Production Debugging Data Format 01.
virtual void event() override
Event processor.
virtual ~TOPPackerModule()
Destructor.
virtual void endRun() override
End-of-run action.
virtual void terminate() override
Termination action.
virtual void beginRun() override
Called when entering a new run.
void packType0Ver16()
Pack in format: c_Type0Ver16 (Feature-extracted data) this format was never implemented in firmware!
Abstract base class for different kinds of events.