CMS 3D CMS Logo

imath.h
Go to the documentation of this file.
1 // // Integer representation of floating point arithmetic suitable for FPGA designs
2 //
3 // Author: Yuri Gershtein
4 // Date: March 2018
5 //
6 // Functionality:
7 //
8 // *note* all integers are assumed to be signed
9 //
10 // all variables have units, stored in a map <string,int>, with string a unit (i.e. "phi") and int the power
11 // "2" is always present in the map, and it's int pair is referred to as 'shift'
12 // units are properly combined / propagated through calculations
13 // adding/subtracting variables with different units throws an exception
14 // adding/subtracting variables with different shifts is allowed and is handled correctly
15 //
16 // calculate() method re-calculates the variable double and int values based on its operands
17 // returns false in case of overflows and/or mismatches between double and int calculations.
18 //
19 // the maximum and minimum values that the variable assumes are stored and updated each time calculate() is called
20 // if IMATH_ROOT is defined, all values are also stored in a histogram
21 //
22 // VarDef (string name, string units, double fmax, double K):
23 // define variable with bit value fval = K*ival, and maximum absolute value fmax.
24 // calculates nbins on its own
25 // one can assign value to it using set_ methods
26 //
27 // VarParam (string name, string units, double fval, int nbits):
28 // define a parameter. K is calculated based on the fval and nbits
29 //
30 // or (string name, std::string units, double fval, double K):
31 // define a parameer with bit value fval = K*ival.
32 // calculates nbins on its own
33 //
34 // VarAdd (string name, VarBase *p1, VarBase *p2, double range = -1, int nmax = 18):
35 // VarSubtract(string name, VarBase *p1, VarBase *p2, double range = -1, int nmax = 18):
36 // add/subtract variables. Bit length increases by 1, but capped at nmax
37 // if range>0 specified, bit length is decreased to drop unnecessary high bits
38 //
39 // VarMult (string name, VarBase *p1, VarBase *p2, double range = -1, int nmax = 18):
40 // multiplication. Bit length is a sum of the lengths of the operads, but capped at nmax
41 // if range>0 specified, bit length is decreased to drop unnecessary high bits or post-shift is reduced
42 //
43 // VarTimesC (string name, VarBase *p1, double cF, int ps = 17):
44 // multiplication by a constant. Bit length stays the same
45 // ps defines number of bits used to represent the constant
46 //
47 // VarDSPPostadd (string name, VarBase *p1, VarBase *p2, VarBase *p3, double range = -1, int nmax = 18):
48 // explicit instantiation of the 3-clock DSP postaddition: p1*p2+p3
49 // range and nmax have the same meaning as for the VarMult.
50 //
51 // VarShift (string name, VarBase *p1, int shift):
52 // shifts the variable right by shift (equivalent to multiplication by pow(2, -shift));
53 // Units stay the same, nbits are adjusted.
54 //
55 // VarShiftround (string name, VarBase *p1, int shift):
56 // shifts the variable right by shift, but doing rounding, i.e.
57 // (p>>(shift-1)+1)>>1;
58 // Units stay the same, nbits are adjusted.
59 //
60 // VarNeg (string name, VarBase *p1):
61 // multiplies the variable by -1
62 //
63 // VarInv (string name, VarBase *p1, double offset, int nbits, int n, unsigned int shift, mode m, int nbaddr=-1):
64 // LUT-based inversion, f = 1./(offset + f1) and i = 2^n / (offsetI + i1)
65 // nbits is the width of the LUT (signed)
66 // m is from enum mode {pos, neg, both} and refers to possible sign values of f
67 // for pos and neg, the most significant bit of p1 (i.e. the sign bit) is ignored
68 // shift is a shift applied in i1<->address conversions (used to reduce size of LUT)
69 // nbaddr: if not specified, it is taken to be equal to p1->nbits()
70 //
71 //
72 // VarNounits (string name, VarBase *p1, int ps = 17):
73 // convert a number with units to a number - needed for trig function expansion (i.e. 1 - 0.5*phi^2)
74 // ps is a number of bits to represent the unit conversion constant
75 //
76 // VarAdjustK (string name, VarBase *p1, double Knew, double epsilon = 1e-5, bool do_assert = false, int nbits = -1)
77 // adjust variable shift so the K is as close to Knew as possible (needed for bit length adjustments)
78 // if do_assert is true, throw an exeption if Knew/Kold is not a power of two
79 // epsilon is a comparison precision, nbits forces the bit length (possibly discarding MSBs)
80 //
81 // VarAdjustKR (string name, VarBase *p1, double Knew, double epsilon = 1e-5, bool do_assert = false, int nbits = -1)
82 // - same as adjustK(), but with rounding, and therefore latency=1
83 //
84 // bool calculate(int debug_level) runs through the entire formula tree recalculating both ineteger and floating point values
85 // returns true if everything is OK, false if obvious problems with the calculation exist, i.e
86 // - integer value does not fit into the alotted number of bins
87 // - integer value is more then 10% or more then 2 away from fval_/K_
88 // debug_level: 0 - no warnings
89 // 1 - limited warning
90 // 2 - as 1, but also include explicit warnings when LUT was used out of its range
91 // 3 - maximum complaints level
92 //
93 // VarFlag (string name, VarBase *cut_var, VarBase *...)
94 //
95 // flag to apply cuts defined for any variable. When output as Verilog, the flag
96 // is true if and only if the following conditions are all true:
97 // 1) the cut defined by each VarCut pointer in the argument list must be passed
98 // by the associated variable
99 // 2) each VarBase pointer in the argument list that is not also a VarCut
100 // pointer must pass all of its associated cuts
101 // 3) all children of the variables in the argument list must pass all of their
102 // associated cuts
103 // The VarFlag::passes() method replicates the behavior of the output Verilog,
104 // returning true if and only if the above conditions are all true. The
105 // VarBase::local_passes() method can be used to query if a given variable passes
106 // its associated cuts, regardless of whether its children do.
107 //
108 #ifndef L1Trigger_TrackFindingTracklet_interface_imath_h
109 #define L1Trigger_TrackFindingTracklet_interface_imath_h
110 
111 //use root if uncommented
112 //#ifndef CMSSW_GIT_HASH
113 //#define IMATH_ROOT
114 //#endif
115 
116 #include <limits>
117 #include <iostream>
118 #include <fstream>
119 #include <vector>
120 #include <map>
121 #include <cmath>
122 #include <sstream>
123 #include <string>
124 #include <cassert>
125 #include <set>
126 
131 
132 #ifdef IMATH_ROOT
133 #include <TH2F.h>
134 #include <TFile.h>
135 #include <TCanvas.h>
136 #include <TTree.h>
137 #endif
138 
139 //operation latencies for proper HDL pipelining
140 #define MULT_LATENCY 1
141 #define LUT_LATENCY 2
142 #define DSP_LATENCY 3
143 
144 // Print out information on the pass/fail status of all variables. Warning:
145 // this outputs a lot of information for busy events!
146 
147 namespace trklet {
148 
149  struct imathGlobals {
150  bool printCutInfo_{false};
151 #ifdef IMATH_ROOT
152  TFile *h_file_ = new TFile("imath.root", "RECREATE");
153  bool use_root;
154 #endif
155  };
156 
157  class VarCut;
158  class VarFlag;
159 
160  class VarBase {
161  public:
163  globals_ = globals;
164  p1_ = p1;
165  p2_ = p2;
166  p3_ = p3;
167  name_ = name;
168  latency_ = l;
169  int step1 = (p1) ? p1->step() + p1->latency() : 0;
170  int step2 = (p2) ? p2->step() + p2->latency() : 0;
171  step_ = std::max(step1, step2);
172 
173  cuts_.clear();
174  cut_var_ = nullptr;
175 
176  pipe_counter_ = 0;
177  pipe_delays_.clear();
178 
181  readytoprint_ = true;
182  readytoanalyze_ = true;
183  usedasinput_ = false;
184  Kmap_.clear();
185  Kmap_["2"] = 0; // initially, zero shift
186 #ifdef IMATH_ROOT
187  h_ = 0;
188  h_nbins_ = 1024;
189  h_precision_ = 0.02;
190 #endif
191  }
192  virtual ~VarBase() {
193 #ifdef IMATH_ROOT
194  if (globals_->h_file_) {
195  globals_->h_file_->ls();
196  globals_->h_file_->Close();
197  globals_->h_file_ = 0;
198  }
199 #endif
200  }
201 
202  static struct Verilog {
203  } verilog;
204  static struct HLS {
205  } hls;
206 
207  std::string kstring() const;
208  std::string name() const { return name_; }
209  std::string op() const { return op_; }
210  VarBase *p1() const { return p1_; }
211  VarBase *p2() const { return p2_; }
212  VarBase *p3() const { return p3_; }
213  double fval() const { return fval_; }
214  long int ival() const { return ival_; }
215 
216  bool local_passes() const;
217  void passes(std::map<const VarBase *, std::vector<bool> > &passes,
218  const std::map<const VarBase *, std::vector<bool> > *const previous_passes = nullptr) const;
219  void print_cuts(std::map<const VarBase *, std::set<std::string> > &cut_strings,
220  const int step,
221  Verilog,
222  const std::map<const VarBase *, std::set<std::string> > *const previous_cut_strings = nullptr) const;
223  void print_cuts(std::map<const VarBase *, std::set<std::string> > &cut_strings,
224  const int step,
225  HLS,
226  const std::map<const VarBase *, std::set<std::string> > *const previous_cut_strings = nullptr) const;
227  void add_cut(VarCut *cut, const bool call_set_cut_var = true);
228  VarBase *cut_var();
229  // observed range of fval_ (only filled if debug_level > 0)
230  double minval() const { return minval_; }
231  double maxval() const { return maxval_; }
232  void analyze();
233 #ifdef IMATH_ROOT
234  TH2F *h() { return h_; }
235 #endif
236  void reset() {
239 #ifdef IMATH_ROOT
240  h_->Clear();
241 #endif
242  }
243 
244  int nbits() const { return nbits_; }
245  std::map<std::string, int> Kmap() const { return Kmap_; }
246  double range() const { return (1 << (nbits_ - 1)) * K_; } // everything is signed
247  double K() const { return K_; };
248  int shift() const { return Kmap_.at("2"); }
249 
250  void makeready();
251  int step() const { return step_; }
252  int latency() const { return latency_; }
253  void add_latency(unsigned int l) { latency_ += l; } //only call before using the variable in calculation!
254  bool calculate(int debug_level = 0);
255  virtual void local_calculate() {}
256  void calcDebug(int debug_level, long int ival_prev, bool &all_ok);
257  virtual void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) {
258  fs << "// VarBase here. Soemthing is wrong!! " << l1 << ", " << l2 << ", " << l3 << "\n";
259  }
260  virtual void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) {
261  fs << "// VarBase here. Soemthing is wrong!! " << l1 << ", " << l2 << ", " << l3 << "\n";
262  }
263  void print_step(int step, std::ofstream &fs, Verilog);
264  void print_step(int step, std::ofstream &fs, HLS);
265  void print_all(std::ofstream &fs, Verilog);
266  void print_all(std::ofstream &fs, HLS);
267  void print_truncation(std::string &t, const std::string &o1, const int ps, Verilog) const;
268  void print_truncation(std::string &t, const std::string &o1, const int ps, HLS) const;
269  void inputs(std::vector<VarBase *> *vd); //collect all inputs
270 
271  int pipe_counter() { return pipe_counter_; }
273  void add_delay(int i) { pipe_delays_.push_back(i); }
274  bool has_delay(int i); //returns true if already have this variable delayed.
275  static void verilog_print(const std::vector<VarBase *> &v, std::ofstream &fs) { design_print(v, fs, verilog); }
276  static void hls_print(const std::vector<VarBase *> &v, std::ofstream &fs) { design_print(v, fs, hls); }
277  static void design_print(const std::vector<VarBase *> &v, std::ofstream &fs, Verilog);
278  static void design_print(const std::vector<VarBase *> &v, std::ofstream &fs, HLS);
279  static std::string pipe_delay(VarBase *v, int nbits, int delay);
280  std::string pipe_delays(const int step);
281  static std::string pipe_delay_wire(VarBase *v, std::string name_delayed, int nbits, int delay);
282 
283 #ifdef IMATH_ROOT
284  static TTree *addToTree(imathGlobals *globals, VarBase *v, char *s = 0);
285  static TTree *addToTree(imathGlobals *globals, int *v, char *s);
286  static TTree *addToTree(imathGlobals *globals, double *v, char *s);
287  static void fillTree(imathGlobals *globals);
288  static void writeTree(imathGlobals *globals);
289 #endif
290 
291  void dump_msg();
292  std::string dump();
293  static std::string itos(int i);
294 
295  protected:
301  std::string op_; // operation
302  int latency_; // number of clock cycles for the operation (for HDL output)
303  int step_; // step number in the calculation (for HDL output)
304 
305  double fval_; // exact calculation
306  long int ival_; // integer calculation
307  double val_; // integer calculation converted to double, ival_*K
308 
309  std::vector<VarBase *> cuts_;
311 
312  int nbits_;
313  double K_;
314  std::map<std::string, int> Kmap_;
315 
317  std::vector<int> pipe_delays_;
318 
322 
323  double minval_;
324  double maxval_;
325 #ifdef IMATH_ROOT
326  void set_hist_pars(int n = 256, double p = 0.05) {
327  h_nbins_ = n;
328  h_precision_ = p;
329  }
330  int h_nbins_;
331  double h_precision_;
332  TH2F *h_;
333 #endif
334  };
335 
336  class VarAdjustK : public VarBase {
337  public:
340  VarBase *p1,
341  double Knew,
342  double epsilon = 1e-5,
343  bool do_assert = false,
344  int nbits = -1)
345  : VarBase(globals, name, p1, nullptr, nullptr, 0) {
346  op_ = "adjustK";
347  K_ = p1->K();
348  Kmap_ = p1->Kmap();
349 
350  double r = Knew / K_;
351 
352  lr_ = (r > 1) ? log2(r) + epsilon : log2(r);
353  K_ = K_ * pow(2, lr_);
354  if (do_assert)
355  assert(std::abs(Knew / K_ - 1) < epsilon);
356 
357  if (nbits > 0)
358  nbits_ = nbits;
359  else
360  nbits_ = p1->nbits() - lr_;
361 
362  Kmap_["2"] = Kmap_["2"] + lr_;
363  }
364 
365  ~VarAdjustK() override = default;
366 
367  void adjust(double Knew, double epsilon = 1e-5, bool do_assert = false, int nbits = -1);
368 
369  void local_calculate() override;
370  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
371  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
372 
373  protected:
374  int lr_;
375  };
376 
377  class VarAdjustKR : public VarBase {
378  public:
381  VarBase *p1,
382  double Knew,
383  double epsilon = 1e-5,
384  bool do_assert = false,
385  int nbits = -1)
386  : VarBase(globals, name, p1, nullptr, nullptr, 1) {
387  op_ = "adjustKR";
388  K_ = p1->K();
389  Kmap_ = p1->Kmap();
390 
391  double r = Knew / K_;
392 
393  lr_ = (r > 1) ? log2(r) + epsilon : log2(r);
394  K_ = K_ * pow(2, lr_);
395  if (do_assert)
396  assert(std::abs(Knew / K_ - 1) < epsilon);
397 
398  if (nbits > 0)
399  nbits_ = nbits;
400  else
401  nbits_ = p1->nbits() - lr_;
402 
403  Kmap_["2"] = Kmap_["2"] + lr_;
404  }
405 
406  ~VarAdjustKR() override = default;
407 
408  void local_calculate() override;
409  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
410  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
411 
412  protected:
413  int lr_;
414  };
415 
416  class VarParam : public VarBase {
417  public:
418  VarParam(imathGlobals *globals, std::string name, double fval, int nbits)
419  : VarBase(globals, name, nullptr, nullptr, nullptr, 0) {
420  op_ = "const";
421  nbits_ = nbits;
422  int l = log2(std::abs(fval)) + 1.9999999 - nbits;
423  Kmap_["2"] = l;
424  K_ = pow(2, l);
425  fval_ = fval;
426  ival_ = fval / K_;
427  }
429  : VarBase(globals, name, nullptr, nullptr, nullptr, 0) {
430  op_ = "const";
431  K_ = K;
432  nbits_ = log2(fval / K) + 1.999999; //plus one to round up
433  if (!units.empty())
434  Kmap_[units] = 1;
435  else {
436  //defining a constant, K should be a power of two
437  int l = log2(K);
438  if (std::abs(pow(2, l) / K - 1) > 1e-5) {
439  char slog[100];
440  snprintf(slog, 100, "defining unitless constant, yet K is not a power of 2! %g, %g", K, pow(2, l));
441  edm::LogVerbatim("Tracklet") << slog;
442  }
443  Kmap_["2"] = l;
444  }
445  }
446 
447  ~VarParam() override = default;
448 
449  void set_fval(double fval) {
450  fval_ = fval;
451  if (fval > 0)
452  ival_ = fval / K_ + 0.5;
453  else
454  ival_ = fval / K_ - 0.5;
455  val_ = ival_ * K_;
456  }
457  void set_ival(int ival) {
458  ival_ = ival;
459  fval_ = ival * K_;
460  val_ = fval_;
461  }
462  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
463  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
464  };
465 
466  class VarDef : public VarBase {
467  public:
468  //construct from scratch
469  VarDef(imathGlobals *globals, std::string name, std::string units, double fmax, double K)
470  : VarBase(globals, name, nullptr, nullptr, nullptr, 1) {
471  op_ = "def";
472  K_ = K;
473  nbits_ = log2(fmax / K) + 1.999999; //plus one to round up
474  if (!units.empty())
475  Kmap_[units] = 1;
476  else {
477  //defining a constant, K should be a power of two
478  int l = log2(K);
479  if (std::abs(pow(2, l) / K - 1) > 1e-5) {
480  char slog[100];
481  snprintf(slog, 100, "defining unitless constant, yet K is not a power of 2! %g, %g", K, pow(2, l));
482  edm::LogVerbatim("Tracklet") << slog;
483  }
484  Kmap_["2"] = l;
485  }
486  }
487  //construct from abother variable (all provenance info is lost!)
488  VarDef(imathGlobals *globals, std::string name, VarBase *p) : VarBase(globals, name, nullptr, nullptr, nullptr, 1) {
489  op_ = "def";
490  K_ = p->K();
491  nbits_ = p->nbits();
492  Kmap_ = p->Kmap();
493  }
494  void set_fval(double fval) {
495  fval_ = fval;
496  if (fval > 0)
497  ival_ = fval / K_;
498  else
499  ival_ = fval / K_ - 1;
500  val_ = ival_ * K_;
501  }
502  void set_ival(int ival) {
503  ival_ = ival;
504  fval_ = ival * K_;
505  val_ = ival_ * K_;
506  }
507  ~VarDef() override = default;
508  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
509  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
510  };
511 
512  class VarAdd : public VarBase {
513  public:
514  VarAdd(imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, double range = -1, int nmax = 18)
515  : VarBase(globals, name, p1, p2, nullptr, 1) {
516  op_ = "add";
517 
518  std::map<std::string, int> map1 = p1->Kmap();
519  std::map<std::string, int> map2 = p2->Kmap();
520  int s1 = map1["2"];
521  int s2 = map2["2"];
522 
523  //first check if the constants are all lined up
524  //go over the two maps subtracting the units
525  for (const auto &it : map2) {
526  if (map1.find(it.first) == map1.end())
527  map1[it.first] = -it.second;
528  else
529  map1[it.first] = map1[it.first] - it.second;
530  }
531 
532  char slog[100];
533 
534  //assert if different
535  for (const auto &it : map1) {
536  if (it.second != 0) {
537  if (it.first != "2") {
538  snprintf(
539  slog, 100, "VarAdd: bad units! %s^%i for variable %s", (it.first).c_str(), it.second, name_.c_str());
540  edm::LogVerbatim("Tracklet") << slog;
541  p1->dump_msg();
542  p2->dump_msg();
543  throw cms::Exception("BadConfig") << "imath units are different!";
544  }
545  }
546  }
547 
548  double ki1 = p1->K() / pow(2, s1);
549  double ki2 = p2->K() / pow(2, s2);
550  //those should be the same
551  if (std::abs(ki1 / ki2 - 1.) > 1e-6) {
552  snprintf(slog, 100, "VarAdd: bad constants! %f %f for variable %s", ki1, ki2, name_.c_str());
553  edm::LogVerbatim("Tracklet") << slog;
554  p1->dump_msg();
555  p2->dump_msg();
556  throw cms::Exception("BadConfig") << "imath constants are different!";
557  }
558  //everything checks out!
559 
560  Kmap_ = p1->Kmap();
561 
562  int s0 = s1 < s2 ? s1 : s2;
563  shift1 = s1 - s0;
564  shift2 = s2 - s0;
565 
566  int n1 = p1->nbits() + shift1;
567  int n2 = p2->nbits() + shift2;
568  int n0 = 1 + (n1 > n2 ? n1 : n2);
569 
570  //before shifting, check the range
571  if (range > 0) {
572  n0 = log2(range / ki1 / pow(2, s0)) + 1e-9;
573  n0 = n0 + 2;
574  }
575 
576  if (n0 <= nmax) { //if it fits, we're done
577  ps_ = 0;
578  Kmap_["2"] = s0;
579  nbits_ = n0;
580  } else {
581  ps_ = n0 - nmax;
582  Kmap_["2"] = s0 + ps_;
583  nbits_ = nmax;
584  }
585 
586  K_ = ki1 * pow(2, Kmap_["2"]);
587  }
588  ~VarAdd() override = default;
589  void local_calculate() override;
590  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
591  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
592 
593  protected:
594  int ps_;
595  int shift1;
596  int shift2;
597  };
598 
599  class VarSubtract : public VarBase {
600  public:
601  VarSubtract(imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, double range = -1, int nmax = 18)
602  : VarBase(globals, name, p1, p2, nullptr, 1) {
603  op_ = "subtract";
604 
605  std::map<std::string, int> map1 = p1->Kmap();
606  std::map<std::string, int> map2 = p2->Kmap();
607  int s1 = map1["2"];
608  int s2 = map2["2"];
609 
610  //first check if the constants are all lined up go over the two maps subtracting the units
611  for (const auto &it : map2) {
612  if (map1.find(it.first) == map1.end())
613  map1[it.first] = -it.second;
614  else
615  map1[it.first] = map1[it.first] - it.second;
616  }
617 
618  char slog[100];
619 
620  //assert if different
621  for (const auto &it : map1) {
622  if (it.second != 0) {
623  if (it.first != "2") {
624  snprintf(
625  slog, 100, "VarAdd: bad units! %s^%i for variable %s", (it.first).c_str(), it.second, name_.c_str());
626  edm::LogVerbatim("Tracklet") << slog;
627  p1->dump_msg();
628  p2->dump_msg();
629  throw cms::Exception("BadConfig") << "imath units are different!";
630  }
631  }
632  }
633 
634  double ki1 = p1->K() / pow(2, s1);
635  double ki2 = p2->K() / pow(2, s2);
636  //those should be the same
637  if (std::abs(ki1 / ki2 - 1.) > 1e-6) {
638  snprintf(slog, 100, "VarAdd: bad constants! %f %f for variable %s", ki1, ki2, name_.c_str());
639  edm::LogVerbatim("Tracklet") << slog;
640  p1->dump_msg();
641  p2->dump_msg();
642  throw cms::Exception("BadConfig") << "imath constants are different!";
643  }
644  //everything checks out!
645 
646  Kmap_ = p1->Kmap();
647 
648  int s0 = s1 < s2 ? s1 : s2;
649  shift1 = s1 - s0;
650  shift2 = s2 - s0;
651 
652  int n1 = p1->nbits() + shift1;
653  int n2 = p2->nbits() + shift2;
654  int n0 = 1 + (n1 > n2 ? n1 : n2);
655 
656  //before shifting, check the range
657  if (range > 0) {
658  n0 = log2(range / ki1 / pow(2, s0)) + 1e-9;
659  n0 = n0 + 2;
660  }
661 
662  if (n0 <= nmax) { //if it fits, we're done
663  ps_ = 0;
664  Kmap_["2"] = s0;
665  nbits_ = n0;
666  } else {
667  ps_ = n0 - nmax;
668  Kmap_["2"] = s0 + ps_;
669  nbits_ = nmax;
670  }
671 
672  K_ = ki1 * pow(2, Kmap_["2"]);
673  }
674 
675  ~VarSubtract() override = default;
676 
677  void local_calculate() override;
678  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
679  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
680 
681  protected:
682  int ps_;
683  int shift1;
684  int shift2;
685  };
686 
687  class VarNounits : public VarBase {
688  public:
689  VarNounits(imathGlobals *globals, std::string name, VarBase *p1, int ps = 17)
690  : VarBase(globals, name, p1, nullptr, nullptr, MULT_LATENCY) {
691  op_ = "nounits";
692  ps_ = ps;
693  nbits_ = p1->nbits();
694 
695  int s1 = p1->shift();
696  double ki = p1->K() / pow(2, s1);
697  int m = log2(ki);
698 
699  K_ = pow(2, s1 + m);
700  Kmap_["2"] = s1 + m;
701  double c = ki * pow(2, -m);
702  cI_ = c * pow(2, ps_);
703  }
704  ~VarNounits() override = default;
705 
706  void local_calculate() override;
707  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
708  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
709 
710  protected:
711  int ps_;
712  int cI_;
713  };
714 
715  class VarShiftround : public VarBase {
716  public:
718  : VarBase(globals, name, p1, nullptr, nullptr, 1) { // latency is one because there is an addition
719  op_ = "shiftround";
720  shift_ = shift;
721 
722  nbits_ = p1->nbits() - shift;
723  Kmap_ = p1->Kmap();
724  K_ = p1->K();
725  }
726  ~VarShiftround() override = default;
727 
728  void local_calculate() override;
729  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
730  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
731 
732  protected:
733  int shift_;
734  };
735 
736  class VarShift : public VarBase {
737  public:
739  : VarBase(globals, name, p1, nullptr, nullptr, 0) {
740  op_ = "shift";
741  shift_ = shift;
742 
743  nbits_ = p1->nbits() - shift;
744  Kmap_ = p1->Kmap();
745  K_ = p1->K();
746  }
747  ~VarShift() override = default;
748  void local_calculate() override;
749  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
750  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
751 
752  protected:
753  int shift_;
754  };
755 
756  class VarNeg : public VarBase {
757  public:
758  VarNeg(imathGlobals *globals, std::string name, VarBase *p1) : VarBase(globals, name, p1, nullptr, nullptr, 1) {
759  op_ = "neg";
760  nbits_ = p1->nbits();
761  Kmap_ = p1->Kmap();
762  K_ = p1->K();
763  }
764  ~VarNeg() override = default;
765  void local_calculate() override;
766  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
767  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
768  };
769 
770  class VarTimesC : public VarBase {
771  public:
772  VarTimesC(imathGlobals *globals, std::string name, VarBase *p1, double cF, int ps = 17)
773  : VarBase(globals, name, p1, nullptr, nullptr, MULT_LATENCY) {
774  op_ = "timesC";
775  cF_ = cF;
776  ps_ = ps;
777 
778  nbits_ = p1->nbits();
779  Kmap_ = p1->Kmap();
780  K_ = p1->K();
781 
782  int s1 = Kmap_["2"];
783  double l = log2(std::abs(cF));
784  if (l > 0)
785  l += 0.999999;
786  int m = l;
787 
788  cI_ = cF * pow(2, ps - m);
789  K_ = K_ * pow(2, m);
790  Kmap_["2"] = s1 + m;
791  }
792  ~VarTimesC() override = default;
793  void local_calculate() override;
794  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
795  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
796 
797  protected:
798  int ps_;
799  int cI_;
800  double cF_;
801  };
802 
803  class VarMult : public VarBase {
804  public:
805  VarMult(imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, double range = -1, int nmax = 18)
806  : VarBase(globals, name, p1, p2, nullptr, MULT_LATENCY) {
807  op_ = "mult";
808 
809  const std::map<std::string, int> map1 = p1->Kmap();
810  const std::map<std::string, int> map2 = p2->Kmap();
811  for (const auto &it : map1) {
812  if (Kmap_.find(it.first) == Kmap_.end())
813  Kmap_[it.first] = it.second;
814  else
815  Kmap_[it.first] = Kmap_[it.first] + it.second;
816  }
817  for (const auto &it : map2) {
818  if (Kmap_.find(it.first) == Kmap_.end())
819  Kmap_[it.first] = it.second;
820  else
821  Kmap_[it.first] = Kmap_[it.first] + it.second;
822  }
823  K_ = p1->K() * p2->K();
824  int s0 = Kmap_["2"];
825 
826  int n0 = p1->nbits() + p2->nbits();
827  if (range > 0) {
828  n0 = log2(range / K_) + 1e-9;
829  n0 = n0 + 2;
830  }
831  if (n0 < nmax) {
832  ps_ = 0;
833  nbits_ = n0;
834  } else {
835  ps_ = n0 - nmax;
836  nbits_ = nmax;
837  Kmap_["2"] = s0 + ps_;
838  K_ = K_ * pow(2, ps_);
839  }
840  }
841  ~VarMult() override = default;
842  void local_calculate() override;
843  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
844  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
845 
846  protected:
847  int ps_;
848  };
849 
850  class VarDSPPostadd : public VarBase {
851  public:
853  imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, VarBase *p3, double range = -1, int nmax = 18)
854  : VarBase(globals, name, p1, p2, p3, DSP_LATENCY) {
855  op_ = "DSP_postadd";
856 
857  //first, get constants for the p1*p2
858  std::map<std::string, int> map1 = p1->Kmap();
859  std::map<std::string, int> map2 = p2->Kmap();
860  for (const auto &it : map2) {
861  if (map1.find(it.first) == map1.end())
862  map1[it.first] = it.second;
863  else
864  map1[it.first] = map1[it.first] + it.second;
865  }
866  double k0 = p1->K() * p2->K();
867  int s0 = map1["2"];
868 
869  //now addition
870  std::map<std::string, int> map3 = p3->Kmap();
871  int s3 = map3["2"];
872 
873  //first check if the constants are all lined up
874  //go over the two maps subtracting the units
875  for (const auto &it : map3) {
876  if (map1.find(it.first) == map1.end())
877  map1[it.first] = -it.second;
878  else
879  map1[it.first] = map1[it.first] - it.second;
880  }
881 
882  char slog[100];
883 
884  //assert if different
885  for (const auto &it : map1) {
886  if (it.second != 0) {
887  if (it.first != "2") {
888  snprintf(slog,
889  100,
890  "VarDSPPostadd: bad units! %s^%i for variable %s",
891  (it.first).c_str(),
892  it.second,
893  name_.c_str());
894  edm::LogVerbatim("Tracklet") << slog;
895  p1->dump_msg();
896  p2->dump_msg();
897  p3->dump_msg();
898  throw cms::Exception("BadConfig") << "imath units are different!";
899  }
900  }
901  }
902 
903  double ki1 = k0 / pow(2, s0);
904  double ki2 = p3->K() / pow(2, s3);
905  //those should be the same
906  if (std::abs(ki1 / ki2 - 1.) > 1e-6) {
907  snprintf(slog, 100, "VarDSPPostadd: bad constants! %f %f for variable %s", ki1, ki2, name_.c_str());
908  edm::LogVerbatim("Tracklet") << slog;
909  p1->dump_msg();
910  p2->dump_msg();
911  p3->dump_msg();
912  throw cms::Exception("BadConfig") << "imath constants are different!";
913  }
914  //everything checks out!
915 
916  shift3_ = s3 - s0;
917  if (shift3_ < 0) {
918  throw cms::Exception("BadConfig") << "imath VarDSPPostadd: loosing precision on C in A*B+C: " << shift3_;
919  }
920 
921  Kmap_ = p3->Kmap();
922  Kmap_["2"] = Kmap_["2"] - shift3_;
923 
924  int n12 = p1->nbits() + p2->nbits();
925  int n3 = p3->nbits() + shift3_;
926  int n0 = 1 + (n12 > n3 ? n12 : n3);
927 
928  //before shifting, check the range
929  if (range > 0) {
930  n0 = log2(range / ki2 / pow(2, s3)) + 1e-9;
931  n0 = n0 + 2;
932  }
933 
934  if (n0 <= nmax) { //if it fits, we're done
935  ps_ = 0;
936  nbits_ = n0;
937  } else {
938  ps_ = n0 - nmax;
939  Kmap_["2"] = Kmap_["2"] + ps_;
940  nbits_ = nmax;
941  }
942 
943  K_ = ki2 * pow(2, Kmap_["2"]);
944  }
945  ~VarDSPPostadd() override = default;
946 
947  void local_calculate() override;
948  using VarBase::print;
949  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
950 
951  protected:
952  int ps_;
953  int shift3_;
954  };
955 
956  class VarInv : public VarBase {
957  public:
958  enum mode { pos, neg, both };
959 
962  VarBase *p1,
963  double offset,
964  int nbits,
965  int n,
966  unsigned int shift,
967  mode m,
968  int nbaddr = -1)
969  : VarBase(globals, name, p1, nullptr, nullptr, LUT_LATENCY) {
970  op_ = "inv";
971  offset_ = offset;
972  nbits_ = nbits;
973  n_ = n;
974  shift_ = shift;
975  m_ = m;
976  if (nbaddr < 0)
977  nbaddr = p1->nbits();
978  nbaddr_ = nbaddr - shift;
979  if (m_ != mode::both)
980  nbaddr_--;
981  Nelements_ = 1 << nbaddr_;
982  mask_ = Nelements_ - 1;
983  ashift_ = sizeof(int) * 8 - nbaddr_;
984 
985  const std::map<std::string, int> map1 = p1->Kmap();
986  for (const auto &it : map1)
987  Kmap_[it.first] = -it.second;
988  Kmap_["2"] = Kmap_["2"] - n;
989  K_ = pow(2, -n) / p1->K();
990 
991  LUT = new int[Nelements_];
992  double offsetI = lround(offset_ / p1_->K());
993  for (int i = 0; i < Nelements_; ++i) {
994  int i1 = addr_to_ival(i);
995  LUT[i] = gen_inv(offsetI + i1);
996  }
997  }
998  ~VarInv() override { delete[] LUT; }
999 
1000  void set_mode(mode m) { m_ = m; }
1001  void initLUT(double offset);
1002  double offset() { return offset_; }
1003  double Ioffset() { return offset_ / p1_->K(); }
1004 
1005  void local_calculate() override;
1006  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
1007  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
1008  void writeLUT(std::ofstream &fs) const { writeLUT(fs, verilog); }
1009  void writeLUT(std::ofstream &fs, Verilog) const;
1010  void writeLUT(std::ofstream &fs, HLS) const;
1011 
1012  int ival_to_addr(int ival) { return ((ival >> shift_) & mask_); }
1013  int addr_to_ival(int addr) {
1014  switch (m_) {
1015  case mode::pos:
1016  return l1t::bitShift(addr, shift_);
1017  case mode::neg:
1018  return l1t::bitShift((addr - Nelements_), shift_);
1019  case mode::both:
1020  return l1t::bitShift(addr, ashift_) >> (ashift_ - shift_);
1021  }
1022  assert(0);
1023  }
1024  int gen_inv(int i) {
1025  unsigned int ms = sizeof(int) * 8 - nbits_;
1026  int lut = 0;
1027  if (i > 0) {
1028  int i1 = i + (1 << shift_) - 1;
1029  int lut1 = (lround((1 << n_) / i) << ms) >> ms;
1030  int lut2 = (lround((1 << n_) / (i1)) << ms) >> ms;
1031  lut = 0.5 * (lut1 + lut2);
1032  } else if (i < -1) {
1033  int i1 = i + (1 << shift_) - 1;
1034  int i2 = i;
1035  int lut1 = (lround((1 << n_) / i1) << ms) >> ms;
1036  int lut2 = (lround((1 << n_) / i2) << ms) >> ms;
1037  lut = 0.5 * (lut1 + lut2);
1038  }
1039  return lut;
1040  }
1041 
1042  protected:
1043  double offset_;
1044  int n_;
1046  unsigned int shift_;
1047  unsigned int mask_;
1048  unsigned int ashift_;
1050  int nbaddr_;
1051 
1052  int *LUT;
1053  };
1054 
1055  class VarCut : public VarBase {
1056  public:
1057  VarCut(imathGlobals *globals, double lower_cut, double upper_cut)
1058  : VarBase(globals, "", nullptr, nullptr, nullptr, 0),
1061  parent_flag_(nullptr) {
1062  op_ = "cut";
1063  }
1064 
1066  : VarCut(globals, lower_cut, upper_cut) {
1068  }
1069  ~VarCut() override = default;
1070 
1071  double lower_cut() const { return lower_cut_; }
1072  double upper_cut() const { return upper_cut_; }
1073 
1074  void local_passes(std::map<const VarBase *, std::vector<bool> > &passes,
1075  const std::map<const VarBase *, std::vector<bool> > *const previous_passes = nullptr) const;
1076  using VarBase::print;
1077  void print(std::map<const VarBase *, std::set<std::string> > &cut_strings,
1078  const int step,
1079  Verilog,
1080  const std::map<const VarBase *, std::set<std::string> > *const previous_cut_strings = nullptr) const;
1081  void print(std::map<const VarBase *, std::set<std::string> > &cut_strings,
1082  const int step,
1083  HLS,
1084  const std::map<const VarBase *, std::set<std::string> > *const previous_cut_strings = nullptr) const;
1085 
1086  void set_parent_flag(VarFlag *parent_flag, const bool call_add_cut);
1088  void set_cut_var(VarBase *cut_var, const bool call_add_cut = true);
1089 
1090  protected:
1091  double lower_cut_;
1092  double upper_cut_;
1094  };
1095 
1096  class VarFlag : public VarBase {
1097  public:
1098  template <class... Args>
1100  : VarBase(globals, name, nullptr, nullptr, nullptr, 0) {
1101  op_ = "flag";
1102  nbits_ = 1;
1103  add_cuts(cut, args...);
1104  }
1105 
1106  template <class... Args>
1107  void add_cuts(VarBase *cut, Args... args) {
1108  add_cut(cut);
1109  add_cuts(args...);
1110  }
1111 
1113 
1114  void add_cut(VarBase *cut, const bool call_set_parent_flag = true);
1115 
1116  void calculate_step();
1117  bool passes();
1118  void print(std::ofstream &fs, Verilog, int l1 = 0, int l2 = 0, int l3 = 0) override;
1119  void print(std::ofstream &fs, HLS, int l1 = 0, int l2 = 0, int l3 = 0) override;
1120  };
1121 }; // namespace trklet
1122 #endif
void set_cut_var(VarBase *cut_var, const bool call_add_cut=true)
Definition: imath.cc:365
VarShiftround(imathGlobals *globals, std::string name, VarBase *p1, int shift)
Definition: imath.h:717
int * LUT
Definition: imath.h:1052
Log< level::Info, true > LogVerbatim
std::string name() const
Definition: imath.h:208
int latency_
Definition: imath.h:302
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
void calcDebug(int debug_level, long int ival_prev, bool &all_ok)
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
static void verilog_print(const std::vector< VarBase *> &v, std::ofstream &fs)
Definition: imath.h:275
double fval() const
Definition: imath.h:213
static void hls_print(const std::vector< VarBase *> &v, std::ofstream &fs)
Definition: imath.h:276
int gen_inv(int i)
Definition: imath.h:1024
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
void pipe_increment()
Definition: imath.h:272
void analyze()
Definition: imath.cc:29
VarFlag * parent_flag_
Definition: imath.h:1093
VarDef(imathGlobals *globals, std::string name, VarBase *p)
Definition: imath.h:488
~VarMult() override=default
void inputs(std::vector< VarBase *> *vd)
Definition: imath.cc:205
int pipe_counter()
Definition: imath.h:271
void add_cut(VarCut *cut, const bool call_set_cut_var=true)
Definition: imath.cc:359
unsigned int mask_
Definition: imath.h:1047
void local_calculate() override
double val_
Definition: imath.h:307
void print_step(int step, std::ofstream &fs, Verilog)
void local_calculate() override
void add_cuts(VarBase *cut, Args... args)
Definition: imath.h:1107
void print_all(std::ofstream &fs, Verilog)
double range() const
Definition: imath.h:246
int nbits() const
Definition: imath.h:244
VarBase * cut_var()
Definition: imath.cc:388
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
VarFlag(imathGlobals *globals, std::string name, VarBase *cut, Args... args)
Definition: imath.h:1099
~VarTimesC() override=default
VarBase * p1_
Definition: imath.h:298
double offset()
Definition: imath.h:1002
void local_calculate() override
void add_cuts(VarBase *cut)
Definition: imath.h:1112
std::string pipe_delays(const int step)
Definition: imath.cc:184
bool passes()
Definition: imath.cc:395
VarBase * cut_var_
Definition: imath.h:310
double Ioffset()
Definition: imath.h:1003
imathGlobals * globals_
Definition: imath.h:296
VarBase * p2_
Definition: imath.h:299
bool has_delay(int i)
Definition: imath.cc:165
void set_fval(double fval)
Definition: imath.h:494
std::string kstring() const
Definition: imath.cc:18
VarDef(imathGlobals *globals, std::string name, std::string units, double fmax, double K)
Definition: imath.h:469
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
assert(be >=bs)
~VarAdd() override=default
~VarParam() override=default
std::vector< int > pipe_delays_
Definition: imath.h:317
void print(std::map< const VarBase *, std::set< std::string > > &cut_strings, const int step, Verilog, const std::map< const VarBase *, std::set< std::string > > *const previous_cut_strings=nullptr) const
static struct trklet::VarBase::Verilog verilog
VarInv(imathGlobals *globals, std::string name, VarBase *p1, double offset, int nbits, int n, unsigned int shift, mode m, int nbaddr=-1)
Definition: imath.h:960
int shift() const
Definition: imath.h:248
int ival_to_addr(int ival)
Definition: imath.h:1012
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(imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, VarBase *p3, int l)
Definition: imath.h:162
void local_calculate() override
VarBase * p3_
Definition: imath.h:300
VarSubtract(imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, double range=-1, int nmax=18)
Definition: imath.h:601
std::string op_
Definition: imath.h:301
int Nelements_
Definition: imath.h:1049
VarShift(imathGlobals *globals, std::string name, VarBase *p1, int shift)
Definition: imath.h:738
VarAdd(imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, double range=-1, int nmax=18)
Definition: imath.h:514
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
void initLUT(double offset)
Definition: imath.cc:142
VarParam(imathGlobals *globals, std::string name, std::string units, double fval, double K)
Definition: imath.h:428
double offset_
Definition: imath.h:1043
void local_calculate() override
#define MULT_LATENCY
Definition: imath.h:140
virtual void local_calculate()
Definition: imath.h:255
double lower_cut_
Definition: imath.h:1091
bool local_passes() const
Definition: imath.cc:315
~VarShift() override=default
int n0
Definition: AMPTWrapper.h:44
void set_fval(double fval)
Definition: imath.h:449
unsigned int ashift_
Definition: imath.h:1048
VarBase * p1() const
Definition: imath.h:210
std::map< std::string, int > Kmap() const
Definition: imath.h:245
void local_calculate() override
#define LUT_LATENCY
Definition: imath.h:141
void local_calculate() override
~VarSubtract() override=default
int step() const
Definition: imath.h:251
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
std::string op() const
Definition: imath.h:209
~VarShiftround() override=default
int latency() const
Definition: imath.h:252
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
void dump_msg()
Definition: imath.cc:96
VarAdjustK(imathGlobals *globals, std::string name, VarBase *p1, double Knew, double epsilon=1e-5, bool do_assert=false, int nbits=-1)
Definition: imath.h:338
VarNounits(imathGlobals *globals, std::string name, VarBase *p1, int ps=17)
Definition: imath.h:689
void local_calculate() override
double maxval() const
Definition: imath.h:231
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
VarBase * p3() const
Definition: imath.h:212
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
#define DSP_LATENCY
Definition: imath.h:142
void local_calculate() override
virtual void print(std::ofstream &fs, HLS, int l1=0, int l2=0, int l3=0)
Definition: imath.h:260
double K() const
Definition: imath.h:247
void local_calculate() override
double minval_
Definition: imath.h:323
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
virtual void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0)
Definition: imath.h:257
static struct trklet::VarBase::HLS hls
bool readytoprint_
Definition: imath.h:320
void add_latency(unsigned int l)
Definition: imath.h:253
void set_mode(mode m)
Definition: imath.h:1000
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
~VarDSPPostadd() override=default
void add_cut(VarBase *cut, const bool call_set_parent_flag=true)
Definition: imath.cc:373
VarDSPPostadd(imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, VarBase *p3, double range=-1, int nmax=18)
Definition: imath.h:852
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
void print_truncation(std::string &t, const std::string &o1, const int ps, Verilog) const
int pipe_counter_
Definition: imath.h:316
VarAdjustKR(imathGlobals *globals, std::string name, VarBase *p1, double Knew, double epsilon=1e-5, bool do_assert=false, int nbits=-1)
Definition: imath.h:379
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
VarBase * p2() const
Definition: imath.h:211
static void design_print(const std::vector< VarBase *> &v, std::ofstream &fs, Verilog)
VarCut(imathGlobals *globals, double lower_cut, double upper_cut)
Definition: imath.h:1057
void reset()
Definition: imath.h:236
~VarCut() override=default
double maxval_
Definition: imath.h:324
void local_calculate() override
~VarAdjustK() override=default
~VarNeg() override=default
VarTimesC(imathGlobals *globals, std::string name, VarBase *p1, double cF, int ps=17)
Definition: imath.h:772
double lower_cut() const
Definition: imath.h:1071
void set_ival(int ival)
Definition: imath.h:457
TString units(TString variable, Char_t axis)
VarCut(imathGlobals *globals, VarBase *cut_var, double lower_cut, double upper_cut)
Definition: imath.h:1065
double K_
Definition: imath.h:313
double cF_
Definition: imath.h:800
void set_ival(int ival)
Definition: imath.h:502
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
int shift1
Definition: imath.h:595
double minval() const
Definition: imath.h:230
VarMult(imathGlobals *globals, std::string name, VarBase *p1, VarBase *p2, double range=-1, int nmax=18)
Definition: imath.h:805
~VarAdjustKR() override=default
~VarInv() override
Definition: imath.h:998
int shift2
Definition: imath.h:596
bool readytoanalyze_
Definition: imath.h:319
VarNeg(imathGlobals *globals, std::string name, VarBase *p1)
Definition: imath.h:758
~VarDef() override=default
virtual ~VarBase()
Definition: imath.h:192
VarParam(imathGlobals *globals, std::string name, double fval, int nbits)
Definition: imath.h:418
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
std::string dump()
Definition: imath.cc:78
step
Definition: StallMonitor.cc:83
bool usedasinput_
Definition: imath.h:321
void writeLUT(std::ofstream &fs) const
Definition: imath.h:1008
std::vector< unsigned short int > LUT
Definition: DTTracoLUTs.h:31
unsigned int shift_
Definition: imath.h:1046
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
double fval_
Definition: imath.h:305
VarFlag * parent_flag()
Definition: imath.h:1087
void add_delay(int i)
Definition: imath.h:273
~VarNounits() override=default
bool calculate(int debug_level=0)
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:29
void print(std::ofstream &fs, Verilog, int l1=0, int l2=0, int l3=0) override
int bitShift(int num, int bits)
Definition: BitShift.h:6
void print_cuts(std::map< const VarBase *, std::set< std::string > > &cut_strings, const int step, Verilog, const std::map< const VarBase *, std::set< std::string > > *const previous_cut_strings=nullptr) const
void local_calculate() override