CMS 3D CMS Logo

LutNetworkFixedPointRegression2Outputs.h
Go to the documentation of this file.
1 /*
2  * LutNetworkFixedPointRegression2Outputs.h
3  *
4  * Created on: April 13, 2021
5  * Author: Karol Bunkowski, kbunkow@cern.ch
6  */
7 
8 #ifndef L1Trigger_L1TMuonOverlapPhase2_LutNetworkFixedPointRegression2Outputs_h
9 #define L1Trigger_L1TMuonOverlapPhase2_LutNetworkFixedPointRegression2Outputs_h
10 
12 
13 #include "ap_int.h"
14 
16 
17 #include <cmath>
18 
19 #include <boost/property_tree/ptree.hpp>
20 #include <boost/property_tree/xml_parser.hpp>
21 
22 namespace lutNN {
23 
24  //_I - number of integer bits in the ap_ufixed, _F - number of fractional bits in the ap_ufixed
25  //the network has two outputs, and since each output can have different range, the LUTs in the last layer have different I and F
26  template <int input_I,
27  int input_F,
28  std::size_t inputSize,
29  int layer1_lut_I,
30  int layer1_lut_F,
31  int layer1_neurons,
32  int layer1_output_I, //to the layer1 output the bias is added to make the layer1 input
33  int layer2_input_I,
34  int layer2_lut_I,
35  int layer2_lut_F,
36  int layer2_neurons,
37  int layer3_input_I,
39  int layer3_0_lut_I,
40  int layer3_0_lut_F,
41  int output0_I,
42  int output0_F,
44  int layer3_1_lut_I,
45  int layer3_1_lut_F,
46  int output1_I,
47  int output1_F>
49  public:
52 
53  std::cout << "LutNetworkFixedPoint" << std::endl;
54  lutLayer1.setName("lutLayer1");
55  lutLayer2.setName("lutLayer2");
56  lutLayer3_0.setName("lutLayer3_0");
57  lutLayer3_1.setName("lutLayer3_1");
58  };
59 
61 
65 
66  static constexpr unsigned int noHitCntShift = layer1_output_I; //FIXME should be layer1_output_I ???
67 
69 
79 
81 
87  1,
88  output0_I>
90  LutLayer3_0 lutLayer3_0; //"lutLayer3_0"
91 
97  1,
98  output1_I>
100  LutLayer3_1 lutLayer3_1; //"lutLayer3_1"
101 
104  auto& layer1Out = lutLayer1.getOutWithOffset();
105 
106  std::array<ap_ufixed<layer2_input_I + layer2_input_F, layer2_input_I, AP_TRN, AP_SAT>, layer1_neurons>
107  layer1OutWithBias;
108  for (unsigned int i = 0; i < layer1Out.size(); i++) {
109  layer1OutWithBias[i] = layer1Out[i] + layer1Bias;
110  }
111 
112  lutLayer2.runWithInterpolation(layer1OutWithBias);
113  auto& layer2Out = lutLayer2.getOutWithOffset();
114 
115  typename LutLayer3_0::inputArrayType lutLayer3_0_input;
116  std::copy(layer2Out.begin(), layer2Out.begin() + lutLayer3_0_input.size(), lutLayer3_0_input.begin());
117 
118  typename LutLayer3_1::inputArrayType lutLayer3_1_input;
119  std::copy(layer2Out.begin() + lutLayer3_0_input.size(), layer2Out.end(), lutLayer3_1_input.begin());
120 
121  lutLayer3_0.runWithInterpolation(lutLayer3_0_input);
122  lutLayer3_1.runWithInterpolation(lutLayer3_1_input);
123  }
124 
125  void run(std::vector<float>& inputs, float noHitVal, std::vector<double>& nnResult) override {
126  unsigned int noHitsCnt = 0;
127  for (unsigned int iInput = 0; iInput < inputs.size(); iInput++) {
128  inputArray[iInput] = inputs[iInput];
129  if (inputs[iInput] == noHitVal)
130  noHitsCnt++;
131  }
132 
133  unsigned int bias = (noHitsCnt << noHitCntShift);
134 
135  //layer1Bias switches the input of the layer2 (i.e. output of the layer1) do different regions in the LUTs
136  //depending on the number of layers without hits
137  layer1Bias = bias;
138 
140 
141  //output0_I goes to the declaration of the lutLayer3_0, but it does not matter, as it is used only for the outputArray
142  //auto layer3_0_out = ap_ufixed<output0_I+output0_F, output0_I, AP_RND_CONV, AP_SAT>(lutLayer3_0.getLutOutSum()[0]); //TODO should be AP_RND_CONV rather, but it affect the rate
143  //auto layer3_1_out = ap_fixed <output1_I+output1_F, output1_I, AP_RND_CONV, AP_SAT>(lutLayer3_1.getLutOutSum()[0]); //here layer3_0_out has size 1
144  auto layer3_0_out = lutLayer3_0.getLutOutSum()[0]; //here layer3_0_out has size 1
145  auto layer3_1_out = lutLayer3_1.getLutOutSum()[0]; //here layer3_0_out has size 1
146 
147  nnResult[0] = layer3_0_out.to_float();
148  nnResult[1] = layer3_1_out.to_float();
149  LogTrace("l1tOmtfEventPrint") << "layer3_0_out[0] " << layer3_0_out[0] << " layer3_1_out[0] " << layer3_1_out[0]
150  << std::endl;
151  }
152 
153  //pt in the hardware scale, ptGeV = (ptHw -1) / 2
154  int getCalibratedHwPt() override {
155  auto lutAddr = ap_ufixed<output0_I + output0_F + output0_F, output0_I + output0_F, AP_RND_CONV, AP_SAT>(
157  lutAddr = lutAddr << output0_F;
158  //std::cout<<"lutLayer3_0.getLutOutSum()[0] "<<lutLayer3_0.getLutOutSum()[0]<<" lutAddr.to_uint() "<<lutAddr.to_uint()<<" ptCalibrationArray[lutAddr] "<<ptCalibrationArray[lutAddr.to_uint()]<<std::endl;
159  return ptCalibrationArray[lutAddr.to_uint()].to_uint();
160  }
161 
162  void save(const std::string& filename) override {
163  // Create an empty property tree object.
164  boost::property_tree::ptree tree;
165 
170 
175 
176  int size = ptCalibrationArray.size();
177  std::string key = "LutNetworkFixedPointRegression2Outputs.ptCalibrationArray";
178  PUT_VAR(tree, key, size)
179  std::ostringstream ostr;
180  for (auto& a : ptCalibrationArray) {
181  ostr << a.to_uint() << ", ";
182  }
183  tree.put(key + ".values", ostr.str());
184 
186  tree,
187  std::locale(),
188  boost::property_tree::xml_parser::xml_writer_make_settings<std::string>(' ', 2));
189  }
190 
191  void load(const std::string& filename) override {
192  // Create an empty property tree object.
193  boost::property_tree::ptree tree;
194 
195  boost::property_tree::read_xml(filename, tree);
196 
201 
206 
207  std::string key = "LutNetworkFixedPointRegression2Outputs.ptCalibrationArray";
208  int size = ptCalibrationArray.size();
209  CHECK_VAR(tree, key, size)
210 
211  auto str = tree.get<std::string>(key + ".values");
212 
213  std::stringstream ss(str);
215 
216  for (auto& a : ptCalibrationArray) {
217  if (std::getline(ss, item, ',')) {
218  a = std::stoul(item, nullptr, 10);
219  } else {
220  throw std::runtime_error(
221  "LutNetworkFixedPointRegression2Outputs::read: number of items get from file is smaller than lut size");
222  }
223  }
224  }
225 
227 
228  private:
229  std::array<ap_ufixed<LutLayer1::input_W, input_I, AP_TRN, AP_SAT>, inputSize> inputArray;
230  ap_uint<layer2_input_I> layer1Bias;
231 
232  //ptCalibrationArray size should be 1024, the LSB of the input 0.25 GeV,
233  //the output is int, with range 0...511, the LSB of output 0.5 GeV
234  std::array<ap_uint<9>, 1 << (output0_I + output0_F)> ptCalibrationArray;
235 
236  std::string name = "LutNetworkFixedPointRegression2Outputs";
237  };
238 
239 } /* namespace lutNN */
240 
241 #endif /* L1Trigger_L1TMuonOverlapPhase2_LutNetworkFixedPointRegression2Outputs_h */
static constexpr int output1_F
#define PUT_VAR(tree, keyPath, var)
static constexpr int layer3_1_inputCnt
std::array< ap_ufixed< LutLayer1::input_W, input_I, AP_TRN, AP_SAT >, inputSize > inputArray
static constexpr int layer1_neurons
lutSumArrayType & runWithInterpolation(const inputArrayType &inputArray)
static constexpr int output1_I
LutNeuronLayerFixedPoint< layer2_input_I, layer2_input_F, layer1_neurons, layer2_lut_I, layer2_lut_F, layer2_neurons, layer3_input_I > LutLayer2
static constexpr int layer2_lut_I
static constexpr int layer1_lut_F
#define LogTrace(id)
void load(boost::property_tree::ptree &tree, std::string keyPath)
static constexpr int layer3_0_lut_I
LutNeuronLayerFixedPoint< input_I, input_F, inputSize, layer1_lut_I, layer1_lut_F, layer1_neurons, layer1_output_I > LutLayer1
static constexpr int layer3_1_lut_I
void run(std::vector< float > &inputs, float noHitVal, std::vector< double > &nnResult) override
std::array< ap_uint< 9 >, 1<<(output0_I+output0_F)> ptCalibrationArray
LutNeuronLayerFixedPoint< layer3_input_I, layer3_input_F, layer3_0_inputCnt, layer3_0_lut_I, layer3_0_lut_F, 1, output0_I > LutLayer3_0
key
prepare the HTCondor submission files and eventually submit them
def write_xml(scenario, fileName)
static constexpr int input_I
static constexpr int layer3_0_lut_F
static constexpr int layer1_output_I
static constexpr int layer2_input_I
static constexpr int layer2_neurons
LutNeuronLayerFixedPoint< layer3_input_I, layer3_input_F, layer3_1_inputCnt, layer3_1_lut_I, layer3_1_lut_F, 1, output1_I > LutLayer3_1
static constexpr int layer1_lut_I
static constexpr int input_F
static constexpr int layer3_input_I
void save(boost::property_tree::ptree &tree, std::string keyPath)
double a
Definition: hdecay.h:121
static constexpr int layer3_0_inputCnt
static constexpr int output0_I
#define CHECK_VAR(tree, keyPath, var)
static constexpr int layer2_lut_F
static constexpr int output0_F
static constexpr int layer3_1_lut_F
Definition: tree.py:1
#define str(s)