CMS 3D CMS Logo

l1tGTSingleInOutLUT.py
Go to the documentation of this file.
1 """
2 This computes the most optimal COS_PHI_LUT and COSH_ETA_LUT. Call
3 :func:`~l1tGTSingleInOutLUT.SingleInOutLUT.export` to export the
4 generated LUT.
5 """
6 
7 import FWCore.ParameterSet.Config as cms
8 from L1Trigger.Phase2L1GT.l1tGTScales import scale_parameter
9 from statistics import mean, median, stdev
10 import math
11 
12 
14 
15  def __init__(self, width_in, unused_lsbs, lsb, output_scale_factor, operation, start_value=0, label=""):
16  self.debug_txt = ""
17  input_scale_factor = 2**unused_lsbs * lsb
18  self.unused_lsbs = unused_lsbs
19  self.lsb = lsb
20  signed_output = min([operation(input_scale_factor * (i + 0.5) + start_value)
21  for i in range(2**width_in)]) < 0
22 
23  self.width_out = math.ceil(math.log2(output_scale_factor *
24  max([abs(operation(input_scale_factor * (i + 0.5) + start_value)) for i in range(2**width_in - 1)] +
25  [abs(operation(input_scale_factor * (2**width_in - 1) + start_value))])))
26 
27  if signed_output:
28  self.width_out += 1
29 
30  self.debug_info(
31  "***************************** {} LUT {} *****************************".format(operation.__name__, label))
32  self.debug_info("Depth: {} x {} (addr x data)".format(width_in, self.width_out))
33  self.debug_info("Scale: {}".format(output_scale_factor))
34 
35  self.width_in = width_in
36  self.output_scale_factor = output_scale_factor
37  self.input_scale_factor = input_scale_factor
38  self.operation = operation
39  self.start_value = start_value
40  self.lut = cms.vint32(
41  * ([round(output_scale_factor * operation(input_scale_factor * (i + 0.5) + start_value)) for i in range(2**width_in - 1)]
42  + [round(output_scale_factor * operation(input_scale_factor * (2 ** width_in - 1) + start_value))]))
43 
44  self.print_error()
45 
46  def debug_info(self, msg):
47  self.debug_txt += msg + "\n"
48 
49  def config(self):
50  return cms.PSet(
51  output_scale_factor=cms.double(self.output_scale_factor),
52  unused_lsbs=cms.uint32(self.unused_lsbs),
53  lut=self.lut,
54  max_error=cms.double(self.max_error)
55  )
56 
57  def export(self, filename: str):
58  print(self.debug_txt)
59  with open(filename, "w") as file:
60  for value in self.lut:
61  file.write("{:X}".format(int(value) & ((1 << self.width_out) - 1)
62  ).rjust(math.ceil(self.width_out/4), '0') + "\n")
63 
64  @ staticmethod
65  def optimal_scale_factor(width_in, max_width_out, unused_lsbs, lsb, operation, start_value=0):
66  input_scale_factor = 2**unused_lsbs * lsb
67  scale_factor = (2**max_width_out - 1) / max([abs(operation(input_scale_factor * (i + 0.5) + start_value))
68  for i in range(2**width_in)])
69  return scale_factor
70 
71  def print_error(self):
72  errors = [abs(self.lut[int(i/(2**self.unused_lsbs))]/self.output_scale_factor -
73  self.operation(i * self.lsb + self.start_value)) for i in range(2**(self.width_in + self.unused_lsbs))]
74 
75  self.max_error = max(errors)
76 
77  self.debug_info("Error: {:.5f} +/- {:.5f}, max: {:.5f}, total: {:.5f}, median: {:.5f}".format(
78  mean(errors), stdev(errors), self.max_error, sum(errors), median(errors)))
79 
80  # mass_errors = [errors[i]/(2*self.operation(i * self.lsb + self.start_value)) for i in range(2**(self.width_in + self.unused_lsbs)) ]
81  # self.debug_info("inv mass error: {:.5f} +/- {:.5f}, max: {:.5f}, total: {:.5f}, median: {:.5f}".format(
82  # mean(mass_errors), stdev(mass_errors), max(mass_errors), sum(mass_errors), median(mass_errors)))
83 
84 
85 COS_PHI_IN_WIDTH = 10 # not using 2 lsb and 1 msb (cos(x + pi) = -cos(x), x in [0, pi))
86 COSH_ETA_IN_WIDTH = 11 # not using 2 lsb and 1 msb (splitted LUT)
87 ISOLATION_WIDTH = 11
88 
89 # Since we calculate cosh(dEta) - cos(dPhi); both must be on the same scale the difference should fit into 17 bits for the DSP
90 optimal_scale_factor = math.floor(
91  (2**17 - 1) / (math.cosh((2**(COSH_ETA_IN_WIDTH + 2) - 1)*scale_parameter.eta_lsb.value()) + 1))
92 
93 COS_PHI_LUT = SingleInOutLUT(
94  COS_PHI_IN_WIDTH, 2, scale_parameter.phi_lsb.value(), optimal_scale_factor, math.cos)
95 
96 # eta in [0, 2pi)
97 COSH_ETA_LUT = SingleInOutLUT(
98  COSH_ETA_IN_WIDTH, 2, scale_parameter.eta_lsb.value(), optimal_scale_factor, math.cosh, 0, "[0, 2pi)")
99 
100 # eta in [2pi, 4pi)
101 COSH_ETA_LUT_2 = SingleInOutLUT(
102  COSH_ETA_IN_WIDTH, 2, scale_parameter.eta_lsb.value(),
103  SingleInOutLUT.optimal_scale_factor(
104  COSH_ETA_IN_WIDTH, 17, 2, scale_parameter.eta_lsb.value(), math.cosh, 2**13 * scale_parameter.eta_lsb.value()),
105  math.cosh, 2**13 * scale_parameter.eta_lsb.value(), "[2pi, 4pi)")
def optimal_scale_factor(width_in, max_width_out, unused_lsbs, lsb, operation, start_value=0)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
T median(std::vector< T > values)
Definition: median.h:16
def stdev(xlist)
Definition: plotscripts.py:69
def __init__(self, width_in, unused_lsbs, lsb, output_scale_factor, operation, start_value=0, label="")