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 countall = 0;
247  unsigned int countsel = 0;
248 
249  unsigned int countteall = 0;
250  unsigned int stubpairs = 0;
251 
252  unsigned int ntedata = 0;
253 
254  unsigned int ninnerstubs = 0;
255 
256  //Actual implemenation starts here
257 
258  //Reset the tebuffer
259  std::get<0>(tebuffer_).reset();
260  std::get<1>(tebuffer_) = 0;
261  std::get<2>(tebuffer_) = std::get<3>(tebuffer_);
262 
263  //Reset the teunits
264  for (auto& teunit : teunits_) {
265  teunit.reset();
266  }
267 
268  TEData tedata;
269  TEData tedata__;
270  TEData tedata___;
271  bool goodtedata = false;
272  bool goodtedata__ = false;
273  bool goodtedata___ = false;
274 
275  bool tebuffernearfull;
276 
277  for (unsigned int istep = 0; istep < maxStep_; istep++) {
278  // These print statements are not on by defaul but can be enabled for the
279  // comparison with HLS code to track differences.
280  if (print) {
281  CircularBuffer<TEData>& tedatabuffer = std::get<0>(tebuffer_);
282  unsigned int& istub = std::get<1>(tebuffer_);
283  unsigned int& imem = std::get<2>(tebuffer_);
284  cout << "istep=" << istep << " TEBuffer: " << istub << " " << imem << " " << tedatabuffer.rptr() << " "
285  << tedatabuffer.wptr();
286  int k = -1;
287  for (auto& teunit : teunits_) {
288  k++;
289  cout << " [" << k << " " << teunit.rptr() << " " << teunit.wptr() << " " << teunit.idle() << "]";
290  }
291  cout << endl;
292  }
293 
294  CircularBuffer<TEData>& tedatabuffer = std::get<0>(tebuffer_);
295  tebuffernearfull = tedatabuffer.nearfull();
296 
297  //
298  // First block here checks if there is a teunit with data that should should be used
299  // to calculate the tracklet parameters
300  //
301 
302  TrackletEngineUnit* teunitptr = nullptr;
303 
304  for (auto& teunit : teunits_) {
305  teunit.setNearFull();
306  if (!teunit.empty()) {
307  teunitptr = &teunit;
308  }
309  }
310 
311  if (teunitptr != nullptr) {
312  auto stubpair = teunitptr->read();
313  stubpairs++;
314 
316  edm::LogVerbatim("Tracklet") << "Will break on too many tracklets in " << getName();
317  break;
318  }
319  countall++;
320  const Stub* innerFPGAStub = stubpair.first;
321  const L1TStub* innerStub = innerFPGAStub->l1tstub();
322 
323  const Stub* outerFPGAStub = stubpair.second;
324  const L1TStub* outerStub = outerFPGAStub->l1tstub();
325 
326  if (settings_.debugTracklet()) {
327  edm::LogVerbatim("Tracklet") << "TrackletProcessor execute " << getName() << "[" << iSector_ << "]";
328  }
329 
330  bool accept = false;
331 
333  accept = barrelSeeding(innerFPGAStub, innerStub, outerFPGAStub, outerStub);
334  } else if (iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4) {
335  accept = diskSeeding(innerFPGAStub, innerStub, outerFPGAStub, outerStub);
336  } else {
337  accept = overlapSeeding(outerFPGAStub, outerStub, innerFPGAStub, innerStub);
338  }
339 
340  if (accept)
341  countsel++;
342 
344  edm::LogVerbatim("Tracklet") << "Will break on number of tracklets in " << getName();
345  assert(0);
346  break;
347  }
348 
349  if (settings_.debugTracklet()) {
350  edm::LogVerbatim("Tracklet") << "TrackletProcessor execute done";
351  }
352  }
353 
354  //
355  // The second block fills the teunit if data in buffer and process TEUnit step
356  //
357  //
358 
359  bool notemptytebuffer = !tedatabuffer.empty();
360 
361  int ite = -1;
362  for (auto& teunit : teunits_) {
363  ite++;
364  if (teunit.idle()) {
365  if (notemptytebuffer) {
366  teunit.init(std::get<0>(tebuffer_).read());
367  notemptytebuffer = false; //prevent initialzing another TE unit
368  }
369  }
370  teunit.step(print, istep, ite);
371  }
372 
373  //
374  // The third block here checks if we have input stubs to process
375  //
376  //
377 
378  if (goodtedata___)
379  tedatabuffer.store(tedata___);
380 
381  goodtedata = false;
382 
383  unsigned int& istub = std::get<1>(tebuffer_);
384  unsigned int& imem = std::get<2>(tebuffer_);
385  unsigned int imemend = std::get<4>(tebuffer_);
386 
387  if ((!tebuffernearfull) && imem < imemend && istub < innerallstubs_[imem]->nStubs()) {
388  ninnerstubs++;
389 
390  const Stub* stub = innerallstubs_[imem]->getStub(istub);
391 
392  if (settings_.debugTracklet()) {
393  edm::LogVerbatim("Tracklet") << getName() << " Have stub in " << innerallstubs_[imem]->getName();
394  }
395 
396  bool negdisk = (stub->disk().value() < 0); //FIXME stub needs to contain bit for +/- z disk
397 
398  FPGAWord phicorr = stub->phicorr();
399  int innerfinephi = phicorr.bits(phicorr.nbits() - nbitsfinephi_, nbitsfinephi_);
400  FPGAWord innerbend = stub->bend();
401 
402  //Take the top nbitszfinebintable_ bits of the z coordinate
403  int indexz = (stub->z().value() >> (stub->z().nbits() - nbitszfinebintable_)) & ((1 << nbitszfinebintable_) - 1);
404  int indexr = -1;
405  if (layerdisk1_ > (N_LAYER - 1)) {
406  if (negdisk) {
407  indexz = ((1 << nbitszfinebintable_) - 1) - indexz;
408  }
409  indexr = stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_);
410  } else { //Take the top nbitsfinebintable_ bits of the z coordinate
411  indexr = (stub->r().value() >> (stub->r().nbits() - nbitsrfinebintable_)) & ((1 << nbitsrfinebintable_) - 1);
412  }
413 
414  int lutval = -1;
415  if (iSeed_ < 6) { //FIXME should only be one table - but will need coordination with HLS code.
416  lutval = innerTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
417  } else {
418  lutval = innerOverlapTable_.lookup((indexz << nbitsrfinebintable_) + indexr);
419  }
420 
421  if (lutval != -1) {
422  unsigned int lutwidth = settings_.lutwidthtab(0, iSeed_);
423  FPGAWord lookupbits(lutval, lutwidth, true, __LINE__, __FILE__);
424 
425  int rzfinebinfirst = lookupbits.bits(0, NFINERZBITS); //finerz
426  int next = lookupbits.bits(NFINERZBITS, 1); //use next r/z bin
427  int start = lookupbits.bits(NFINERZBITS + 1, nbitsrzbin_); //rz bin
428  int rzdiffmax = lookupbits.bits(NFINERZBITS + 1 + nbitsrzbin_, NFINERZBITS);
429 
430  if ((iSeed_ == Seed::D1D2 || iSeed_ == Seed::D3D4) && negdisk) { //TODO - need to store negative disk
431  start += (1 << nbitsrzbin_);
432  }
433  int last = start + next;
434 
435  int nbins = (1 << N_RZBITS);
436 
437  unsigned int useregindex = (innerfinephi << innerbend.nbits()) + innerbend.value();
439  //FIXME If the lookupbits were rationally organized this would be much simpler
440  unsigned int nrbits = 3;
441  int ir = ((start & ((1 << (nrbits - 1)) - 1)) << 1) + (rzfinebinfirst >> (NFINERZBITS - 1));
442  useregindex = (useregindex << nrbits) + ir;
443  }
444 
445  unsigned int usereg = useregiontable_.lookup(useregindex);
446 
447  tedata.regions_.clear();
448  tedata.stub_ = stub;
449  tedata.rzbinfirst_ = rzfinebinfirst;
450  tedata.start_ = start;
451  tedata.innerfinephi_ = innerfinephi;
452  tedata.rzdiffmax_ = rzdiffmax;
453  tedata.innerbend_ = innerbend;
454 
455  std::string mask = "";
456 
457  for (int ibin = start; ibin <= last; ibin++) {
458  for (unsigned int ireg = 0; ireg < settings_.nvmte(1, iSeed_); ireg++) {
459  if (!(usereg & (1 << ireg))) {
460  mask = "0" + mask;
461  continue;
462  }
463 
464  if (settings_.debugTracklet()) {
465  edm::LogVerbatim("Tracklet") << getName() << " looking for matching stub in bin " << ibin << " with "
466  << outervmstubs_->nVMStubsBinned(ireg * nbins + ibin) << " stubs";
467  }
468  assert(ireg * nbins + ibin < outervmstubs_->nBin());
469  int nstubs = outervmstubs_->nVMStubsBinned(ireg * nbins + ibin);
470 
471  if (nstubs > 0) {
472  mask = "1" + mask;
473  tedata.regions_.emplace_back(tuple<int, int, int>(ibin - start, ireg, nstubs));
474  countteall += nstubs;
475  } else {
476  mask = "0" + mask;
477  }
478  }
479  }
480 
481  if (!tedata.regions_.empty()) {
482  ntedata++;
483  goodtedata = true;
484  }
485  }
486  istub++;
487  if (istub >= innerallstubs_[imem]->nStubs()) {
488  istub = 0;
489  imem++;
490  }
491  } else if ((!tebuffernearfull) && imem < imemend && istub == 0) {
492  imem++;
493  }
494 
495  goodtedata___ = goodtedata__;
496  goodtedata__ = goodtedata;
497 
498  tedata___ = tedata__;
499  tedata__ = tedata;
500 
501  //
502  // stop looping over istep if done
503  //
504 
505  bool done = true;
506 
507  if (imem < imemend || (!tedatabuffer.empty())) {
508  done = false;
509  }
510 
511  for (auto& teunit : teunits_) {
512  if (!(teunit.idle() && teunit.empty()))
513  done = false;
514  }
515 
516  if (done) {
517  donecount++;
518  }
519 
520  //FIXME This should be done cleaner... Not too hard, but need to check fully the TEBuffer and TEUnit buffer.
521  if (donecount > 4) {
522  break;
523  }
524  }
525 
526  //
527  // Done with processing - collect performance statistics
528  //
529 
530  if (settings_.writeMonitorData("TP")) {
531  globals_->ofstream("trackletprocessor.txt") << getName() << " " << ninnerstubs //# inner stubs
532  << " " << outervmstubs_->nVMStubs() //# outer stubs
533  << " " << countteall //# pairs tried in TE
534  << " " << stubpairs //# stubs pairs
535  << " " << countsel //# tracklets found
536  << endl;
537  }
538 }
void execute(unsigned int iSector, double phimin, double phimax)
size
Write out results.
Definition: start.py:1
unsigned int vmrlutrbits(unsigned int layerdisk) const
Definition: Settings.h:179
Log< level::Info, true > LogVerbatim
constexpr unsigned int N_RZBITS
Definition: Settings.h:35
const std::pair< const Stub *, const Stub * > & read()
constexpr int N_DISK
Definition: Settings.h:22
unsigned int maxStep(std::string module) const
Definition: Settings.h:116
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:140
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:292
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
Definition: TrackletLUT.cc:904
bool writetrace() const
Definition: Settings.h:183
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:106
double rmean(unsigned int iLayer) const
Definition: Settings.h:164
Divides< A, C > D1
Definition: Factorize.h:136
unsigned int nbitsvmte(unsigned int inner, unsigned int iSeed) const
Definition: Settings.h:95
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:109
double zmean(unsigned int iDisk) const
Definition: Settings.h:167
std::vector< AllInnerStubsMemory * > innerallstubs_
unsigned int nvmte(unsigned int inner, unsigned int iSeed) const
Definition: Settings.h:101
constexpr unsigned int NFINERZBITS
Definition: Settings.h:33
std::vector< std::vector< TrackletProjectionsMemory * > > trackletprojdisks_
unsigned int nallstubs(unsigned int layerdisk) const
Definition: Settings.h:107
bool debugTracklet() const
Definition: Settings.h:182
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:64
int nfinephi(unsigned int inner, unsigned int iSeed) const
Definition: Settings.h:133
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:184
bool useSeed(unsigned int iSeed) const
Definition: Settings.h:94
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:151
const Stub * stub_
std::ofstream & ofstream(std::string fname)
Definition: Globals.cc:44
double rmaxdiskvm() const
Definition: Settings.h:328
unsigned int ntrackletmax() const
Definition: Settings.h:343
Definition: output.py:1
double maxrinv() const
Definition: Settings.h:319
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:493
unsigned int vmrlutzbits(unsigned int layerdisk) const
Definition: Settings.h:178
constexpr int N_LAYER
Definition: Settings.h:21
bool barrelSeeding(const Stub *innerFPGAStub, const L1TStub *innerStub, const Stub *outerFPGAStub, const L1TStub *outerStub)
double rmaxdiskl1overlapvm() const
Definition: Settings.h:330
std::vector< std::tuple< int, int, int > > regions_