Belle II Software  release-06-00-14
ARICHPackerModule.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 include
10 #include <arich/modules/arichPacker/ARICHPackerModule.h>
11 
12 // framework - DataStore
13 #include <framework/datastore/StoreArray.h>
14 #include <framework/datastore/StoreObjPtr.h>
15 
16 // framework aux
17 #include <framework/logging/Logger.h>
18 
19 // Dataobject classes
20 #include <arich/dataobjects/ARICHDigit.h>
21 #include <rawdata/dataobjects/RawARICH.h>
22 #include <framework/dataobjects/EventMetaData.h>
23 #include <bitset>
24 
25 using namespace std;
26 
27 namespace Belle2 {
33 #define ARICH_BUFFER_NWORDS 252 // arich number of words (ints) in buffer; 3 + 33 + 6 * 36; 3 merger header words + 5.5 FEB header words / FEB + 36 data words per / FEB
34  //-----------------------------------------------------------------
35  // Register module
36  //-----------------------------------------------------------------
37 
38  REG_MODULE(ARICHPacker)
39 
40  //-----------------------------------------------------------------
41  // Implementation
42  //-----------------------------------------------------------------
43 
45  m_nonSuppressed(0), m_bitMask(0), m_debug(0)
46 
47  {
48  // set module description (e.g. insert text)
49  setDescription("Raw data packer for ARICH");
50  setPropertyFlags(c_ParallelProcessingCertified);
51  addParam("nonSuppressed", m_nonSuppressed, "Pack in non-suppressed format (store all channels)", unsigned(0));
52  addParam("version", m_version, "dataformat version", unsigned(6));
53  addParam("bitMask", m_bitMask, "hit bit mask (4 bits/channel)", (unsigned)0xF);
54  addParam("debug", m_debug, "print packed bitmap", 0);
55  addParam("inputDigitsName", m_inputDigitsName, "name of ARICHDigit store array", string(""));
56  addParam("outputRawDataName", m_outputRawDataName, "name of RawARICH store array", string(""));
57 
58  }
59 
60  ARICHPackerModule::~ARICHPackerModule()
61  {
62  }
63 
64  void ARICHPackerModule::initialize()
65  {
66 
67  StoreArray<ARICHDigit> digits(m_inputDigitsName);
68  digits.isRequired();
69 
70  StoreArray<RawARICH> rawData(m_outputRawDataName);
71  rawData.registerInDataStore();
72  }
73 
74  void ARICHPackerModule::beginRun()
75  {
76  }
77 
78  void ARICHPackerModule::event()
79  {
80 
81  StoreObjPtr<EventMetaData> evtMetaData;
82  StoreArray<ARICHDigit> digits(m_inputDigitsName);
83  StoreArray<RawARICH> rawData(m_outputRawDataName);
84 
85  int nModules = N_MERGERS * N_FEB2MERGER;
86 
87  vector<const ARICHDigit*>* sortedDigits = new vector<const ARICHDigit*>[nModules];
88  int nPacked = 0;
89  for (const auto& digit : digits) {
90  int moduleID = digit.getModuleID();
91  unsigned mergerID = m_mergerMap->getMergerID(moduleID);
92  if (!mergerID) { B2WARNING("No module2merger mapping for module ID: " << moduleID << "; Digit will not be packed!"); continue;}
93  if (!m_copperMap->getCopperID(mergerID)) { B2WARNING("No merger2copper mapping for merger ID: " << mergerID << "; Digit will not be packed!"); continue;}
94  sortedDigits[moduleID - 1].push_back(&digit);
95  nPacked++;
96  }
97 
98  int buffer[4][ARICH_BUFFER_NWORDS];
99 
100  for (const auto& copperID : m_copperMap->getCopperIDs()) {
101 
102  int bufferSize[4] = {0, 0, 0, 0};
103  for (int finesse = 0; finesse < 4; finesse++) {
104 
105  unsigned ibyte = 0;
106 
107  for (int j = 0; j < ARICH_BUFFER_NWORDS; j++) {
108  buffer[finesse][j] = 0;
109  }
110 
111  auto* buf = buffer[finesse];
112 
113  // get corresponding merger ID
114  unsigned mergerID = m_copperMap->getMergerID(copperID, finesse);
115  unsigned mergerSN = m_mergerMap->getMergerSN(mergerID);
116  if (!mergerID) continue;
117 
118  ARICHRawHeader mergerHead;
119  unsigned dataFormat = m_nonSuppressed + 1; // production data -> TODO: use enum
120  mergerHead.type = dataFormat;
121  mergerHead.version = m_version;
122  mergerHead.mergerID = mergerSN;
123  mergerHead.FEBSlot = 0;
124  mergerHead.trigger = evtMetaData->getEvent();
125  // mergerHead.length dont forget
126 
127  ibyte += ARICHRAW_HEADER_SIZE;
128 
129  int nboards = N_FEB2MERGER;
130 
131  for (int k = 0; k < nboards; k++) {
132 
133  int moduleID = m_mergerMap->getModuleID(mergerID, k + 1);
134  if (moduleID <= 0) continue;
135 
136  // FEB header
137  ARICHRawHeader FEBHead;
138  FEBHead.type = dataFormat;
139  FEBHead.version = m_version;
140  FEBHead.mergerID = mergerSN;
141  FEBHead.FEBSlot = k; // board slots go from 0-5 for now, if firmware is updated to 1-6 add +1 !!
142  FEBHead.trigger = evtMetaData->getEvent();
143 
144  if (m_nonSuppressed) {
145  // data length in bytes
146  FEBHead.length = 144 + ARICHFEB_HEADER_SIZE; // 144ch * 1 byte
147  writeHeader(buf, ibyte, FEBHead);
148  ibyte += ARICHFEB_HEADER_SIZE; // leave slot for FEB header (FEB header to be implemented!)
149 
150  // write data
151  for (const auto& digit : sortedDigits[moduleID - 1]) {
152  unsigned chn = digit->getChannelID();
153  //std::cout << "pack: mod: " << boardID << " ch " << chn<< std::endl;
154  unsigned shift = 143 - chn;
155  unsigned bitmap = (unsigned)digit->getBitmap();
156  buf[(ibyte + shift) / 4] += (bitmap << (3 - (ibyte + shift) % 4) * 8);
157  }
158  ibyte += 144;
159  } else {
160  FEBHead.length = ARICHFEB_HEADER_SIZE + sortedDigits[moduleID - 1].size() * 2; // each hit is 2 bytes! channel + bitmap
161  writeHeader(buf, ibyte, FEBHead);
162  ibyte += ARICHFEB_HEADER_SIZE; // leave slot for FEB header (FEB header to be implemented!)
163 
164  for (const auto& digit : sortedDigits[moduleID - 1]) {
165  unsigned chn = digit->getChannelID();
166  //std::cout << "pack: mod: " << boardID << " ch " << chn<< std::endl;
167  unsigned shift = (3 - ibyte % 4) * 8;
168  buf[ibyte / 4] += (chn << shift);
169  ibyte++;
170  shift = (3 - ibyte % 4) * 8;
171  unsigned bitmap = (unsigned)digit->getBitmap();
172  buf[ibyte / 4] += (bitmap << shift);
173  ibyte++;
174  }
175  }
176  }
177 
178  unsigned merg = 0;
179  mergerHead.length = ibyte - ARICHRAW_HEADER_SIZE;
180  writeHeader(buf, merg, mergerHead);
181 
182  bufferSize[finesse] = ceil(ibyte / 4.);
183 
184  if (m_debug) {
185  std::cout << "Pack finesse: " << finesse << std::endl;
186  for (int i = 0; i < bufferSize[finesse]; i++) {
187  std::cout << i << "-th word bitset " << bitset<32>(buf[i]) << std::endl;
188  }
189  }
190  }
191 
192  RawCOPPERPackerInfo info;
193  info.exp_num = evtMetaData->getExperiment();
194  info.run_subrun_num = (evtMetaData->getRun() << 8) +
195  (evtMetaData->getSubrun() & 0xFF); // run number : 14bits, subrun # : 8bits
196  info.eve_num = evtMetaData->getEvent();
197  info.node_id = ARICH_ID + copperID;
198  info.tt_ctime = 0;
199  info.tt_utime = 0;
200  info.b2l_ctime = 0;
201  info.hslb_crc16_error_bit = 0;
202  info.truncation_mask = 0;
203  info.type_of_data = 0;
204 
205  auto* raw = rawData.appendNew();
206  raw->PackDetectorBuf(buffer[0], bufferSize[0],
207  buffer[1], bufferSize[1],
208  buffer[2], bufferSize[2],
209  buffer[3], bufferSize[3],
210  info);
211 
212  }
213 
214  delete [] sortedDigits;
215 
216  }
217 
218  void ARICHPackerModule::writeHeader(int* buffer, unsigned& ibyte, const ARICHRawHeader& head)
219  {
220 
221  unsigned char line1[4];
222  int shift;
223 
224  line1[3] = head.type;
225  line1[2] = head.version;
226  line1[1] = head.mergerID;
227  line1[0] = head.FEBSlot;
228 
229  for (int i = 0; i < 4; i++) {
230  shift = (3 - ibyte % 4) * 8;
231  buffer[ibyte / 4] |= line1[3 - i] << shift;
232  ibyte++;
233  }
234 
235  auto len = reinterpret_cast<const unsigned char*>(&head.length);
236 
237  for (int i = 0; i < 4; i++) {
238  shift = (3 - ibyte % 4) * 8;
239  buffer[ibyte / 4] |= len[3 - i] << shift;
240  ibyte++;
241  }
242 
243  // trigger number
244  auto trg = reinterpret_cast<const unsigned char*>(&head.trigger);
245  for (int i = 0; i < 4; i++) {
246  shift = (3 - ibyte % 4) * 8;
247  buffer[ibyte / 4] |= trg[3 - i] << shift;
248  ibyte++;
249  }
250 
251  }
252 
253 
254 
255 
256  void ARICHPackerModule::endRun()
257  {
258  }
259 
260  void ARICHPackerModule::terminate()
261  {
262  }
263 
264 
266 } // end Belle2 namespace
267 
Raw data packer for ARICH.
Base class for Modules.
Definition: Module.h:72
struct to contain header information used by RawCOPPERFormat::Packer()
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:95
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.