CMS 3D CMS Logo

imath.cc
Go to the documentation of this file.
1 //
2 // Integer representation of floating point arithmetic suitable for FPGA designs
3 //
4 // Author: Yuri Gershtein
5 // Date: March 2018
6 //
7 
9 
11 
12 #include <cmath>
13 
14 using namespace trklet;
15 
17 
19  char s[1024];
20  std::string t = "";
21  for (const auto &Kmap : Kmap_) {
22  sprintf(s, "^(%i)", Kmap.second);
23  std::string t0(s);
24  t = t + Kmap.first + t0;
25  }
26  return t;
27 }
28 
30  if (!readytoanalyze_)
31  return;
32 
33  double u = maxval_;
34  if (u < -minval_)
35  u = -minval_;
36 
37  int iu = log2(range() / u);
38  if (iu > 1) {
39  char slog[1024];
40  sprintf(slog,
41  "analyzing %s: range %g is much larger then %g. suggest cutting by a factor of 2^%i",
42  name_.c_str(),
43  range(),
44  u,
45  iu);
46  edm::LogVerbatim("Tracklet") << slog;
47  }
48 #ifdef IMATH_ROOT
49  char slog[100];
50  if (h_) {
51  double eff = h_->Integral() / h_->GetEntries();
52  if (eff < 0.99) {
53  sprintf(slog, "analyzing %s: range is too small, contains %f", name_.c_str(), eff);
54  edm::LogVerbatim("Tracklet") << slog;
55  h_->Print();
56  }
57  globals_->h_file_->cd();
58  TCanvas *c = new TCanvas();
59  c->cd();
60  h_->Draw("colz");
61  h_->Write();
62  } else {
63  if (globals_->use_root) {
64  sprintf(slog, "analyzing %s: no histogram!\n", name_.c_str());
65  edm::LogVerbatim("Tracklet") << slog;
66  }
67  }
68 #endif
69 
70  if (p1_)
71  p1_->analyze();
72  if (p2_)
73  p2_->analyze();
74 
75  readytoanalyze_ = false;
76 }
77 
79  char s[1024];
80  std::string u = kstring();
81  sprintf(
82  s,
83  "Name = %s \t Op = %s \t nbits = %i \n ival = %li \t fval = %g \t K = %g Range = %f\n units = %s\n",
84  name_.c_str(),
85  op_.c_str(),
86  nbits_,
87  ival_,
88  fval_,
89  K_,
90  range(),
91  u.c_str());
92  std::string t(s);
93  return t;
94 }
95 
97  char s[2048];
98  std::string u = kstring();
99  sprintf(s,
100  "Name = %s \t Op = %s \t nbits = %i \n ival = %li \t fval = %g \t K = %g Range = %f\n units = "
101  "%s\n step = %i, latency = %i\n",
102  name_.c_str(),
103  op_.c_str(),
104  nbits_,
105  ival_,
106  fval_,
107  K_,
108  range(),
109  u.c_str(),
110  step_,
111  latency_);
112  std::string t(s);
113  edm::LogVerbatim("Tracklet") << t;
114  if (p1_)
115  p1_->dump_msg();
116  if (p2_)
117  p2_->dump_msg();
118 }
119 
120 void VarAdjustK::adjust(double Knew, double epsilon, bool do_assert, int nbits) {
121  //WARNING!!!
122  //THIS METHID CAN BE USED ONLY FOR THE FINAL ANSWER
123  //THE CHANGE IN CONSTANT CAN NOT BE PROPAGATED UP THE CALCULATION TREE
124 
125  K_ = p1_->K();
126  Kmap_ = p1_->Kmap();
127  double r = Knew / K_;
128 
129  lr_ = (r > 1) ? log2(r) + epsilon : log2(r);
130  K_ = K_ * pow(2, lr_);
131  if (do_assert)
132  assert(std::abs(Knew / K_ - 1) < epsilon);
133 
134  if (nbits > 0)
135  nbits_ = nbits;
136  else
137  nbits_ = p1_->nbits() - lr_;
138 
139  Kmap_["2"] = Kmap_["2"] + lr_;
140 }
141 
142 void VarInv::initLUT(double offset) {
143  offset_ = offset;
144  double offsetI = lround(offset_ / p1_->K());
145  for (int i = 0; i < Nelements_; ++i) {
146  int i1 = addr_to_ival(i);
147  LUT[i] = gen_inv(offsetI + i1);
148  }
149 }
150 
152  pipe_counter_ = 0;
153  pipe_delays_.clear();
154  readytoprint_ = true;
155  readytoanalyze_ = true;
156  usedasinput_ = false;
157  if (p1_)
158  p1_->makeready();
159  if (p2_)
160  p2_->makeready();
161  if (p3_)
162  p3_->makeready();
163 }
164 
166  //dumb sequential search
167  for (int pipe_delay : pipe_delays_)
168  if (pipe_delay == i)
169  return true;
170  return false;
171 }
172 
174  //have we been delayed by this much already?
175  if (v->has_delay(delay))
176  return "";
177  v->add_delay(delay);
178  std::string name = v->name();
179  std::string name_delayed = name + "_delay" + itos(delay);
180  std::string out = "wire signed [" + itos(nbits - 1) + ":0] " + name_delayed + ";\n";
181  out = out + pipe_delay_wire(v, name_delayed, nbits, delay);
182  return out;
183 }
185  std::string out = "";
186  if (p1_)
187  out += p1_->pipe_delays(step);
188  if (p2_)
189  out += p2_->pipe_delays(step);
190  if (p3_)
191  out += p3_->pipe_delays(step);
192 
193  int l = step - latency_ - step_;
194  return (out + pipe_delay(this, nbits(), l));
195 }
197  std::string name = v->name();
198  std::string name_pipe = name + "_pipe" + itos(v->pipe_counter());
199  v->pipe_increment();
200  std::string out = "pipe_delay #(.STAGES(" + itos(delay) + "), .WIDTH(" + itos(nbits) + ")) " + name_pipe +
201  "(.clk(clk), .val_in(" + name + "), .val_out(" + name_delayed + "));\n";
202  return out;
203 }
204 
205 void VarBase::inputs(std::vector<VarBase *> *vd) {
206  if (op_ == "def" && !usedasinput_) {
207  usedasinput_ = true;
208  vd->push_back(this);
209  } else {
210  if (p1_)
211  p1_->inputs(vd);
212  if (p2_)
213  p2_->inputs(vd);
214  if (p3_)
215  p3_->inputs(vd);
216  }
217 }
218 
219 #ifdef IMATH_ROOT
220 TTree *VarBase::addToTree(imathGlobals *globals, VarBase *v, char *s) {
221  if (globals->h_file_ == 0) {
222  globals->h_file_ = new TFile("imath.root", "RECREATE");
223  edm::LogVerbatim("Tracklet") << "recreating file imath.root";
224  }
225  globals->h_file_->cd();
226  TTree *tt = (TTree *)globals->h_file_->Get("tt");
227  if (tt == 0) {
228  tt = new TTree("tt", "");
229  edm::LogVerbatim("Tracklet") << "creating TTree tt";
230  }
231  std::string si = v->name() + "_i";
232  std::string sf = v->name() + "_f";
233  std::string sv = v->name();
234  if (s != 0) {
236  si = prefix + si;
237  sf = prefix + sf;
238  sv = prefix + sv;
239  }
240  if (!tt->GetBranchStatus(si.c_str())) {
241  tt->Branch(si.c_str(), (Long64_t *)&(v->ival_));
242  tt->Branch(sf.c_str(), &(v->fval_));
243  tt->Branch(sv.c_str(), &(v->val_));
244  }
245 
246  if (v->p1_)
247  addToTree(globals, v->p1_, s);
248  if (v->p2_)
249  addToTree(globals, v->p2_, s);
250  if (v->p3_)
251  addToTree(globals, v->p3_, s);
252 
253  return tt;
254 }
255 TTree *VarBase::addToTree(imathGlobals *globals, double *v, char *s) {
256  if (globals->h_file_ == 0) {
257  globals->h_file_ = new TFile("imath.root", "RECREATE");
258  edm::LogVerbatim("Tracklet") << "recreating file imath.root";
259  }
260  globals->h_file_->cd();
261  TTree *tt = (TTree *)globals->h_file_->Get("tt");
262  if (tt == 0) {
263  tt = new TTree("tt", "");
264  edm::LogVerbatim("Tracklet") << "creating TTree tt";
265  }
266  tt->Branch(s, v);
267  return tt;
268 }
269 TTree *VarBase::addToTree(imathGlobals *globals, int *v, char *s) {
270  if (globals->h_file_ == 0) {
271  globals->h_file_ = new TFile("imath.root", "RECREATE");
272  edm::LogVerbatim("Tracklet") << "recreating file imath.root";
273  }
274  globals->h_file_->cd();
275  TTree *tt = (TTree *)globals->h_file_->Get("tt");
276  if (tt == 0) {
277  tt = new TTree("tt", "");
278  edm::LogVerbatim("Tracklet") << "creating TTree tt";
279  }
280  tt->Branch(s, v);
281  return tt;
282 }
283 void VarBase::fillTree(imathGlobals *globals) {
284  if (globals->h_file_ == 0)
285  return;
286  globals->h_file_->cd();
287  TTree *tt = (TTree *)globals->h_file_->Get("tt");
288  if (tt == 0)
289  return;
290  tt->Fill();
291 }
292 void VarBase::writeTree(imathGlobals *globals) {
293  if (globals->h_file_ == 0)
294  return;
295  globals->h_file_->cd();
296  TTree *tt = (TTree *)globals->h_file_->Get("tt");
297  if (tt == 0)
298  return;
299  tt->Write();
300 }
301 
302 #endif
303 
304 void VarCut::local_passes(std::map<const VarBase *, std::vector<bool> > &passes,
305  const std::map<const VarBase *, std::vector<bool> > *const previous_passes) const {
306  const int lower_cut = lower_cut_ / cut_var_->K();
307  const int upper_cut = upper_cut_ / cut_var_->K();
308  if (!previous_passes || (previous_passes && !previous_passes->count(cut_var_))) {
309  if (!passes.count(cut_var_))
310  passes[cut_var_];
311  passes.at(cut_var_).push_back(cut_var_->ival() > lower_cut && cut_var_->ival() < upper_cut);
312  }
313 }
314 
315 bool VarBase::local_passes() const {
316  bool passes = false;
317  for (const auto &cut : cuts_) {
318  const VarCut *const cast_cut = (VarCut *)cut;
319  const int lower_cut = cast_cut->lower_cut() / K_;
320  const int upper_cut = cast_cut->upper_cut() / K_;
321  passes = passes || (ival_ > lower_cut && ival_ < upper_cut);
322  if (globals_->printCutInfo_) {
323  edm::LogVerbatim("Tracklet") << " " << name_ << " "
324  << ((ival_ > lower_cut && ival_ < upper_cut) ? "PASSES" : "FAILS")
325  << " (required: " << lower_cut * K_ << " < " << ival_ * K_ << " < " << upper_cut * K_
326  << ")";
327  }
328  }
329  return passes;
330 }
331 
332 void VarBase::passes(std::map<const VarBase *, std::vector<bool> > &passes,
333  const std::map<const VarBase *, std::vector<bool> > *const previous_passes) const {
334  if (p1_)
335  p1_->passes(passes, previous_passes);
336  if (p2_)
337  p2_->passes(passes, previous_passes);
338  if (p3_)
339  p3_->passes(passes, previous_passes);
340 
341  for (const auto &cut : cuts_) {
342  const VarCut *const cast_cut = (VarCut *)cut;
343  const int lower_cut = cast_cut->lower_cut() / K_;
344  const int upper_cut = cast_cut->upper_cut() / K_;
345  if (!previous_passes || (previous_passes && !previous_passes->count(this))) {
346  if (!passes.count(this))
347  passes[this];
348  passes.at(this).push_back(ival_ > lower_cut && ival_ < upper_cut);
349  if (globals_->printCutInfo_) {
350  edm::LogVerbatim("Tracklet") << " " << name_ << " "
351  << ((ival_ > lower_cut && ival_ < upper_cut) ? "PASSES" : "FAILS")
352  << " (required: " << lower_cut * K_ << " < " << ival_ * K_ << " < "
353  << upper_cut * K_ << ")";
354  }
355  }
356  }
357 }
358 
359 void VarBase::add_cut(VarCut *cut, const bool call_set_cut_var) {
360  cuts_.push_back(cut);
361  if (call_set_cut_var)
362  cut->set_cut_var(this, false);
363 }
364 
365 void VarCut::set_cut_var(VarBase *cut_var, const bool call_add_cut) {
366  cut_var_ = cut_var;
367  if (call_add_cut)
368  cut_var->add_cut(this, false);
369  if (parent_flag_)
371 }
372 
373 void VarFlag::add_cut(VarBase *cut, const bool call_set_parent_flag) {
374  cuts_.push_back(cut);
375  if (cut->op() == "cut" && call_set_parent_flag) {
376  VarCut *const cast_cut = (VarCut *)cut;
377  cast_cut->set_parent_flag(this, false);
378  }
379  calculate_step();
380 }
381 
382 void VarCut::set_parent_flag(VarFlag *parent_flag, const bool call_add_cut) {
384  if (call_add_cut)
385  parent_flag->add_cut(this, false);
386 }
387 
389  if (op_ == "cut")
390  return cut_var_;
391  else
392  return this;
393 }
394 
396  if (globals_->printCutInfo_) {
397  edm::LogVerbatim("Tracklet") << "Checking if " << name_ << " passes...";
398  }
399 
400  std::map<const VarBase *, std::vector<bool> > passes0, passes1;
401  for (const auto &cut : cuts_) {
402  if (cut->op() != "cut")
403  continue;
404  const VarCut *const cast_cut = (VarCut *)cut;
405  cast_cut->local_passes(passes0);
406  }
407  for (const auto &cut : cuts_) {
408  if (cut->op() != "cut")
409  cut->passes(passes1, &passes0);
410  else {
411  if (cut->cut_var()->p1())
412  cut->cut_var()->p1()->passes(passes1, &passes0);
413  if (cut->cut_var()->p2())
414  cut->cut_var()->p2()->passes(passes1, &passes0);
415  if (cut->cut_var()->p3())
416  cut->cut_var()->p3()->passes(passes1, &passes0);
417  }
418  }
419 
420  bool passes = true;
421  for (const auto &cut_var : passes0) {
422  bool local_passes = false;
423  for (const auto pass : cut_var.second)
424  local_passes = local_passes || pass;
426  }
427  for (const auto &cut_var : passes1) {
428  bool local_passes = false;
429  for (const auto pass : cut_var.second)
430  local_passes = local_passes || pass;
432  }
433 
434  if (globals_->printCutInfo_) {
435  edm::LogVerbatim("Tracklet") << name_ << " " << (passes ? "PASSES" : "FAILS");
436  }
437 
438  return passes;
439 }
void set_cut_var(VarBase *cut_var, const bool call_add_cut=true)
Definition: imath.cc:365
Log< level::Info, true > LogVerbatim
std::string name() const
Definition: imath.h:208
int latency_
Definition: imath.h:302
int gen_inv(int i)
Definition: imath.h:1024
void analyze()
Definition: imath.cc:29
VarFlag * parent_flag_
Definition: imath.h:1093
void inputs(std::vector< VarBase *> *vd)
Definition: imath.cc:205
void add_cut(VarCut *cut, const bool call_set_cut_var=true)
Definition: imath.cc:359
double range() const
Definition: imath.h:246
int nbits() const
Definition: imath.h:244
VarBase * cut_var()
Definition: imath.cc:388
VarBase * p1_
Definition: imath.h:298
double offset()
Definition: imath.h:1002
std::string pipe_delays(const int step)
Definition: imath.cc:184
bool passes()
Definition: imath.cc:395
VarBase * cut_var_
Definition: imath.h:310
std::string to_string(const V &value)
Definition: OMSAccess.h:77
imathGlobals * globals_
Definition: imath.h:296
VarBase * p2_
Definition: imath.h:299
bool has_delay(int i)
Definition: imath.cc:165
std::string kstring() const
Definition: imath.cc:18
assert(be >=bs)
std::vector< int > pipe_delays_
Definition: imath.h:317
void passes(std::map< const VarBase *, std::vector< bool > > &passes, const std::map< const VarBase *, std::vector< bool > > *const previous_passes=nullptr) const
Definition: imath.cc:332
int addr_to_ival(int addr)
Definition: imath.h:1013
VarBase * p3_
Definition: imath.h:300
std::string op_
Definition: imath.h:301
int Nelements_
Definition: imath.h:1049
void initLUT(double offset)
Definition: imath.cc:142
double offset_
Definition: imath.h:1043
Definition: TTTypes.h:54
double lower_cut_
Definition: imath.h:1091
bool local_passes() const
Definition: imath.cc:315
std::map< std::string, int > Kmap() const
Definition: imath.h:245
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void dump_msg()
Definition: imath.cc:96
static std::string itos(int i)
Definition: imath.cc:16
void adjust(double Knew, double epsilon=1e-5, bool do_assert=false, int nbits=-1)
Definition: imath.cc:120
long int ival_
Definition: imath.h:306
std::vector< DeviationSensor2D * > vd
double upper_cut() const
Definition: imath.h:1072
void set_parent_flag(VarFlag *parent_flag, const bool call_add_cut)
Definition: imath.cc:382
double K() const
Definition: imath.h:247
double minval_
Definition: imath.h:323
bool readytoprint_
Definition: imath.h:320
void add_cut(VarBase *cut, const bool call_set_parent_flag=true)
Definition: imath.cc:373
int pipe_counter_
Definition: imath.h:316
double upper_cut_
Definition: imath.h:1092
void makeready()
Definition: imath.cc:151
static std::string pipe_delay_wire(VarBase *v, std::string name_delayed, int nbits, int delay)
Definition: imath.cc:196
long int ival() const
Definition: imath.h:214
std::vector< VarBase * > cuts_
Definition: imath.h:309
std::string name_
Definition: imath.h:297
static std::string pipe_delay(VarBase *v, int nbits, int delay)
Definition: imath.cc:173
std::map< std::string, int > Kmap_
Definition: imath.h:314
double maxval_
Definition: imath.h:324
double lower_cut() const
Definition: imath.h:1071
double K_
Definition: imath.h:313
bool readytoanalyze_
Definition: imath.h:319
void local_passes(std::map< const VarBase *, std::vector< bool > > &passes, const std::map< const VarBase *, std::vector< bool > > *const previous_passes=nullptr) const
Definition: imath.cc:304
std::string dump()
Definition: imath.cc:78
step
Definition: StallMonitor.cc:98
bool usedasinput_
Definition: imath.h:321
std::vector< unsigned short int > LUT
Definition: DTTracoLUTs.h:31
double fval_
Definition: imath.h:305
VarFlag * parent_flag()
Definition: imath.h:1087
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29