File indexing completed on 2024-05-29 04:20:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef L1Trigger_L1TMuonOverlapPhase2_LutNeuronlayerFixedPoint_h
0011 #define L1Trigger_L1TMuonOverlapPhase2_LutNeuronlayerFixedPoint_h
0012
0013 #include <ap_fixed.h>
0014 #include <ap_int.h>
0015 #include <array>
0016 #include <limits>
0017 #include <iomanip>
0018 #include <cassert>
0019
0020 #include <boost/property_tree/ptree.hpp>
0021
0022 #include "L1Trigger/L1TMuonOverlapPhase2/interface/LutNetworkFixedPointCommon.h"
0023 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0024 #include "FWCore/Utilities/interface/Exception.h"
0025
0026 namespace lutNN {
0027
0028 constexpr size_t floorlog2(size_t i) {
0029 if (!(i > 0))
0030 throw cms::Exception("Incorrect input")
0031 << "Argument of floorlog2 must be grater than 0, while " << i << " used.\n";
0032 return i == 1 ? 0 : 1 + floorlog2(i >> 1);
0033 }
0034 constexpr size_t ceillog2(size_t i) {
0035 if (!(i > 0))
0036 throw cms::Exception("Incorrect input")
0037 << "Argument of ceillog2 must be grater than 0, while " << i << " used.\n";
0038 return i == 1 ? 0 : floorlog2(i - 1) + 1;
0039 }
0040
0041 template <int input_I, int input_F, size_t inputSize, int lut_I, int lut_F, int neurons, int output_I>
0042 class LutNeuronLayerFixedPoint {
0043 public:
0044 static constexpr int input_W = input_I + input_F;
0045 static constexpr int lut_W = lut_I + lut_F;
0046
0047
0048
0049 static constexpr int lutOutSum_I = lut_I + ceillog2(inputSize);
0050 static constexpr int lutOutSum_W = lutOutSum_I + lut_F;
0051
0052 static constexpr int output_W = output_I + lut_F;
0053
0054
0055 static constexpr size_t lutSize = 1 << input_I;
0056
0057 typedef std::array<ap_ufixed<input_W, input_I, AP_TRN, AP_SAT>, inputSize> inputArrayType;
0058
0059 typedef std::array<ap_fixed<lutOutSum_W, lutOutSum_I>, neurons> lutSumArrayType;
0060
0061 LutNeuronLayerFixedPoint() {
0062
0063
0064 LogTrace("l1tOmtfEventPrint") << "Constructing LutNeuronLayerFixedPoint " << name << "\n input_I "
0065 << std::setw(2) << input_I << " input_F " << std::setw(2) << input_F
0066 << " input_W " << std::setw(2) << input_W << " inputSize " << std::setw(2)
0067 << inputSize << "\n lut_I " << std::setw(2) << lut_I << " lut_F "
0068 << std::setw(2) << lut_F << " lut_W " << std::setw(2) << lut_W << " lutSize "
0069 << std::setw(2) << lutSize << "\n lutOutSum_I " << std::setw(2) << lutOutSum_I
0070 << " lutOutSum_W " << std::setw(2) << lutOutSum_W << "\n output_I "
0071 << std::setw(2) << output_I << " output_W " << std::setw(2) << output_W
0072 << "\n neurons " << std::setw(2) << neurons << "\n outOffset " << outOffset << " = "
0073 << std::hex << outOffset << " width " << outOffset.width << std::dec;
0074 }
0075
0076 virtual ~LutNeuronLayerFixedPoint() {}
0077
0078 void setName(std::string name) { this->name = name; }
0079
0080 auto& getLutArray() { return lutArray; }
0081
0082 void setLutArray(
0083 const std::array<std::array<std::array<ap_fixed<output_W, output_I>, lutSize>, neurons>, inputSize>& lutArray) {
0084 this->lutArray = lutArray;
0085 }
0086
0087 void save(boost::property_tree::ptree& tree, std::string keyPath) {
0088 PUT_VAR(tree, keyPath + "." + name, input_I)
0089 PUT_VAR(tree, keyPath + "." + name, input_F)
0090 PUT_VAR(tree, keyPath + "." + name, inputSize)
0091 PUT_VAR(tree, keyPath + "." + name, lut_I)
0092 PUT_VAR(tree, keyPath + "." + name, lut_F)
0093 PUT_VAR(tree, keyPath + "." + name, neurons)
0094 PUT_VAR(tree, keyPath + "." + name, output_I)
0095
0096 for (unsigned int iInput = 0; iInput < lutArray.size(); iInput++) {
0097 for (unsigned int iNeuron = 0; iNeuron < lutArray[iInput].size(); iNeuron++) {
0098 auto& lut = lutArray.at(iInput).at(iNeuron);
0099 std::ostringstream ostr;
0100 for (auto& a : lut) {
0101 ostr << std::fixed << std::setprecision(19) << a.to_float() << ", ";
0102 }
0103 tree.put(keyPath + "." + name + ".lutArray." + std::to_string(iInput) + "." + std::to_string(iNeuron),
0104 ostr.str());
0105 }
0106 }
0107 }
0108
0109 void load(boost::property_tree::ptree& tree, std::string keyPath) {
0110 CHECK_VAR(tree, keyPath + "." + name, input_I)
0111 CHECK_VAR(tree, keyPath + "." + name, input_F)
0112 CHECK_VAR(tree, keyPath + "." + name, inputSize)
0113 CHECK_VAR(tree, keyPath + "." + name, lut_I)
0114 CHECK_VAR(tree, keyPath + "." + name, lut_F)
0115 CHECK_VAR(tree, keyPath + "." + name, neurons)
0116 CHECK_VAR(tree, keyPath + "." + name, output_I)
0117
0118 for (unsigned int iInput = 0; iInput < lutArray.size(); iInput++) {
0119 for (unsigned int iNeuron = 0; iNeuron < lutArray[iInput].size(); iNeuron++) {
0120 auto& lut = lutArray.at(iInput).at(iNeuron);
0121 auto str = tree.get<std::string>(keyPath + "." + name + ".lutArray." + std::to_string(iInput) + "." +
0122 std::to_string(iNeuron));
0123
0124 std::stringstream ss(str);
0125 std::string item;
0126
0127 for (auto& a : lut) {
0128 if (std::getline(ss, item, ',')) {
0129 a = std::stof(item, nullptr);
0130 } else {
0131 throw std::runtime_error(
0132 "LutNeuronLayerFixedPoint::read: number of items get from file is smaller than lut size");
0133 }
0134 }
0135 }
0136 }
0137 }
0138
0139 lutSumArrayType& runWithInterpolation(const inputArrayType& inputArray) {
0140 for (unsigned int iNeuron = 0; iNeuron < lutOutSumArray.size(); iNeuron++) {
0141 auto& lutOutSum = lutOutSumArray.at(iNeuron);
0142 lutOutSum = 0;
0143 for (unsigned int iInput = 0; iInput < inputArray.size(); iInput++) {
0144 auto address = inputArray.at(iInput).to_uint();
0145 auto& lut = lutArray.at(iInput).at(iNeuron);
0146
0147 auto addresPlus1 = address + 1;
0148 if (addresPlus1 >= lut.size())
0149 addresPlus1 = address;
0150
0151 auto derivative = lut.at(addresPlus1) - lut.at(address);
0152
0153
0154 ap_ufixed<input_W - input_I, 0> fractionalPart = inputArray.at(iInput);
0155
0156 auto result = lut.at(address) + fractionalPart * derivative;
0157 lutOutSum += result;
0158 }
0159
0160 lutOutSumArray.at(iNeuron) = lutOutSum;
0161 }
0162
0163 return lutOutSumArray;
0164 }
0165
0166
0167 auto& getLutOutSum() { return lutOutSumArray; }
0168
0169
0170
0171 auto& getOutWithOffset() {
0172 for (unsigned int iOut = 0; iOut < lutOutSumArray.size(); iOut++) {
0173 outputArray[iOut] = lutOutSumArray[iOut] + outOffset;
0174 }
0175
0176 return outputArray;
0177 }
0178
0179 auto getName() { return name; }
0180
0181 private:
0182 lutSumArrayType lutOutSumArray;
0183 std::array<ap_ufixed<output_W, output_I, AP_TRN, AP_SAT>, neurons> outputArray;
0184
0185 ap_uint<output_I> outOffset = 1 << (output_I - 1);
0186
0187 std::array<std::array<std::array<ap_fixed<lut_W, lut_I>, lutSize>, neurons>, inputSize>
0188 lutArray;
0189
0190 std::string name;
0191 };
0192
0193 }
0194
0195 #endif