CMS 3D CMS Logo

TrackletProcessor.cc
Go to the documentation of this file.
8 
12 
13 #include <utility>
14 #include <tuple>
15 
16 using namespace std;
17 using namespace trklet;
18 
19 TrackletProcessor::TrackletProcessor(string name, Settings const& settings, Globals* globals)
20  : TrackletCalculatorBase(name, settings, globals),
21  tebuffer_(CircularBuffer<TEData>(3), 0, 0, 0, 0),
22  pttableinner_(settings),
23  pttableouter_(settings),
24  useregiontable_(settings),
25  innerTable_(settings),
26  innerOverlapTable_(settings) {
27  iAllStub_ = -1;
28 
29  for (unsigned int ilayer = 0; ilayer < N_LAYER; ilayer++) {
30  vector<TrackletProjectionsMemory*> tmp(settings_.nallstubs(ilayer), nullptr);
31  trackletprojlayers_.push_back(tmp);
32  }
33 
34  for (unsigned int idisk = 0; idisk < N_DISK; idisk++) {
35  vector<TrackletProjectionsMemory*> tmp(settings_.nallstubs(idisk + N_LAYER), nullptr);
36  trackletprojdisks_.push_back(tmp);
37  }
38 
39  outervmstubs_ = nullptr;
40 
42 
43  double rmin = -1.0;
44  double rmax = -1.0;
45 
47  rmin = settings_.rmean(layerdisk1_);
48  rmax = settings_.rmean(layerdisk2_);
49  } else {
50  if (iSeed_ == Seed::L1D1) {
52  rmin = settings_.rmean(layerdisk1_);
53  } else if (iSeed_ == Seed::L2D1) {
54  rmax = settings_.rmaxdiskvm();
55  rmin = settings_.rmean(layerdisk1_);
56  } else {
57  rmax = settings_.rmaxdiskvm();
59  }
60  }
61 
62  double dphimax = asin(0.5 * settings_.maxrinv() * rmax) - asin(0.5 * settings_.maxrinv() * rmin);
63 
64  //number of fine phi bins in sector
65  int nfinephibins =
67  double dfinephi = settings_.dphisectorHG() / nfinephibins;
68 
70 
71  int nbins = 2.0 * (dphimax / dfinephi + 1.0);
72 
73  nbitsfinephidiff_ = log(nbins) / log(2.0) + 1;
74 
77 
79  if (iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4)
80  nbitsrzbin_ = 2;
81 
84 
87  innerTable_.initVMRTable(layerdisk1_, TrackletLUT::VMRTableType::inner); //projection to next layer/disk
88  }
89 
92  TrackletLUT::VMRTableType::inneroverlap); //projection to disk from layer
93  }
94 
95  // set TC index
96  iTC_ = name_[7] - 'A';
97  assert(iTC_ >= 0 && iTC_ < 14);
98 
99  TCIndex_ = (iSeed_ << 4) + iTC_;
100  assert(TCIndex_ >= 0 && TCIndex_ <= (int)settings_.ntrackletmax());
101 
102  maxStep_ = settings_.maxStep("TP");
103 }
104 
106  outputProj = dynamic_cast<TrackletProjectionsMemory*>(memory);
107  assert(outputProj != nullptr);
108 }
109 
111  if (settings_.writetrace()) {
112  edm::LogVerbatim("Tracklet") << "In " << name_ << " adding output to " << memory->getName() << " to output "
113  << output;
114  }
115  if (output == "trackpar") {
116  auto* tmp = dynamic_cast<TrackletParametersMemory*>(memory);
117  assert(tmp != nullptr);
118  trackletpars_ = tmp;
119  return;
120  }
121 
122  if (output.substr(0, 7) == "projout") {
123  //output is on the form 'projoutL2PHIC' or 'projoutD3PHIB'
124  auto* tmp = dynamic_cast<TrackletProjectionsMemory*>(memory);
125  assert(tmp != nullptr);
126 
127  unsigned int layerdisk = output[8] - '1'; //layer or disk counting from 0
128  unsigned int phiregion = output[12] - 'A'; //phiregion counting from 0
129 
130  if (output[7] == 'L') {
131  assert(layerdisk < N_LAYER);
132  assert(phiregion < trackletprojlayers_[layerdisk].size());
133  //check that phiregion not already initialized
134  assert(trackletprojlayers_[layerdisk][phiregion] == nullptr);
135  trackletprojlayers_[layerdisk][phiregion] = tmp;
136  return;
137  }
138 
139  if (output[7] == 'D') {
140  assert(layerdisk < N_DISK);
141  assert(phiregion < trackletprojdisks_[layerdisk].size());
142  //check that phiregion not already initialized
143  assert(trackletprojdisks_[layerdisk][phiregion] == nullptr);
144  trackletprojdisks_[layerdisk][phiregion] = tmp;
145  return;
146  }
147  }
148 
149  throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find output : " << output;
150 }
151 
153  if (settings_.writetrace()) {
154  edm::LogVerbatim("Tracklet") << "In " << name_ << " adding input from " << memory->getName() << " to input "
155  << input;
156  }
157 
158  if (input == "outervmstubin") {
159  auto* tmp = dynamic_cast<VMStubsTEMemory*>(memory);
160  assert(tmp != nullptr);
161  outervmstubs_ = tmp;
162  iAllStub_ = tmp->getName()[11] - 'A';
163  if (iSeed_ == Seed::L2L3)
164  iAllStub_ = tmp->getName()[11] - 'I';
165  if (iSeed_ == Seed::L1D1 || iSeed_ == Seed::L2D1) {
166  if (tmp->getName()[11] == 'X')
167  iAllStub_ = 0;
168  if (tmp->getName()[11] == 'Y')
169  iAllStub_ = 1;
170  if (tmp->getName()[11] == 'Z')
171  iAllStub_ = 2;
172  if (tmp->getName()[11] == 'W')
173  iAllStub_ = 3;
174  }
175 
176  unsigned int iTP = getName()[7] - 'A';
177 
180 
181  //need iAllStub_ set before building the table
182 
185 
188  layerdisk1_,
189  layerdisk2_,
190  iSeed_,
192  iAllStub_,
193  &pttableinner_,
194  &pttableouter_,
195  outervmstubs_);
196 
197  teunits_.resize(settings_.teunits(iSeed_), teunit);
198 
199  return;
200  }
201 
202  if (input == "innerallstubin") {
203  auto* tmp = dynamic_cast<AllInnerStubsMemory*>(memory);
204  assert(tmp != nullptr);
205  if (innerallstubs_.size() == 2) { //FIXME this should be done with better logic with reading the input stubs
206  innerallstubs_.insert(innerallstubs_.begin(), tmp);
207  } else {
208  innerallstubs_.push_back(tmp);
209  }
210 
211  //FIXME should be done once after all inputs are added
212  tebuffer_ = tuple<CircularBuffer<TEData>, unsigned int, unsigned int, unsigned int, unsigned int>(
213  CircularBuffer<TEData>(3), 0, 0, 0, innerallstubs_.size());
214 
215  return;
216  }
217  if (input == "outerallstubin") {
218  auto* tmp = dynamic_cast<AllStubsMemory*>(memory);
219  assert(tmp != nullptr);
220  outerallstubs_.push_back(tmp);
221  return;
222  }
223  throw cms::Exception("BadConfig") << __FILE__ << " " << __LINE__ << " Could not find input : " << input;
224 }
225 
226 void TrackletProcessor::execute(unsigned int iSector, double phimin, double phimax) {
227  bool print = (iSector == 3) && (getName() == "TP_L1L2D");
228  print = false;
229 
230  phimin_ = phimin;
231  phimax_ = phimax;
232  iSector_ = iSector;
233 
234  if (!settings_.useSeed(iSeed_))
235  return;
236 
237  //Not most elegant solution; but works
238  int donecount = 0;
239 
240  //Consistency checks
241  assert(iAllStub_ >= 0);
243  assert(outervmstubs_ != nullptr);
244 
245  //used to collect performance data
246  unsigned int countsel = 0;
247 
248  unsigned int countteall = 0;
249  unsigned int stubpairs = 0;
250 
251  unsigned int ninnerstubs = 0;
252 
253  //Actual implemenation starts here
254 
255  //Reset the tebuffer
256  std::get<0>(tebuffer_).reset();
257  std::get<1>(tebuffer_) = 0;
258  std::get<2>(tebuffer_) = std::get<3>(tebuffer_);
259 
260  //Reset the teunits
261  for (auto& teunit : teunits_) {
262  teunit.reset();
263  }
264 
265  TEData tedata;
266  TEData tedata__;
267  TEData tedata___;
268  bool goodtedata = false;
269  bool goodtedata__ = false;
270  bool goodtedata___ = false;
271 
272  bool tebuffernearfull;
273 
274  for (unsigned int istep = 0; istep < maxStep_; istep++) {
275  // These print statements are not on by defaul but can be enabled for the
276  // comparison with HLS code to track differences.
277  if (print) {
278  CircularBuffer<TEData>& tedatabuffer = std::get<0>(tebuffer_);
279  unsigned int& istub = std::get<1>(tebuffer_);
280  unsigned int& imem = std::get<2>(tebuffer_);
281  cout << "istep=" << istep << " TEBuffer: " << istub << " " << imem << " " << tedatabuffer.rptr() << " "
282  << tedatabuffer.wptr();
283  int k = -1;
284  for (auto& teunit : teunits_) {
285  k++;
286  cout << " [" << k << " " << teunit.rptr() << " " << teunit.wptr() << " " << teunit.idle() << "]";
287  }
288  cout << endl;
289  }
290 
291  CircularBuffer<TEData>& tedatabuffer = std::get<0>(tebuffer_);
292  tebuffernearfull = tedatabuffer.nearfull();
293 
294  //
295  // First block here checks if there is a teunit with data that should should be used
296  // to calculate the tracklet parameters
297  //
298 
299  TrackletEngineUnit* teunitptr = nullptr;
300 
301  for (auto& teunit : teunits_) {
302  teunit.setNearFull();
303  if (!teunit.empty()) {
304  teunitptr = &teunit;
305  }
306  }
307 
308  if (teunitptr != nullptr) {
309  auto stubpair = teunitptr->read();
310  stubpairs++;
311 
313  edm::LogVerbatim("Tracklet") << "Will break on too many tracklets in " << getName();
314  break;
315  }
316  const Stub* innerFPGAStub = stubpair.first;
317  const L1TStub* innerStub = innerFPGAStub->l1tstub();
318 
319  const Stub* outerFPGAStub = stubpair.second;
320  const L1TStub* outerStub = outerFPGAStub->l1tstub();
321 
322  if (settings_.debugTracklet()) {
323  edm::LogVerbatim("Tracklet") << "TrackletProcessor execute " << getName() << "[" << iSector_ << "]";
324  }
325 
326  bool accept = false;
327 
329  accept = barrelSeeding(innerFPGAStub, innerStub, outerFPGAStub, outerStub);
330  } else if (iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4) {
331  accept = diskSeeding(innerFPGAStub, innerStub, outerFPGAStub, outerStub);
332  } else {
333  accept = overlapSeeding(outerFPGAStub, outerStub, innerFPGAStub, innerStub);
334  }
335 
336  if (accept)
337  countsel++;
338 
340  edm::LogVerbatim("Tracklet") << "Will break on number of tracklets in " << getName();
341  assert(0);
342  break;
343  }
344 
345  if (settings_.debugTracklet()) {
346  edm::LogVerbatim("Tracklet") << "TrackletProcessor execute done";
347  }
348  }
349 
350  //
351  // The second block fills the teunit if data in buffer and process TEUnit step
352  //
353  //
354 
355  bool notemptytebuffer = !tedatabuffer.empty();
356 
357  int ite = -1;
358  for (auto& teunit : teunits_) {
359  ite++;
360  if (teunit.idle()) {
361  if (notemptytebuffer) {
362  teunit.init(std::get<0>(tebuffer_).read());
363  notemptytebuffer = false; //prevent initialzing another TE unit
364  }
365  }
366  teunit.step(print, istep, ite);
367  }
368 
369  //
370  // The third block here checks if we have input stubs to process
371  //
372  //
373 
374  if (goodtedata___)
375  tedatabuffer.store(tedata___);
376 
377  goodtedata = false;
378 
379  unsigned int& istub = std::get<1>(tebuffer_);
380  unsigned int& imem = std::get<2>(tebuffer_);
381  unsigned int imemend = std::get<4>(tebuffer_);
382 
383  if ((!tebuffernearfull) && imem < imemend && istub < innerallstubs_[imem]->nStubs()) {
384  ninnerstubs++;
385 
386  const Stub* stub = innerallstubs_[imem]->getStub(istub);
387 
388  if (settings_.debugTracklet()) {
389  edm::LogVerbatim("Tracklet") << getName() << " Have stub in " << innerallstubs_[imem]->getName();
390  }
391 
392  bool negdisk = (stub->disk().value() < 0); //FIXME stub needs to contain bit for +/- z disk
393 
394  FPGAWord phicorr = stub->phicorr();
395  int innerfinephi = phicorr.bits(phicorr.nbits() - nbitsfinephi_, nbitsfinephi_);
396  FPGAWord innerbend = stub->bend();
397 
398  //Take the top nbitszfinebintable_ bits of the z coordinate
399  int indexz = (stub->z().value() >> (stub->z().nbits() - nbitszfinebintable_)) & ((1 << nbitszfinebintable_) - 1);
400  int indexr = -1;
401  if (layerdisk1_ > (N_LAYER - 1)) {
402  if (negdisk) {
403  indexz = ((1 << nbitszfinebintable_) - 1) - indexz;
404  }
405  indexr = stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_);
406  } else { //Take the top nbitsfinebintable_ bits of the z coordinate
407  indexr = (stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_)) & ((1 << nbitsrfinebintable_) - 1);
408  }
409 
410  int lutval = -1;
411  if (iSeed_ < 6) { //FIXME should only be one table - but will need coordination with HLS code.
412  lutval = innerTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
413  } else {
414  lutval = innerOverlapTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
415  }
416 
417  if (lutval != -1) {
418  unsigned int lutwidth = settings_.lutwidthtab(0, iSeed_);
419  FPGAWord lookupbits(lutval, lutwidth, true, __LINE__, __FILE__);
420 
421  int rzfinebinfirst = lookupbits.bits(0, NFINERZBITS); //finerz
422  int next = lookupbits.bits(NFINERZBITS, 1); //use next r/z bin
423  int start = lookupbits.bits(NFINERZBITS + 1, nbitsrzbin_); //rz bin
424  int rzdiffmax = lookupbits.bits(NFINERZBITS + 1 + nbitsrzbin_, NFINERZBITS);
425 
426  if ((iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4) && negdisk) { //TODO - need to store negative disk
427  start += (1 << nbitsrzbin_);
428  }
429  int last = start + next;
430 
431  int nbins = (1 << N_RZBITS);
432 
433  unsigned int useregindex = (innerfinephi << innerbend.nbits()) + innerbend.value();
435  //FIXME If the lookupbits were rationally organized this would be much simpler
436  unsigned int nrbits = 3;
437  int ir = ((start & ((1 << (nrbits - 1)) - 1)) << 1) + (rzfinebinfirst >> (NFINERZBITS - 1));
438  useregindex = (useregindex << nrbits) + ir;
439  }
440 
441  unsigned int usereg = useregiontable_.lookup(useregindex);
442 
443  tedata.regions_.clear();
444  tedata.stub_ = stub;
445  tedata.rzbinfirst_ = rzfinebinfirst;
446  tedata.start_ = start;
447  tedata.innerfinephi_ = innerfinephi;
448  tedata.rzdiffmax_ = rzdiffmax;
449  tedata.innerbend_ = innerbend;
450 
451  std::string mask = "";
452 
453  for (int ibin = start; ibin <= last; ibin++) {
454  for (unsigned int ireg = 0; ireg < settings_.nvmte(1, iSeed_); ireg++) {
455  if (!(usereg & (1 << ireg))) {
456  mask = "0" + mask;
457  continue;
458  }
459 
460  if (settings_.debugTracklet()) {
461  edm::LogVerbatim("Tracklet") << getName() << " looking for matching stub in bin " << ibin << " with "
462  << outervmstubs_->nVMStubsBinned(ireg * nbins + ibin) << " stubs";
463  }
464  assert(ireg * nbins + ibin < outervmstubs_->nBin());
465  int nstubs = outervmstubs_->nVMStubsBinned(ireg * nbins + ibin);
466 
467  if (nstubs > 0) {
468  mask = "1" + mask;
469  tedata.regions_.emplace_back(tuple<int, int, int>(ibin - start, ireg, nstubs));
470  countteall += nstubs;
471  } else {
472  mask = "0" + mask;
473  }
474  }
475  }
476 
477  if (!tedata.regions_.empty()) {
478  goodtedata = true;
479  }
480  }
481  istub++;
482  if (istub >= innerallstubs_[imem]->nStubs()) {
483  istub = 0;
484  imem++;
485  }
486  } else if ((!tebuffernearfull) && imem < imemend && istub == 0) {
487  imem++;
488  }
489 
490  goodtedata___ = goodtedata__;
491  goodtedata__ = goodtedata;
492 
493  tedata___ = tedata__;
494  tedata__ = tedata;
495 
496  //
497  // stop looping over istep if done
498  //
499 
500  bool done = true;
501 
502  if (imem < imemend || (!tedatabuffer.empty())) {
503  done = false;
504  }
505 
506  for (auto& teunit : teunits_) {
507  if (!(teunit.idle() && teunit.empty()))
508  done = false;
509  }
510 
511  if (done) {
512  donecount++;
513  }
514 
515  //FIXME This should be done cleaner... Not too hard, but need to check fully the TEBuffer and TEUnit buffer.
516  if (donecount > 4) {
517  break;
518  }
519  }
520 
521  //
522  // Done with processing - collect performance statistics
523  //
524 
525  if (settings_.writeMonitorData("TP")) {
526  globals_->ofstream("trackletprocessor.txt") << getName() << " " << ninnerstubs //# inner stubs
527  << " " << outervmstubs_->nVMStubs() //# outer stubs
528  << " " << countteall //# pairs tried in TE
529  << " " << stubpairs //# stubs pairs
530  << " " << countsel //# tracklets found
531  << endl;
532  }
533 }
void execute(unsigned int iSector, double phimin, double phimax)
Definition: start.py:1
unsigned int vmrlutrbits(unsigned int layerdisk) const
Definition: Settings.h:189
Log< level::Info, true > LogVerbatim
constexpr unsigned int N_RZBITS
Definition: Settings.h:39
const std::pair< const Stub *, const Stub * > & read()
constexpr int N_DISK
Definition: Settings.h:26
unsigned int maxStep(std::string module) const
Definition: Settings.h:123
bool diskSeeding(const Stub *innerFPGAStub, const L1TStub *innerStub, const Stub *outerFPGAStub, const L1TStub *outerStub)
const FPGAWord & r() const
Definition: Stub.h:60
double lutwidthtab(unsigned int inner, unsigned int iSeed) const
Definition: Settings.h:147
std::string name_
Definition: ProcessBase.h:38
unsigned int rptr() const
unsigned int wptr() const
const FPGAWord & z() const
Definition: Stub.h:61
double dphisectorHG() const
Definition: Settings.h:314
void addInput(MemoryBase *memory, std::string input) override
void initLayerDisksandISeed(unsigned int &layerdisk1, unsigned int &layerdisk2, unsigned int &iSeed)
Definition: ProcessBase.cc:63
Settings const & settings_
Definition: ProcessBase.h:40
Globals * globals_
Definition: ProcessBase.h:41
int lookup(unsigned int index) const
bool writetrace() const
Definition: Settings.h:193
const FPGAWord & bend() const
Definition: Stub.h:58
std::vector< AllStubsMemory * > outerallstubs_
assert(be >=bs)
bool accept(const edm::Event &event, const edm::TriggerResults &triggerTable, const std::string &triggerPath)
Definition: TopDQMHelpers.h:31
void addOutputProjection(TrackletProjectionsMemory *&outputProj, MemoryBase *memory)
constexpr uint32_t mask
Definition: gpuClustering.h:26
static std::string const input
Definition: EdmProvDump.cc:50
const FPGAWord & disk() const
Definition: Stub.h:68
std::vector< TrackletEngineUnit > teunits_
bool overlapSeeding(const Stub *innerFPGAStub, const L1TStub *innerStub, const Stub *outerFPGAStub, const L1TStub *outerStub)
std::tuple< CircularBuffer< TEData >, unsigned int, unsigned int, unsigned int, unsigned int > tebuffer_
unsigned int nbitsallstubs(unsigned int layerdisk) const
Definition: Settings.h:113
double rmean(unsigned int iLayer) const
Definition: Settings.h:171
Divides< A, C > D1
Definition: Factorize.h:136
unsigned int nbitsvmte(unsigned int inner, unsigned int iSeed) const
Definition: Settings.h:102
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
int value() const
Definition: FPGAWord.h:24
VMStubsTEMemory * outervmstubs_
void store(T element)
L1TStub * l1tstub()
Definition: Stub.h:77
TrackletParametersMemory * trackletpars_
void addOutput(MemoryBase *memory, std::string output) override
bool writeMonitorData(std::string module) const
Definition: Settings.h:116
double zmean(unsigned int iDisk) const
Definition: Settings.h:174
std::vector< AllInnerStubsMemory * > innerallstubs_
unsigned int nvmte(unsigned int inner, unsigned int iSeed) const
Definition: Settings.h:108
constexpr unsigned int NFINERZBITS
Definition: Settings.h:37
std::vector< std::vector< TrackletProjectionsMemory * > > trackletprojdisks_
unsigned int nallstubs(unsigned int layerdisk) const
Definition: Settings.h:114
bool debugTracklet() const
Definition: Settings.h:192
unsigned int nVMStubs() const
std::vector< std::vector< TrackletProjectionsMemory * > > trackletprojlayers_
int nbits() const
Definition: FPGAWord.h:25
void initTPlut(bool fillInner, unsigned int iSeed, unsigned int layerdisk1, unsigned int layerdisk2, unsigned int nbitsfinephidiff, unsigned int iTP)
Definition: TrackletLUT.cc:275
int nfinephi(unsigned int inner, unsigned int iSeed) const
Definition: Settings.h:140
void initTPregionlut(unsigned int iSeed, unsigned int layerdisk1, unsigned int layerdisk2, unsigned int iAllStub, unsigned int nbitsfinephidiff, unsigned int nbitsfinephi, const TrackletLUT &tplutinner, unsigned int iTP)
Definition: TrackletLUT.cc:491
bool useSeed(unsigned int iSeed) const
Definition: Settings.h:101
const FPGAWord & phicorr() const
Definition: Stub.h:63
unsigned int nVMStubsBinned(unsigned int bin) const
unsigned int teunits(unsigned int iSeed) const
Definition: Settings.h:158
const Stub * stub_
std::ofstream & ofstream(std::string fname)
Definition: Globals.cc:44
double rmaxdiskvm() const
Definition: Settings.h:350
unsigned int ntrackletmax() const
Definition: Settings.h:365
Definition: output.py:1
double maxrinv() const
Definition: Settings.h:341
unsigned int bits(unsigned int lsb, unsigned int nbit) const
Definition: FPGAWord.cc:74
tmp
align.sh
Definition: createJobs.py:716
std::string const & getName() const
Definition: ProcessBase.h:22
void reset(double vett[256])
Definition: TPedValues.cc:11
void initVMRTable(unsigned int layerdisk, VMRTableType type, int region=-1)
Definition: TrackletLUT.cc:984
unsigned int vmrlutzbits(unsigned int layerdisk) const
Definition: Settings.h:188
constexpr int N_LAYER
Definition: Settings.h:25
bool barrelSeeding(const Stub *innerFPGAStub, const L1TStub *innerStub, const Stub *outerFPGAStub, const L1TStub *outerStub)
double rmaxdiskl1overlapvm() const
Definition: Settings.h:352
std::vector< std::tuple< int, int, int > > regions_