diff --git a/.gitignore b/.gitignore
index 89543e26bf3d1..20e86694c3ab4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,6 @@ __init__.py
# ignore files under the top level $CMSSW_BASE/src directory, but not its subdirectories
/*
!/*/
+
+
+L1Trigger/L1THGCalUtilities/test/HGCS2*.txt
diff --git a/DataFormats/L1THGCal/BuildFile.xml b/DataFormats/L1THGCal/BuildFile.xml
index aaba3b9a72339..a8ae4c639bf07 100644
--- a/DataFormats/L1THGCal/BuildFile.xml
+++ b/DataFormats/L1THGCal/BuildFile.xml
@@ -7,6 +7,7 @@
+
diff --git a/DataFormats/L1THGCal/interface/HGCalClusterT.h b/DataFormats/L1THGCal/interface/HGCalClusterT.h
index cddd611ce0779..d27d33d7af70a 100644
--- a/DataFormats/L1THGCal/interface/HGCalClusterT.h
+++ b/DataFormats/L1THGCal/interface/HGCalClusterT.h
@@ -179,6 +179,69 @@ namespace l1t {
void triggerCells67percent(float triggerCells67percent) { triggerCells67percent_ = triggerCells67percent; }
void triggerCells90percent(float triggerCells90percent) { triggerCells90percent_ = triggerCells90percent; }
+ // Firmware-specific cluster properties
+ unsigned long int hw_sigma_e_quotient() const { return hw_sigma_e_quotient_; }
+ unsigned long int hw_sigma_e_fraction() const { return hw_sigma_e_fraction_; }
+ unsigned long int hw_mean_z_quotient() const { return hw_mean_z_quotient_; }
+ unsigned long int hw_mean_z_fraction() const { return hw_mean_z_fraction_; }
+ unsigned long int hw_mean_phi_quotient() const { return hw_mean_phi_quotient_; }
+ unsigned long int hw_mean_phi_fraction() const { return hw_mean_phi_fraction_; }
+ unsigned long int hw_mean_eta_quotient() const { return hw_mean_eta_quotient_; }
+ unsigned long int hw_mean_eta_fraction() const { return hw_mean_eta_fraction_; }
+ unsigned long int hw_mean_roz_quotient() const { return hw_mean_roz_quotient_; }
+ unsigned long int hw_mean_roz_fraction() const { return hw_mean_roz_fraction_; }
+ unsigned long int hw_sigma_z_quotient() const { return hw_sigma_z_quotient_; }
+ unsigned long int hw_sigma_z_fraction() const { return hw_sigma_z_fraction_; }
+ unsigned long int hw_sigma_phi_quotient() const { return hw_sigma_phi_quotient_; }
+ unsigned long int hw_sigma_phi_fraction() const { return hw_sigma_phi_fraction_; }
+ unsigned long int hw_sigma_eta_quotient() const { return hw_sigma_eta_quotient_; }
+ unsigned long int hw_sigma_eta_fraction() const { return hw_sigma_eta_fraction_; }
+ unsigned long int hw_sigma_roz_quotient() const { return hw_sigma_roz_quotient_; }
+ unsigned long int hw_sigma_roz_fraction() const { return hw_sigma_roz_fraction_; }
+ unsigned long int hw_e_em_over_e_quotient() const { return hw_e_em_over_e_quotient_; }
+ unsigned long int hw_e_em_over_e_fraction() const { return hw_e_em_over_e_fraction_; }
+ unsigned long int hw_e_em_core_over_e_em_quotient() const { return hw_e_em_core_over_e_em_quotient_; }
+ unsigned long int hw_e_em_core_over_e_em_fraction() const { return hw_e_em_core_over_e_em_fraction_; }
+ unsigned long int hw_e_h_early_over_e_quotient() const { return hw_e_h_early_over_e_quotient_; }
+ unsigned long int hw_e_h_early_over_e_fraction() const { return hw_e_h_early_over_e_fraction_; }
+
+ void hw_sigma_e_quotient(unsigned long int sigma_e_quotient) { hw_sigma_e_quotient_ = sigma_e_quotient; }
+ void hw_sigma_e_fraction(unsigned long int sigma_e_fraction) { hw_sigma_e_fraction_ = sigma_e_fraction; }
+ void hw_mean_z_quotient(unsigned long int mean_z_quotient) { hw_mean_z_quotient_ = mean_z_quotient; }
+ void hw_mean_z_fraction(unsigned long int mean_z_fraction) { hw_mean_z_fraction_ = mean_z_fraction; }
+ void hw_mean_phi_quotient(unsigned long int mean_phi_quotient) { hw_mean_phi_quotient_ = mean_phi_quotient; }
+ void hw_mean_phi_fraction(unsigned long int mean_phi_fraction) { hw_mean_phi_fraction_ = mean_phi_fraction; }
+ void hw_mean_eta_quotient(unsigned long int mean_eta_quotient) { hw_mean_eta_quotient_ = mean_eta_quotient; }
+ void hw_mean_eta_fraction(unsigned long int mean_eta_fraction) { hw_mean_eta_fraction_ = mean_eta_fraction; }
+ void hw_mean_roz_quotient(unsigned long int mean_roz_quotient) { hw_mean_roz_quotient_ = mean_roz_quotient; }
+ void hw_mean_roz_fraction(unsigned long int mean_roz_fraction) { hw_mean_roz_fraction_ = mean_roz_fraction; }
+ void hw_sigma_z_quotient(unsigned long int sigma_z_quotient) { hw_sigma_z_quotient_ = sigma_z_quotient; }
+ void hw_sigma_z_fraction(unsigned long int sigma_z_fraction) { hw_sigma_z_fraction_ = sigma_z_fraction; }
+ void hw_sigma_phi_quotient(unsigned long int sigma_phi_quotient) { hw_sigma_phi_quotient_ = sigma_phi_quotient; }
+ void hw_sigma_phi_fraction(unsigned long int sigma_phi_fraction) { hw_sigma_phi_fraction_ = sigma_phi_fraction; }
+ void hw_sigma_eta_quotient(unsigned long int sigma_eta_quotient) { hw_sigma_eta_quotient_ = sigma_eta_quotient; }
+ void hw_sigma_eta_fraction(unsigned long int sigma_eta_fraction) { hw_sigma_eta_fraction_ = sigma_eta_fraction; }
+ void hw_sigma_roz_quotient(unsigned long int sigma_roz_quotient) { hw_sigma_roz_quotient_ = sigma_roz_quotient; }
+ void hw_sigma_roz_fraction(unsigned long int sigma_roz_fraction) { hw_sigma_roz_fraction_ = sigma_roz_fraction; }
+ void hw_e_em_over_e_quotient(unsigned long int e_em_over_e_quotient) {
+ hw_e_em_over_e_quotient_ = e_em_over_e_quotient;
+ }
+ void hw_e_em_over_e_fraction(unsigned long int e_em_over_e_fraction) {
+ hw_e_em_over_e_fraction_ = e_em_over_e_fraction;
+ }
+ void hw_e_em_core_over_e_em_quotient(unsigned long int e_em_core_over_e_em_quotient) {
+ hw_e_em_core_over_e_em_quotient_ = e_em_core_over_e_em_quotient;
+ }
+ void hw_e_em_core_over_e_em_fraction(unsigned long int e_em_core_over_e_em_fraction) {
+ hw_e_em_core_over_e_em_fraction_ = e_em_core_over_e_em_fraction;
+ }
+ void hw_e_h_early_over_e_quotient(unsigned long int e_h_early_over_e_quotient) {
+ hw_e_h_early_over_e_quotient_ = e_h_early_over_e_quotient;
+ }
+ void hw_e_h_early_over_e_fraction(unsigned long int e_h_early_over_e_fraction) {
+ hw_e_h_early_over_e_fraction_ = e_h_early_over_e_fraction;
+ }
+
/* operators */
bool operator<(const HGCalClusterT& cl) const { return mipPt() < cl.mipPt(); }
bool operator>(const HGCalClusterT& cl) const { return cl < *this; }
@@ -221,6 +284,32 @@ namespace l1t {
float triggerCells67percent_ = 0.;
float triggerCells90percent_ = 0.;
+ // firmware-specific cluster properties
+ unsigned long int hw_sigma_e_quotient_ = 0;
+ unsigned long int hw_sigma_e_fraction_ = 0;
+ unsigned long int hw_mean_z_quotient_ = 0;
+ unsigned long int hw_mean_z_fraction_ = 0;
+ unsigned long int hw_mean_phi_quotient_ = 0;
+ unsigned long int hw_mean_phi_fraction_ = 0;
+ unsigned long int hw_mean_eta_quotient_ = 0;
+ unsigned long int hw_mean_eta_fraction_ = 0;
+ unsigned long int hw_mean_roz_quotient_ = 0;
+ unsigned long int hw_mean_roz_fraction_ = 0;
+ unsigned long int hw_sigma_z_quotient_ = 0;
+ unsigned long int hw_sigma_z_fraction_ = 0;
+ unsigned long int hw_sigma_phi_quotient_ = 0;
+ unsigned long int hw_sigma_phi_fraction_ = 0;
+ unsigned long int hw_sigma_eta_quotient_ = 0;
+ unsigned long int hw_sigma_eta_fraction_ = 0;
+ unsigned long int hw_sigma_roz_quotient_ = 0;
+ unsigned long int hw_sigma_roz_fraction_ = 0;
+ unsigned long int hw_e_em_over_e_quotient_ = 0;
+ unsigned long int hw_e_em_over_e_fraction_ = 0;
+ unsigned long int hw_e_em_core_over_e_em_quotient_ = 0;
+ unsigned long int hw_e_em_core_over_e_em_fraction_ = 0;
+ unsigned long int hw_e_h_early_over_e_quotient_ = 0;
+ unsigned long int hw_e_h_early_over_e_fraction_ = 0;
+
void updateP4AndPosition(const edm::Ptr& c, bool updateCentre = true, float fraction = 1.) {
double cMipt = c->mipPt() * fraction;
double cPt = c->pt() * fraction;
diff --git a/DataFormats/L1THGCal/interface/HGCalCluster_HW.h b/DataFormats/L1THGCal/interface/HGCalCluster_HW.h
new file mode 100644
index 0000000000000..aca57583b4f81
--- /dev/null
+++ b/DataFormats/L1THGCal/interface/HGCalCluster_HW.h
@@ -0,0 +1,294 @@
+#ifndef DataFormats_L1THGCal_HGCalCluster_HW_h
+#define DataFormats_L1THGCal_HGCalCluster_HW_h
+
+#include "DataFormats/L1TParticleFlow/interface/bit_encoding.h"
+
+#include
+// #include
+
+namespace l1thgcfirmware {
+
+ typedef ap_uint<14> e_t; // E, E_EM
+ typedef ap_uint<4> gctbits_t;
+ typedef ap_uint<8> eFraction_t;
+ typedef ap_uint<6> nLayer_t;
+
+ typedef ap_uint<10> eta_t;
+ typedef ap_int<9> phi_t;
+ typedef ap_uint<12> z_t;
+ typedef ap_uint<1> spare_w2_t;
+ typedef ap_uint<10> nTC_t;
+ typedef ap_uint<7> qualFlags_t;
+
+ typedef ap_uint<7> sigma_E_t;
+ typedef ap_uint<13> spare_w3_t;
+ typedef ap_uint<7> sigma_z_t;
+ typedef ap_uint<7> sigma_phi_t;
+ typedef ap_uint<5> sigma_eta_t;
+ typedef ap_uint<7> sigma_roz_t;
+
+ static constexpr int wordLength = 64;
+ static constexpr int nWordsPerCluster = 4;
+ typedef uint64_t ClusterWord;
+ typedef std::array ClusterWords;
+
+ namespace Scales {
+ constexpr float ET_LSB = 1./1024;
+ constexpr float ET_HGCALtoL1_SCALE = 1. / 256;
+ constexpr float ET_L1_LSB = 0.25;
+
+ constexpr int INTPHI_PI = 720;
+ constexpr float ETAPHI_LSB = M_PI / INTPHI_PI;
+ constexpr float Z_LSB = 0.05;
+ constexpr float SIGMA_ROZ_ROZ_LSB = 0.0001920625; // 0.024584/2^(7), max r/z / nBits
+
+ inline float floatEt(e_t et) { return et.to_float() * ET_L1_LSB; }
+ inline float floatEta(eta_t eta) { return eta.to_float() * ETAPHI_LSB; }
+ inline float floatPhi(phi_t phi) { return phi.to_float() * ETAPHI_LSB + M_PI/2; }
+ inline float floatZ(z_t z) { return z.to_float() * Z_LSB; }
+ inline float floatSigmaRozRoz(sigma_roz_t sigmaRozRoz) { return sigmaRozRoz.to_float() * SIGMA_ROZ_ROZ_LSB; }
+
+ inline e_t HGCaltoL1_et(double et) {
+ return round(et * Scales::ET_HGCALtoL1_SCALE);
+ }
+
+ inline z_t HGCaltoL1_z(double z) {
+ return round(z); // Same scale on both sides of interface
+ }
+
+ inline phi_t HGCaltoL1_phi(float phi, bool& saturatedPhi, bool& nominalPhi) {
+ phi_t hw_phi = 0;
+
+ // Temporary fix. First line is what we should use, assuming phi LSB of pi/3456
+ // But steps before CP block don't like this, and put TCs in the wrong bins - to be debugged
+ // So for now, where earlier steps are used to produce input for testing CP block in hardware,
+ // use original LSB (pi/1944) for earlier steps, and convert to CP-block LSB here
+ // const int hw_phi10b = int( round( phi * (5./24) ) ) - 360;
+ const int hw_phi10b = int( round( phi * (3456./1944) * (5./24) ) ) - 360;
+ nominalPhi = ( hw_phi10b < 240 ) && ( hw_phi10b > -241 );
+ if( hw_phi10b > 255 ) {
+ hw_phi = 255;
+ saturatedPhi = true;
+ }
+ else if ( hw_phi10b < -256 ) {
+ hw_phi = -256;
+ saturatedPhi = true;
+ }
+ else {
+ hw_phi = hw_phi10b;
+ saturatedPhi = false;
+ }
+ return hw_phi;
+ }
+
+ inline eFraction_t makeL1EFraction(float num, float denom) {
+ float frac = round(256 * num / denom);
+ if ( frac >= 256. ) frac = 255.;
+ return frac;
+ };
+
+
+ }
+
+
+ struct HGCalCluster_HW {
+
+ // First word
+ e_t e;
+ e_t e_em;
+ gctbits_t gctBits;
+ eFraction_t fractionInCE_E;
+ eFraction_t fractionInCoreCE_E;
+ eFraction_t fractionInEarlyCE_E;
+ nLayer_t firstLayer;
+
+ // Second word
+ eta_t w_eta;
+ phi_t w_phi;
+ z_t w_z;
+ spare_w2_t spare_w2 = 0;
+ nTC_t nTC;
+ qualFlags_t qualFlags;
+
+ // Third word
+ sigma_E_t sigma_E;
+ nLayer_t lastLayer;
+ nLayer_t showerLength;
+ spare_w3_t spare_w3 = 0;
+ sigma_z_t sigma_z;
+ sigma_phi_t sigma_phi;
+ nLayer_t coreShowerLength;
+ sigma_eta_t sigma_eta;
+ sigma_roz_t sigma_roz;
+
+ inline bool operator==(const HGCalCluster_HW &other) const {
+ return e == other.e && e_em == other.e_em && w_eta == other.w_eta && w_phi == other.w_phi && w_z == other.w_z && sigma_roz == other.sigma_roz && fractionInCE_E == other.fractionInCE_E;
+ }
+
+ inline bool operator!=(const HGCalCluster_HW &other) const {
+ return !(*this == other);
+ }
+
+ inline void clear() {
+ e = 0;
+ e_em = 0;
+ gctBits = 0;
+ fractionInCE_E = 0;
+ fractionInCoreCE_E = 0;
+ fractionInEarlyCE_E = 0;
+ firstLayer = 0;
+ w_eta = 0;
+ w_phi = 0;
+ w_z = 0;
+ nTC = 0;
+ qualFlags = 0;
+ sigma_E = 0;
+ lastLayer = 0;
+ showerLength = 0;
+ spare_w3 = 0;
+ sigma_z = 0;
+ sigma_phi = 0;
+ coreShowerLength = 0;
+ sigma_eta = 0;
+ sigma_roz = 0;
+ }
+
+ // float floatE() const { return Scales::floatE(e); }
+ // float floatE_EM() const { return Scales::floatE(e_em); }
+ // float floatFraction() const { return Scales::floatEta(hwEta); }
+
+ static const int BITWIDTH_FIRSTWORD = e_t::width + e_t::width + gctbits_t::width + eFraction_t::width + eFraction_t::width + eFraction_t::width + nLayer_t::width;
+ inline ap_uint pack_firstWord() const {
+ ap_uint ret;
+ unsigned int start = 0;
+ pack_into_bits(ret, start, e);
+ pack_into_bits(ret, start, e_em);
+ pack_into_bits(ret, start, gctBits);
+ pack_into_bits(ret, start, fractionInCE_E);
+ pack_into_bits(ret, start, fractionInCoreCE_E);
+ pack_into_bits(ret, start, fractionInEarlyCE_E);
+ pack_into_bits(ret, start, firstLayer);
+ return ret;
+ }
+
+ static const int BITWIDTH_SECONDWORD = eta_t::width + phi_t::width + z_t::width + spare_w2_t::width + nTC_t::width + qualFlags_t::width;
+ inline ap_uint pack_secondWord() const {
+ ap_uint ret;
+ unsigned int start = 0;
+ pack_into_bits(ret, start, w_eta);
+ pack_into_bits(ret, start, w_phi);
+ pack_into_bits(ret, start, w_z);
+ pack_into_bits(ret, start, spare_w2);
+ pack_into_bits(ret, start, nTC);
+ pack_into_bits(ret, start, qualFlags);
+ return ret;
+ }
+
+ static const int BITWIDTH_THIRDWORD = sigma_E_t::width + nLayer_t::width + nLayer_t::width + spare_w3_t::width + sigma_z_t::width + sigma_phi_t::width + nLayer_t::width + sigma_eta_t::width + sigma_roz_t::width;
+ inline ap_uint pack_thirdWord() const {
+ ap_uint ret;
+ unsigned int start = 0;
+ pack_into_bits(ret, start, sigma_E);
+ pack_into_bits(ret, start, lastLayer);
+ pack_into_bits(ret, start, showerLength);
+ pack_into_bits(ret, start, spare_w3);
+ pack_into_bits(ret, start, sigma_z);
+ pack_into_bits(ret, start, sigma_phi);
+ pack_into_bits(ret, start, coreShowerLength);
+ pack_into_bits(ret, start, sigma_eta);
+ pack_into_bits(ret, start, sigma_roz);
+ return ret;
+ }
+
+ inline ClusterWords pack() const {
+ ClusterWords packed;
+ ap_uint firstWord = this->pack_firstWord();
+ ap_uint secondWord = this->pack_secondWord();
+ ap_uint thirdWord = this->pack_thirdWord();
+ packed[0] = firstWord;
+ packed[1] = secondWord;
+ packed[2] = thirdWord;
+ packed[3] = 0;
+ return packed;
+ }
+
+ inline static void unpack_firstWord(const ap_uint &src, HGCalCluster_HW& cluster) {
+ cluster.initFromBits_firstWord(src);
+ return;
+ }
+
+ inline void initFromBits_firstWord(const ap_uint &src ) {
+ unsigned int start = 0;
+ unpack_from_bits(src, start, e);
+ unpack_from_bits(src, start, e_em);
+ unpack_from_bits(src, start, gctBits);
+ unpack_from_bits(src, start, fractionInCE_E);
+ unpack_from_bits(src, start, fractionInCoreCE_E);
+ unpack_from_bits(src, start, fractionInEarlyCE_E);
+ unpack_from_bits(src, start, firstLayer);
+ }
+
+ inline static void unpack_secondWord(const ap_uint &src, HGCalCluster_HW& cluster) {
+ cluster.initFromBits_secondWord(src);
+ return;
+ }
+
+ inline void initFromBits_secondWord(const ap_uint &src ) {
+ unsigned int start = 0;
+ unpack_from_bits(src, start, w_eta);
+ unpack_from_bits(src, start, w_phi);
+ unpack_from_bits(src, start, w_z);
+ unpack_from_bits(src, start, spare_w2);
+ unpack_from_bits(src, start, nTC);
+ unpack_from_bits(src, start, qualFlags);
+
+ }
+
+ inline static void unpack_thirdWord(const ap_uint &src, HGCalCluster_HW& cluster) {
+ cluster.initFromBits_thirdWord(src);
+ return;
+ }
+
+ inline void initFromBits_thirdWord(const ap_uint &src ) {
+ unsigned int start = 0;
+ unpack_from_bits(src, start, sigma_E);
+ unpack_from_bits(src, start, lastLayer);
+ unpack_from_bits(src, start, showerLength);
+ unpack_from_bits(src, start, spare_w3);
+ unpack_from_bits(src, start, sigma_z);
+ unpack_from_bits(src, start, sigma_phi);
+ unpack_from_bits(src, start, coreShowerLength);
+ unpack_from_bits(src, start, sigma_eta);
+ unpack_from_bits(src, start, sigma_roz);
+ }
+
+
+ inline static HGCalCluster_HW unpack(const ClusterWords &src) {
+ HGCalCluster_HW cluster;
+ ap_uint firstWord = src[0];
+ unpack_firstWord( firstWord, cluster );
+ ap_uint secondWord = src[1];
+ unpack_secondWord( secondWord, cluster );
+ ap_uint thirdWord = src[2];
+ unpack_thirdWord( thirdWord, cluster );
+ return cluster;
+ }
+
+ inline void setGCTBits() {
+ ap_uint<1> gctBit0 = fractionInCE_E > 64;
+ ap_uint<1> gctBit1 = fractionInCoreCE_E > 64;
+ ap_uint<1> gctBit2 = fractionInEarlyCE_E > 64;
+ ap_uint<1> gctBit3 = e_em > 64;
+ gctBits = (gctBit3, gctBit2, gctBit1, gctBit0);
+ }
+
+ inline void setQualityFlags( bool qualFracCE_E, bool qualFracCoreCE_E, bool qualFracEarlyCE_H, bool saturatedTC, unsigned int shapeQuality, bool saturatedPhi, bool nominalPhi ) {
+ qualFlags = (ap_uint<1>(saturatedTC), ap_uint<1>(qualFracCE_E), ap_uint<1>(qualFracCoreCE_E), ap_uint<1>(qualFracEarlyCE_H), ap_uint<1>(shapeQuality), ap_uint<1>(saturatedPhi), ap_uint<1>(nominalPhi));
+ }
+ };
+
+ inline void clear(HGCalCluster_HW &c) { c.clear(); }
+
+} // namespace l1thgcfirmware
+
+#endif
\ No newline at end of file
diff --git a/DataFormats/L1THGCal/interface/HGCalMulticluster.h b/DataFormats/L1THGCal/interface/HGCalMulticluster.h
index 3df4591998e7f..398c04912e8ae 100644
--- a/DataFormats/L1THGCal/interface/HGCalMulticluster.h
+++ b/DataFormats/L1THGCal/interface/HGCalMulticluster.h
@@ -7,6 +7,7 @@
#include "DataFormats/L1THGCal/interface/HGCalCluster.h"
#include
#include
+#include
namespace l1t {
@@ -33,7 +34,7 @@ namespace l1t {
hOverEValid_ = true;
}
- enum EnergyInterpretation { EM = 0 };
+ enum EnergyInterpretation { EM = 0, EM_CORE = 1, H_EARLY = 2 };
void saveEnergyInterpretation(const HGCalMulticluster::EnergyInterpretation eInt, double energy);
@@ -90,6 +91,40 @@ namespace l1t {
float hOverE_;
bool hOverEValid_;
std::map energyInterpretationFractions_;
+
+ public:
+ // Types for firmware representation of cluster data sent to L1T
+ // These are duplicated with those in interface/backend_emulator/HGCalCluster_SA.h
+ // Can we define in one place?
+ static constexpr int wordLength = 64;
+ static constexpr int nWordsPerCluster = 4;
+ typedef uint64_t ClusterWord;
+ typedef std::array ClusterWords;
+ void setHwData( ClusterWords clusterWords ) { hwData_ = clusterWords; }
+ ClusterWords getHwData() const { return hwData_; }
+ void setHwSector( unsigned int sector ) { hwSector_ = sector; }
+ unsigned int getHwSector() const { return hwSector_; }
+ void setHwZSide( int zside ) { hwZSide_ = zside; }
+ int getHwZSide() const { return hwZSide_; }
+
+ // Types for firmware representation of cluster sum data, input to cluster properties step
+ static constexpr int clusterSumWordLength = 64;
+ static constexpr int nWordsPerClusterSum = 8;
+ typedef uint64_t ClusterSumWord;
+ typedef std::array ClusterSumWords;
+ void setHwClusterSumData( ClusterSumWords clusterSumWords ) { hwClusterSumData_ = clusterSumWords; }
+ ClusterSumWords getHwClusterSumData() const { return hwClusterSumData_; }
+
+ private:
+ ClusterWords hwData_;
+ ClusterSumWords hwClusterSumData_;
+ // Store sector number for pattern files
+ // TODO check if detID of emulated cluster always gives same sector
+ // Emulated cluster takes detID of first TC added to it, which is not necessarily a TC in the seed histo bin
+ unsigned int hwSector_;
+ // Safe to take zside from the detID of the emualted cluster
+ // But keep consistent with sector for now
+ int hwZSide_;
};
typedef BXVector HGCalMulticlusterBxCollection;
diff --git a/DataFormats/L1THGCal/src/classes_def.xml b/DataFormats/L1THGCal/src/classes_def.xml
index 0cf6b02cad815..fa1c655b93cf7 100644
--- a/DataFormats/L1THGCal/src/classes_def.xml
+++ b/DataFormats/L1THGCal/src/classes_def.xml
@@ -30,7 +30,8 @@
-
+
+
@@ -47,7 +48,10 @@
-
+
+
+
+
diff --git a/DataFormats/L1TParticleFlow/interface/datatypes.h b/DataFormats/L1TParticleFlow/interface/datatypes.h
index be802bc540b6e..2d791fcd7b362 100644
--- a/DataFormats/L1TParticleFlow/interface/datatypes.h
+++ b/DataFormats/L1TParticleFlow/interface/datatypes.h
@@ -41,9 +41,10 @@ namespace l1ct {
typedef ap_uint<4> egquality_t;
typedef ap_uint<3> stub_t;
typedef ap_ufixed<10, 1, AP_TRN, AP_SAT> srrtot_t;
- typedef ap_uint<8> meanz_t; // mean - MEANZ_OFFSET(= 320 cm)
+ typedef ap_uint<9> meanz_t; // from front face, in cm
typedef ap_ufixed<10, 5, AP_TRN, AP_SAT> hoe_t;
typedef ap_uint<4> redChi2Bin_t;
+ typedef ap_fixed<10, 1, AP_RND_CONV, AP_SAT> id_score_t; // ID score to be between -1 (background) and 1 (signal)
// FIXME: adjust range 10-11bits -> 1/4 - 1/2TeV is probably more than enough for all reasonable use cases
typedef ap_ufixed<11, 9, AP_TRN, AP_SAT> iso_t;
@@ -155,7 +156,7 @@ namespace l1ct {
constexpr float Z0_LSB = 0.05;
constexpr float DXY_LSB = 0.05;
constexpr float PUPPIW_LSB = 1.0 / 256;
- constexpr float MEANZ_OFFSET = 320.;
+ constexpr float MEANZ_LSB = 0.4;
constexpr float SRRTOT_LSB = 0.0019531250; // pow(2, -9)
constexpr unsigned int SRRTOT_SCALE = 64; // pow(2, 6)
constexpr float HOE_LSB = 0.031250000; // pow(2, -5)
@@ -163,8 +164,8 @@ namespace l1ct {
inline float floatPt(pt_t pt) { return pt.to_float(); }
inline float floatPt(dpt_t pt) { return pt.to_float(); }
inline float floatPt(pt2_t pt2) { return pt2.to_float(); }
- inline int intPt(pt_t pt) { return (ap_ufixed<16, 14>(pt) << 2).to_int(); }
- inline int intPt(dpt_t pt) { return (ap_fixed<18, 16>(pt) << 2).to_int(); }
+ inline int intPt(pt_t pt) { return ap_uint(pt.range()).to_int(); }
+ inline int intPt(dpt_t pt) { return ap_int(pt.range()).to_int(); }
inline float floatEta(eta_t eta) { return eta.to_float() * ETAPHI_LSB; }
inline float floatPhi(phi_t phi) { return phi.to_float() * ETAPHI_LSB; }
inline float floatEta(tkdeta_t eta) { return eta.to_float() * ETAPHI_LSB; }
@@ -176,8 +177,9 @@ namespace l1ct {
inline float floatPuppiW(puppiWgt_t puppiw) { return puppiw.to_float() * PUPPIW_LSB; }
inline float floatIso(iso_t iso) { return iso.to_float(); }
inline float floatSrrTot(srrtot_t srrtot) { return srrtot.to_float() / SRRTOT_SCALE; };
- inline float floatMeanZ(meanz_t meanz) { return meanz + MEANZ_OFFSET; };
+ inline float floatMeanZ(meanz_t meanz) { return meanz.to_float() * MEANZ_LSB; };
inline float floatHoe(hoe_t hoe) { return hoe.to_float(); };
+ inline float floatIDScore(id_score_t score) { return score.to_float(); };
inline pt_t makePt(int pt) { return ap_ufixed<16, 14>(pt) >> 2; }
inline dpt_t makeDPt(int dpt) { return ap_fixed<18, 16>(dpt) >> 2; }
@@ -209,7 +211,7 @@ namespace l1ct {
inline int makeDR2FromFloatDR(float dr) { return ceil(dr * dr / ETAPHI_LSB / ETAPHI_LSB); }
inline srrtot_t makeSrrTot(float var) { return srrtot_t(SRRTOT_LSB * round(var * SRRTOT_SCALE / SRRTOT_LSB)); };
- inline meanz_t makeMeanZ(float var) { return round(var - MEANZ_OFFSET); };
+ inline meanz_t makeMeanZ(float var) { return round(var / MEANZ_LSB); };
inline hoe_t makeHoe(float var) { return hoe_t(HOE_LSB * round(var / HOE_LSB)); };
inline float maxAbsEta() { return ((1 << (eta_t::width - 1)) - 1) * ETAPHI_LSB; }
diff --git a/DataFormats/L1TParticleFlow/interface/egamma.h b/DataFormats/L1TParticleFlow/interface/egamma.h
index 457b1700d1021..4a61e317a6a15 100644
--- a/DataFormats/L1TParticleFlow/interface/egamma.h
+++ b/DataFormats/L1TParticleFlow/interface/egamma.h
@@ -87,6 +87,7 @@ namespace l1ct {
z0_t hwZ0;
tkdeta_t hwDEta; // relative to the region center, at calo
tkdphi_t hwDPhi; // relative to the region center, at calo
+ id_score_t hwIDScore;
bool hwCharge;
phi_t hwVtxPhi() const { return hwCharge ? hwPhi + hwDPhi : hwPhi - hwDPhi; }
@@ -95,7 +96,7 @@ namespace l1ct {
inline bool operator==(const EGIsoEleObj &other) const {
return hwPt == other.hwPt && hwEta == other.hwEta && hwPhi == other.hwPhi && hwQual == other.hwQual &&
hwIso == other.hwIso && hwDEta == other.hwDEta && hwDPhi == other.hwDPhi && hwZ0 == other.hwZ0 &&
- hwCharge == other.hwCharge;
+ hwIDScore == other.hwIDScore && hwCharge == other.hwCharge;
}
inline bool operator>(const EGIsoEleObj &other) const { return hwPt > other.hwPt; }
@@ -110,6 +111,7 @@ namespace l1ct {
hwDEta = 0;
hwDPhi = 0;
hwZ0 = 0;
+ hwIDScore = 0;
hwCharge = false;
}
@@ -119,8 +121,10 @@ namespace l1ct {
float floatVtxEta() const { return Scales::floatEta(hwVtxEta()); }
float floatVtxPhi() const { return Scales::floatPhi(hwVtxPhi()); }
float floatZ0() const { return Scales::floatZ0(hwZ0); }
+ float floatIDScore() const { return Scales::floatIDScore(hwIDScore); }
- static const int BITWIDTH = EGIsoObj::BITWIDTH + tkdeta_t::width + tkdphi_t::width + z0_t::width + 1;
+ static const int BITWIDTH =
+ EGIsoObj::BITWIDTH + tkdeta_t::width + tkdphi_t::width + z0_t::width + id_score_t::width + 1;
inline ap_uint pack() const {
ap_uint ret;
unsigned int start = 0;
@@ -133,6 +137,7 @@ namespace l1ct {
pack_into_bits(ret, start, hwDPhi);
pack_into_bits(ret, start, hwZ0);
pack_bool_into_bits(ret, start, hwCharge);
+ pack_into_bits(ret, start, hwIDScore);
return ret;
}
inline static EGIsoEleObj unpack(const ap_uint &src) {
@@ -152,6 +157,7 @@ namespace l1ct {
unpack_from_bits(src, start, hwDPhi);
unpack_from_bits(src, start, hwZ0);
unpack_bool_from_bits(src, start, hwCharge);
+ unpack_from_bits(src, start, hwIDScore);
}
l1gt::Electron toGT() const {
diff --git a/DataFormats/L1TParticleFlow/interface/layer1_emulator.h b/DataFormats/L1TParticleFlow/interface/layer1_emulator.h
index fcb415d426017..f3a1b2d90cea5 100644
--- a/DataFormats/L1TParticleFlow/interface/layer1_emulator.h
+++ b/DataFormats/L1TParticleFlow/interface/layer1_emulator.h
@@ -195,7 +195,6 @@ namespace l1ct {
const l1t::PFTrack *srcTrack;
// we use an index to the standalone object needed to retrieve a Ref when putting
int sta_idx;
- float idScore;
bool read(std::fstream &from);
bool write(std::fstream &to) const;
void clear() {
@@ -203,7 +202,6 @@ namespace l1ct {
srcCluster = nullptr;
srcTrack = nullptr;
sta_idx = -1;
- idScore = -999;
clearIsoVars();
}
@@ -335,7 +333,7 @@ namespace l1ct {
};
struct Event {
- enum { VERSION = 12 };
+ enum { VERSION = 13 };
uint32_t run, lumi;
uint64_t event;
RawInputs raw;
diff --git a/DataFormats/L1TParticleFlow/interface/layer1_objs.h b/DataFormats/L1TParticleFlow/interface/layer1_objs.h
index 48af69b993de1..49435b6fa7ab1 100644
--- a/DataFormats/L1TParticleFlow/interface/layer1_objs.h
+++ b/DataFormats/L1TParticleFlow/interface/layer1_objs.h
@@ -43,9 +43,15 @@ namespace l1ct {
float floatEmPt() const { return Scales::floatPt(hwEmPt); }
float floatEta() const { return Scales::floatEta(hwEta); }
float floatPhi() const { return Scales::floatPhi(hwPhi); }
- float floatSrrTot() const { return Scales::floatSrrTot(hwSrrTot); };
- float floatMeanZ() const { return Scales::floatMeanZ(hwMeanZ); };
- float floatHoe() const { return Scales::floatHoe(hwHoe); };
+ float floatSrrTot() const { return Scales::floatSrrTot(hwSrrTot); }
+ float floatMeanZ() const { return Scales::floatMeanZ(hwMeanZ); }
+ float floatHoe() const { return Scales::floatHoe(hwHoe); }
+ int intSrrTot() const {
+ // bits_to_unt64() is not defined under __SYNTHESIS__
+ return ap_uint(hwSrrTot.range()).to_int();
+ }
+ int intMeanZ() const { return hwMeanZ.to_int(); }
+ int intHoe() const { return ap_uint(hwHoe.range()).to_int(); }
bool hwIsEM() const { return hwEmID != 0; }
@@ -125,6 +131,12 @@ namespace l1ct {
float floatSrrTot() const { return Scales::floatSrrTot(hwSrrTot); };
float floatMeanZ() const { return Scales::floatMeanZ(hwMeanZ); };
float floatHoe() const { return Scales::floatHoe(hwHoe); };
+ int intSrrTot() const {
+ // bits_to_unt64() is not defined under __SYNTHESIS__
+ return ap_uint(hwSrrTot.range()).to_int();
+ }
+ int intMeanZ() const { return hwMeanZ.to_int(); }
+ int intHoe() const { return ap_uint(hwHoe.range()).to_int(); }
static const int BITWIDTH_SLIM = pt_t::width + eta_t::width + phi_t::width + pt_t::width + emid_t::width;
diff --git a/L1Trigger/Configuration/python/SimL1Emulator_cff.py b/L1Trigger/Configuration/python/SimL1Emulator_cff.py
index 5dc7ba09569f6..ec40a2b4d3579 100644
--- a/L1Trigger/Configuration/python/SimL1Emulator_cff.py
+++ b/L1Trigger/Configuration/python/SimL1Emulator_cff.py
@@ -144,6 +144,12 @@
_phase2_siml1emulator.add( l1tTkMuonsGmt )
_phase2_siml1emulator.add( l1tSAMuonsGmt )
+## fix for low-pt muons, this collection is a copy of the l1tTkMuonsGmt collection
+## in which we only keep those low pt muons with an SA muon associated to it. Threshold
+## for this cutoff is configurable.
+l1tTkMuonsGmtLowPtFix = l1tGMTFilteredMuons.clone()
+_phase2_siml1emulator.add( l1tTkMuonsGmtLowPtFix )
+
# Tracker Objects
# ########################################################################
from L1Trigger.L1TTrackMatch.l1tTrackJets_cfi import *
diff --git a/L1Trigger/DemonstratorTools/BuildFile.xml b/L1Trigger/DemonstratorTools/BuildFile.xml
index 692d3965bb994..a0e9d37b75993 100644
--- a/L1Trigger/DemonstratorTools/BuildFile.xml
+++ b/L1Trigger/DemonstratorTools/BuildFile.xml
@@ -5,6 +5,7 @@
+
diff --git a/L1Trigger/DemonstratorTools/interface/BoardData.h b/L1Trigger/DemonstratorTools/interface/BoardData.h
index f68c8c3d83ddb..9c25462e5191e 100644
--- a/L1Trigger/DemonstratorTools/interface/BoardData.h
+++ b/L1Trigger/DemonstratorTools/interface/BoardData.h
@@ -22,6 +22,8 @@ namespace l1t::demo {
const std::string& name() const;
+ void name(const std::string& aName);
+
std::map::const_iterator begin() const;
std::map::iterator begin();
diff --git a/L1Trigger/DemonstratorTools/interface/BoardDataWriter.h b/L1Trigger/DemonstratorTools/interface/BoardDataWriter.h
index 30e7cd3369df7..a3d54b0562065 100644
--- a/L1Trigger/DemonstratorTools/interface/BoardDataWriter.h
+++ b/L1Trigger/DemonstratorTools/interface/BoardDataWriter.h
@@ -24,6 +24,7 @@ namespace l1t::demo {
BoardDataWriter(FileFormat,
const std::string& filePath,
+ const std::string& fileExt,
const size_t framesPerBX,
const size_t tmux,
const size_t maxFramesPerFile,
@@ -31,12 +32,16 @@ namespace l1t::demo {
BoardDataWriter(FileFormat,
const std::string& filePath,
+ const std::string& fileExt,
const size_t framesPerBX,
const size_t tmux,
const size_t maxFramesPerFile,
const std::map>&,
const std::map&);
+ // Set ID string that's written at start of board data files
+ void setBoardDataFileID(const std::string&);
+
void addEvent(const EventData& data);
// If there are events that have not been written to file, forces creation of a board data file containing them
@@ -50,6 +55,9 @@ namespace l1t::demo {
FileFormat fileFormat_;
+ // ID string that's written at start of board data files
+ std::string boardDataFileID_;
+
std::function filePathGen_;
std::vector fileNames_;
diff --git a/L1Trigger/DemonstratorTools/interface/FileFormat.h b/L1Trigger/DemonstratorTools/interface/FileFormat.h
index 06d5bc15b7bcb..b17b12044530a 100644
--- a/L1Trigger/DemonstratorTools/interface/FileFormat.h
+++ b/L1Trigger/DemonstratorTools/interface/FileFormat.h
@@ -6,7 +6,12 @@
namespace l1t::demo {
- enum class FileFormat { APx, EMP, X20 };
+ enum class FileFormat {
+ APx,
+ EMPv1, //< Format used in EMP until version 0.6.x
+ EMPv2, //< Format used in EMP from verison 0.7.0
+ X2O
+ };
std::ostream& operator<<(std::ostream&, FileFormat);
diff --git a/L1Trigger/DemonstratorTools/interface/Frame.h b/L1Trigger/DemonstratorTools/interface/Frame.h
index 00534443bb57d..8abd16a061f6d 100644
--- a/L1Trigger/DemonstratorTools/interface/Frame.h
+++ b/L1Trigger/DemonstratorTools/interface/Frame.h
@@ -18,8 +18,9 @@ namespace l1t::demo {
ap_uint<64> data{0};
bool valid{false};
bool strobe{true};
- bool start{false};
- bool end{false};
+ bool startOfOrbit{false};
+ bool startOfPacket{false};
+ bool endOfPacket{false};
};
} // namespace l1t::demo
diff --git a/L1Trigger/DemonstratorTools/plugins/GTTFileWriter.cc b/L1Trigger/DemonstratorTools/plugins/GTTFileWriter.cc
index b28157833db59..a9fe05c34a399 100644
--- a/L1Trigger/DemonstratorTools/plugins/GTTFileWriter.cc
+++ b/L1Trigger/DemonstratorTools/plugins/GTTFileWriter.cc
@@ -164,6 +164,7 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig)
etMissToken_(consumes>(iConfig.getUntrackedParameter("etmiss"))),
fileWriterInputTracks_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")),
iConfig.getUntrackedParameter("inputFilename"),
+ iConfig.getUntrackedParameter("fileExtension"),
kFramesPerTMUXPeriod,
kGTTBoardTMUX,
kMaxLinesPerFile,
@@ -171,6 +172,7 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig)
kChannelSpecsInput),
fileWriterConvertedTracks_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")),
iConfig.getUntrackedParameter("inputConvertedFilename"),
+ iConfig.getUntrackedParameter("fileExtension"),
kFramesPerTMUXPeriod,
kGTTBoardTMUX,
kMaxLinesPerFile,
@@ -178,6 +180,7 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig)
kChannelSpecsInput),
fileWriterSelectedTracks_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")),
iConfig.getUntrackedParameter("selectedTracksFilename"),
+ iConfig.getUntrackedParameter("fileExtension"),
kFramesPerTMUXPeriod,
kGTTBoardTMUX,
kMaxLinesPerFile,
@@ -186,6 +189,7 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig)
fileWriterVertexAssociatedTracks_(
l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")),
iConfig.getUntrackedParameter("vertexAssociatedTracksFilename"),
+ iConfig.getUntrackedParameter("fileExtension"),
kFramesPerTMUXPeriod,
kGTTBoardTMUX,
kMaxLinesPerFile,
@@ -193,12 +197,14 @@ GTTFileWriter::GTTFileWriter(const edm::ParameterSet& iConfig)
kChannelSpecsInput),
fileWriterOutputToCorrelator_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")),
iConfig.getUntrackedParameter("outputCorrelatorFilename"),
+ iConfig.getUntrackedParameter("fileExtension"),
kFramesPerTMUXPeriod,
kGTTBoardTMUX,
kMaxLinesPerFile,
kChannelSpecsOutputToCorrelator),
fileWriterOutputToGlobalTrigger_(l1t::demo::parseFileFormat(iConfig.getUntrackedParameter("format")),
iConfig.getUntrackedParameter("outputGlobalTriggerFilename"),
+ iConfig.getUntrackedParameter("fileExtension"),
kFramesPerTMUXPeriod,
kGTTBoardTMUX,
kMaxLinesPerFile,
@@ -310,6 +316,7 @@ void GTTFileWriter::fillDescriptions(edm::ConfigurationDescriptions& description
desc.addUntracked("outputCorrelatorFilename", "L1GTTOutputToCorrelatorFile");
desc.addUntracked("outputGlobalTriggerFilename", "L1GTTOutputToGlobalTriggerFile");
desc.addUntracked("format", "APx");
+ desc.addUntracked("fileExtension", "txt");
descriptions.add("GTTFileWriter", desc);
}
diff --git a/L1Trigger/DemonstratorTools/python/GTTFileWriter_cff.py b/L1Trigger/DemonstratorTools/python/GTTFileWriter_cff.py
index 61c4c46929041..c859d23bd5b45 100644
--- a/L1Trigger/DemonstratorTools/python/GTTFileWriter_cff.py
+++ b/L1Trigger/DemonstratorTools/python/GTTFileWriter_cff.py
@@ -15,5 +15,6 @@
vertexAssociatedTracksFilename = cms.untracked.string("L1GTTVertexAssociatedTracksFile"),
outputCorrelatorFilename = cms.untracked.string("L1GTTOutputToCorrelatorFile"),
outputGlobalTriggerFilename = cms.untracked.string("L1GTTOutputToGlobalTriggerFile"),
+ FileExtension = cms.untracked.string("txt"),
format = cms.untracked.string("APx")
)
diff --git a/L1Trigger/DemonstratorTools/src/BoardData.cc b/L1Trigger/DemonstratorTools/src/BoardData.cc
index 2a40b5c3d6fec..f6d4992bfb40d 100644
--- a/L1Trigger/DemonstratorTools/src/BoardData.cc
+++ b/L1Trigger/DemonstratorTools/src/BoardData.cc
@@ -14,6 +14,8 @@ namespace l1t::demo {
const std::string& BoardData::name() const { return name_; }
+ void BoardData::name(const std::string& aName) { name_ = aName; }
+
std::map::const_iterator BoardData::begin() const { return data_.begin(); }
std::map::iterator BoardData::begin() { return data_.begin(); }
diff --git a/L1Trigger/DemonstratorTools/src/BoardDataReader.cc b/L1Trigger/DemonstratorTools/src/BoardDataReader.cc
index 161f62d4974fb..3665c2f503128 100644
--- a/L1Trigger/DemonstratorTools/src/BoardDataReader.cc
+++ b/L1Trigger/DemonstratorTools/src/BoardDataReader.cc
@@ -75,14 +75,14 @@ namespace l1t::demo {
bool expectValid(((j - framesBeforeFirstPacket) % eventLength) < packetLength);
- if (expectValid) {
- if (not chanData.at(j).valid)
- throw std::runtime_error("Frame " + std::to_string(j) + " on channel " +
- std::to_string(indices.at(tmuxIndex)) +
- " is invalid, but expected valid frame");
- } else if (chanData.at(j).valid)
- throw std::runtime_error("Frame " + std::to_string(j) + " on channel " +
- std::to_string(indices.at(tmuxIndex)) + " is valid, but expected invalid frame");
+ // if (expectValid) {
+ // if (not chanData.at(j).valid)
+ // throw std::runtime_error("Frame " + std::to_string(j) + " on channel " +
+ // std::to_string(indices.at(tmuxIndex)) +
+ // " is invalid, but expected valid frame");
+ // } else if (chanData.at(j).valid)
+ // throw std::runtime_error("Frame " + std::to_string(j) + " on channel " +
+ // std::to_string(indices.at(tmuxIndex)) + " is valid, but expected invalid frame");
}
}
}
diff --git a/L1Trigger/DemonstratorTools/src/BoardDataWriter.cc b/L1Trigger/DemonstratorTools/src/BoardDataWriter.cc
index c98a3cb5b9918..7dcd95af15696 100644
--- a/L1Trigger/DemonstratorTools/src/BoardDataWriter.cc
+++ b/L1Trigger/DemonstratorTools/src/BoardDataWriter.cc
@@ -9,12 +9,14 @@ namespace l1t::demo {
BoardDataWriter::BoardDataWriter(FileFormat format,
const std::string& path,
+ const std::string& fileExt,
const size_t framesPerBX,
const size_t tmux,
const size_t maxFramesPerFile,
const ChannelMap_t& channelSpecs)
: fileFormat_(format),
- filePathGen_([=](const size_t i) { return path + "_" + std::to_string(i) + ".txt"; }),
+ boardDataFileID_("CMSSW"),
+ filePathGen_([=](const size_t i) { return path + "_" + std::to_string(i) + "." + fileExt; }),
framesPerBX_(framesPerBX),
boardTMUX_(tmux),
maxFramesPerFile_(maxFramesPerFile),
@@ -24,6 +26,8 @@ namespace l1t::demo {
channelMap_(channelSpecs) {
if (channelMap_.empty())
throw std::runtime_error("BoardDataWriter channel map cannnot be empty");
+ if (fileExt != "txt" && fileExt != "txt.gz" && fileExt != "txt.xz")
+ throw std::runtime_error("BoardDataWriter fileExt must be one of txt, txt.gz, txt.xz");
for (const auto& [id, value] : channelMap_) {
const auto& [spec, indices] = value;
@@ -50,12 +54,16 @@ namespace l1t::demo {
BoardDataWriter::BoardDataWriter(FileFormat format,
const std::string& path,
+ const std::string& fileExt,
const size_t framesPerBX,
const size_t tmux,
const size_t maxFramesPerFile,
const std::map>& channelMap,
const std::map& channelSpecs)
- : BoardDataWriter(format, path, framesPerBX, tmux, maxFramesPerFile, mergeMaps(channelMap, channelSpecs)) {}
+ : BoardDataWriter(
+ format, path, fileExt, framesPerBX, tmux, maxFramesPerFile, mergeMaps(channelMap, channelSpecs)) {}
+
+ void BoardDataWriter::setBoardDataFileID(const std::string& aId) { boardDataFileID_ = aId; }
void BoardDataWriter::addEvent(const EventData& eventData) {
// Check that data is supplied for each channel
@@ -90,9 +98,9 @@ namespace l1t::demo {
// Override flags for start & end of event
BoardData::Channel::iterator it(boardData_.at(chanIndex).end() - 1);
- it->end = true;
+ it->endOfPacket = true;
it -= (channelData.size() - 1);
- it->start = true;
+ it->startOfPacket = true;
// Pad link with non-valid frames
boardData_.at(chanIndex).insert(
@@ -114,6 +122,19 @@ namespace l1t::demo {
for (auto& x : boardData_)
x.second.resize(maxFramesPerFile_);
+ // For each channel: Assert start_of_orbit for first clock cycle that start is asserted
+ for (auto& x : boardData_) {
+ for (auto& frame : x.second) {
+ if (frame.startOfPacket) {
+ frame.startOfOrbit = true;
+ break;
+ }
+ }
+ }
+
+ // Set ID field for board data files
+ boardData_.name(boardDataFileID_);
+
// Write board data object to file
const std::string filePath = filePathGen_(fileNames_.size());
write(boardData_, filePath, fileFormat_);
@@ -144,4 +165,4 @@ namespace l1t::demo {
pendingEvents_ = 0;
}
-} // namespace l1t::demo
\ No newline at end of file
+} // namespace l1t::demo
diff --git a/L1Trigger/DemonstratorTools/src/FileFormat.cc b/L1Trigger/DemonstratorTools/src/FileFormat.cc
index d51110af1308d..741b26c595bdb 100644
--- a/L1Trigger/DemonstratorTools/src/FileFormat.cc
+++ b/L1Trigger/DemonstratorTools/src/FileFormat.cc
@@ -10,11 +10,14 @@ namespace l1t::demo {
case FileFormat::APx:
os << "APx";
break;
- case FileFormat::EMP:
- os << "EMP";
+ case FileFormat::EMPv1:
+ os << "EMPv1";
break;
- case FileFormat::X20:
- os << "X20";
+ case FileFormat::EMPv2:
+ os << "EMPv2";
+ break;
+ case FileFormat::X2O:
+ os << "X2O";
}
return os;
}
diff --git a/L1Trigger/DemonstratorTools/src/utilities.cc b/L1Trigger/DemonstratorTools/src/utilities.cc
index b35ba60c138d6..f9c13a3dcce54 100644
--- a/L1Trigger/DemonstratorTools/src/utilities.cc
+++ b/L1Trigger/DemonstratorTools/src/utilities.cc
@@ -4,6 +4,9 @@
#include
#include
#include
+#include
+#include
+#include
#ifdef CMSSW_GIT_HASH
#include "FWCore/MessageLogger/interface/MessageLogger.h"
@@ -68,12 +71,14 @@ namespace {
namespace l1t::demo {
FileFormat parseFileFormat(const std::string& s) {
- static const std::unordered_map kFormatStringMap({{"EMP", FileFormat::EMP},
- {"emp", FileFormat::EMP},
+ static const std::unordered_map kFormatStringMap({{"EMP", FileFormat::EMPv1},
+ {"emp", FileFormat::EMPv1},
+ {"EMPv1", FileFormat::EMPv1},
+ {"EMPv2", FileFormat::EMPv2},
{"APx", FileFormat::APx},
{"apx", FileFormat::APx},
- {"X20", FileFormat::X20},
- {"x20", FileFormat::X20}});
+ {"X2O", FileFormat::X2O},
+ {"x2O", FileFormat::X2O}});
const auto it = kFormatStringMap.find(s);
if (it == kFormatStringMap.end())
@@ -82,31 +87,49 @@ namespace l1t::demo {
return it->second;
}
- BoardData readAPxFile(std::istream&, const FileFormat);
+ BoardData readAPxFile(std::istream&);
- BoardData readEMPFile(std::istream&, const FileFormat);
+ BoardData readEMPFileV1(std::istream&);
- BoardData readX20File(std::istream&, const FileFormat);
+ BoardData readEMPFileV2(std::istream&);
+
+ BoardData readX2OFile(std::istream&);
BoardData read(const std::string& filePath, const FileFormat format) {
- std::ifstream file(filePath);
+ std::ifstream file(filePath, std::ios_base::in | std::ios_base::binary);
if (not file.is_open())
throw std::runtime_error("Could not open file '" + filePath + "'");
- return read(file, format);
+ boost::iostreams::filtering_istream stream;
+ if (filePath.rfind(".gz") == filePath.length() - 3)
+ stream.push(boost::iostreams::gzip_decompressor());
+ else if (filePath.rfind(".xz") == filePath.length() - 3)
+ stream.push(boost::iostreams::lzma_decompressor());
+
+ stream.push(file);
+
+ return read(stream, format);
}
BoardData read(std::istream& file, const FileFormat format) {
- if (format == FileFormat::APx)
- return readAPxFile(file, format);
- else if (format == FileFormat::EMP)
- return readEMPFile(file, format);
- else
- return readX20File(file, format);
+ switch (format) {
+ case FileFormat::APx:
+ return readAPxFile(file);
+ case FileFormat::EMPv1:
+ return readEMPFileV1(file);
+ case FileFormat::EMPv2:
+ return readEMPFileV2(file);
+ case FileFormat::X2O:
+ return readX2OFile(file);
+ }
+
+ std::ostringstream messageStream;
+ messageStream << "No read function registered for format " << format;
+ throw std::runtime_error(messageStream.str());
}
- BoardData readAPxFile(std::istream& file, const FileFormat format) {
+ BoardData readAPxFile(std::istream& file) {
std::string line;
// Complain if file is empty
@@ -171,8 +194,8 @@ namespace l1t::demo {
else if ((count % 2) == 1) {
uint16_t sbValue = std::stoul(token, nullptr, 16);
dataRows.back().at((count - 1) / 2).valid = (sbValue & 0x1);
- dataRows.back().at((count - 1) / 2).start = ((sbValue >> 1) & 0x1);
- dataRows.back().at((count - 1) / 2).end = ((sbValue >> 3) & 0x1);
+ dataRows.back().at((count - 1) / 2).startOfPacket = ((sbValue >> 1) & 0x1);
+ dataRows.back().at((count - 1) / 2).endOfPacket = ((sbValue >> 3) & 0x1);
}
// Data word
else
@@ -187,7 +210,7 @@ namespace l1t::demo {
return createBoardDataFromRows("", indices, dataRows);
}
- BoardData readEMPFile(std::istream& file, const FileFormat format) {
+ BoardData readEMPFileV1(std::istream& file) {
// 1) Search for ID string
std::string id, line;
while (getline(file, line)) {
@@ -257,15 +280,94 @@ namespace l1t::demo {
return createBoardDataFromRows(id, channels, dataRows);
}
- BoardData readX20File(std::istream& file, const FileFormat format) {
- throw std::runtime_error("Reading X20 file format not yet implemented. Will be done ASAP.");
+ BoardData readEMPFileV2(std::istream& file) {
+ // 1) Search for ID string
+ std::string id, line;
+ while (getline(file, line)) {
+ if (line.empty())
+ continue;
+ if (line[0] == '#')
+ continue;
+
+ if (line.rfind("ID: ", 0) != std::string::npos) {
+ id = line.substr(4);
+ break;
+ } else
+ throw std::logic_error("Found unexpected line found when searching for board ID: \"" + line + "\"");
+ }
+
+ // 2) Check that next line states metadata formatting
+ getline(file, line);
+ if (line.find("Metadata: (strobe,) start of orbit, start of packet, end of packet, valid") != 0)
+ throw std::logic_error("Expected metadata line following 'ID' line. Instead found:" + line);
+
+ // 3) Search for column labels (i.e. list of channels/links)
+ const auto tokens = searchAndTokenize(file, "Link ");
+ std::vector channels;
+ std::transform(tokens.begin(), tokens.end(), std::back_inserter(channels), [](const std::string& s) {
+ return std::stoull(s);
+ });
+
+ // 4) Read the main data rows
+ const std::regex delimiterRegex("\\s\\s+");
+ static const std::regex frameRegex("([01])?([01])([01])([01])([01]) ([0-9a-fA-F]{16})");
+ std::vector> dataRows;
+ while (file.good() and getline(file, line)) {
+ if (line.empty() or line[0] == '#')
+ continue;
+
+ std::ostringstream prefixStream;
+ prefixStream << "Frame ";
+ prefixStream << std::setw(4) << std::setfill('0') << dataRows.size();
+ prefixStream << " ";
+
+ const std::string prefix(prefixStream.str());
+ if (line.rfind(prefix, 0) == std::string::npos)
+ throw std::logic_error("Found unexpected line found when searching for \"" + prefix + "\": \"" + line + "\"");
+
+ std::vector row;
+ std::sregex_token_iterator it(line.begin() + prefix.size(), line.end(), delimiterRegex, -1);
+ for (; it != std::sregex_token_iterator(); it++) {
+ const std::string token(it->str());
+ if (token.empty())
+ continue;
+
+ std::smatch what;
+ if (not std::regex_match(token, what, frameRegex))
+ throw std::logic_error("Token '" + token + "' doesn't match the valid format");
+
+ l1t::demo::Frame value;
+ // Import strobe if the strobe group is matched
+ if (what[1].matched) {
+ value.strobe = (what[1] == "1");
+ }
+
+ value.startOfOrbit = (what[2] == "1");
+ value.startOfPacket = (what[3] == "1");
+ value.endOfPacket = (what[4] == "1");
+ value.valid = (what[5] == "1");
+ value.data = ap_uint<64>(std::stoull(what[6].str(), nullptr, 16));
+
+ row.push_back(value);
+ }
+
+ dataRows.push_back(row);
+ }
+
+ return createBoardDataFromRows(id, channels, dataRows);
+ }
+
+ BoardData readX2OFile(std::istream& file) {
+ throw std::runtime_error("Reading X2O file format not yet implemented. Will be done ASAP.");
}
- void writeAPxFile(const BoardData&, std::ostream&, const FileFormat);
+ void writeAPxFile(const BoardData&, std::ostream&);
+
+ void writeEMPFileV1(const BoardData&, std::ostream&);
- void writeEMPFile(const BoardData&, std::ostream&, const FileFormat);
+ void writeEMPFileV2(const BoardData&, std::ostream&);
- void writeX20File(const BoardData&, std::ostream&, const FileFormat);
+ void writeX2OFile(const BoardData&, std::ostream&);
void write(const BoardData& data, const std::string& filePath, const FileFormat format) {
// Open file
@@ -277,12 +379,19 @@ namespace l1t::demo {
<< "Writing board data (" << std::distance(data.begin(), data.end()) << " channels, "
<< data.begin()->second.size() << " frames) to file '" << filePath << "' (format: " << format << ")"
<< std::endl;
- std::ofstream file(filePath);
+
+ std::ofstream file(filePath, std::ios_base::out | std::ios_base::binary);
if (not file.is_open())
throw std::runtime_error("Could not open file '" + filePath + "'");
- write(data, file, format);
+ boost::iostreams::filtering_ostream stream;
+ if (filePath.rfind(".gz") == filePath.length() - 3)
+ stream.push(boost::iostreams::gzip_compressor());
+ else if (filePath.rfind(".xz") == filePath.length() - 3)
+ stream.push(boost::iostreams::lzma_compressor());
+ stream.push(file);
+ write(data, stream, format);
}
void write(const BoardData& data, std::ostream& file, const FileFormat format) {
@@ -302,18 +411,21 @@ namespace l1t::demo {
// Call relevant write function
switch (format) {
case FileFormat::APx:
- writeAPxFile(data, file, format);
+ writeAPxFile(data, file);
return;
- case FileFormat::EMP:
- writeEMPFile(data, file, format);
+ case FileFormat::EMPv1:
+ writeEMPFileV1(data, file);
return;
- case FileFormat::X20:
- writeX20File(data, file, format);
+ case FileFormat::EMPv2:
+ writeEMPFileV2(data, file);
+ return;
+ case FileFormat::X2O:
+ writeX2OFile(data, file);
return;
}
}
- void writeAPxFile(const BoardData& data, std::ostream& file, const FileFormat format) {
+ void writeAPxFile(const BoardData& data, std::ostream& file) {
// Note: APx sideband encoding
// Short-term, simulation only:
// 0 -> Valid
@@ -350,8 +462,8 @@ namespace l1t::demo {
//const auto j = channel.first;
const auto channelData = channel.second;
uint16_t sideband = channelData.at(i).valid;
- sideband |= channelData.at(i).start << 1;
- sideband |= channelData.at(i).end << 3;
+ sideband |= channelData.at(i).startOfPacket << 1;
+ sideband |= channelData.at(i).endOfPacket << 3;
file << " 0x" << std::setw(2) << sideband;
file << " 0x" << std::setw(16) << uint64_t(channelData.at(i).data);
}
@@ -359,7 +471,7 @@ namespace l1t::demo {
}
}
- void writeEMPFile(const BoardData& data, std::ostream& file, const FileFormat format) {
+ void writeEMPFileV1(const BoardData& data, std::ostream& file) {
file << std::setfill('0');
// Board name/id
@@ -398,8 +510,47 @@ namespace l1t::demo {
}
}
- void writeX20File(const BoardData& data, std::ostream& file, const FileFormat format) {
- throw std::runtime_error("Writing X20 file format not yet implemented. Will be done ASAP.");
+ void writeEMPFileV2(const BoardData& data, std::ostream& file) {
+ file << std::setfill('0');
+
+ // Board name/id
+ file << "ID: " << data.name() << std::endl;
+ file << "Metadata: (strobe,) start of orbit, start of packet, end of packet, valid" << std::endl;
+ file << std::endl;
+
+ // Link header
+ file << " Link ";
+ std::map strobedLinkMap;
+ for (const auto& channel : data) {
+ const auto i = channel.first;
+ strobedLinkMap[i] =
+ std::any_of(channel.second.begin(), channel.second.end(), [](const Frame& x) { return not x.strobe; });
+ if (strobedLinkMap.at(i))
+ file << " ";
+ file << " " << std::setw(3) << i << " ";
+ }
+ file << std::endl;
+
+ // Frames
+ const auto firstChannel = data.begin();
+ for (size_t i = 0; i < firstChannel->second.size(); i++) {
+ file << "Frame " << std::setw(4) << i << " ";
+ for (const auto& channel : data) {
+ //const auto j = channel.first;
+ const auto channelData = channel.second;
+ file << " ";
+ if (strobedLinkMap.at(channel.first))
+ file << std::setw(1) << channelData.at(i).strobe;
+ file << std::setw(1) << channelData.at(i).startOfOrbit << channelData.at(i).startOfPacket
+ << channelData.at(i).endOfPacket << channelData.at(i).valid;
+ file << " " << std::setw(16) << std::hex << uint64_t(channelData.at(i).data);
+ }
+ file << std::endl << std::dec;
+ }
+ }
+
+ void writeX2OFile(const BoardData& data, std::ostream& file) {
+ throw std::runtime_error("Writing X2O file format not yet implemented. Will be done ASAP.");
}
} // namespace l1t::demo
diff --git a/L1Trigger/DemonstratorTools/test/gtt/createFirmwareInputFiles_cfg.py b/L1Trigger/DemonstratorTools/test/gtt/createFirmwareInputFiles_cfg.py
index 6f720104d9db5..bf73082319f6b 100644
--- a/L1Trigger/DemonstratorTools/test/gtt/createFirmwareInputFiles_cfg.py
+++ b/L1Trigger/DemonstratorTools/test/gtt/createFirmwareInputFiles_cfg.py
@@ -15,7 +15,7 @@
'EMP', # default value
VarParsing.VarParsing.multiplicity.singleton,
VarParsing.VarParsing.varType.string,
- "File format (APx, EMP or X20)")
+ "File format (APx, EMP or X2O)")
options.register('threads',
1, # default value
VarParsing.VarParsing.multiplicity.singleton,
diff --git a/L1Trigger/DemonstratorTools/test/gtt/example_vertex_emp.txt b/L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV1.txt
similarity index 100%
rename from L1Trigger/DemonstratorTools/test/gtt/example_vertex_emp.txt
rename to L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV1.txt
diff --git a/L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV2.txt b/L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV2.txt
new file mode 100644
index 0000000000000..a415a333a4cc4
--- /dev/null
+++ b/L1Trigger/DemonstratorTools/test/gtt/example_vertex_empV2.txt
@@ -0,0 +1,176 @@
+ID: CMSSW
+Metadata: (strobe,) start of orbit, start of packet, end of packet, valid
+
+ Link 000
+Frame 0000 0000 0000000000000000
+Frame 0001 0000 0000000000000000
+Frame 0002 0000 0000000000000000
+Frame 0003 0000 0000000000000000
+Frame 0004 0000 0000000000000000
+Frame 0005 0000 0000000000000000
+Frame 0006 0000 0000000000000000
+Frame 0007 0000 0000000000000000
+Frame 0008 0000 0000000000000000
+Frame 0009 0000 0000000000000000
+Frame 0010 1101 0000000000000001
+Frame 0011 0001 0000000000000001
+Frame 0012 0001 0000000000000001
+Frame 0013 0001 0000000000000001
+Frame 0014 0001 0000000000000000
+Frame 0015 0001 0000000000000000
+Frame 0016 0001 0000000000000000
+Frame 0017 0001 0000000000000000
+Frame 0018 0001 0000000000000000
+Frame 0019 0011 0000000000000000
+Frame 0020 0000 0000000000000000
+Frame 0021 0000 0000000000000000
+Frame 0022 0000 0000000000000000
+Frame 0023 0000 0000000000000000
+Frame 0024 0000 0000000000000000
+Frame 0025 0000 0000000000000000
+Frame 0026 0000 0000000000000000
+Frame 0027 0000 0000000000000000
+Frame 0028 0000 0000000000000000
+Frame 0029 0000 0000000000000000
+Frame 0030 0000 0000000000000000
+Frame 0031 0000 0000000000000000
+Frame 0032 0000 0000000000000000
+Frame 0033 0000 0000000000000000
+Frame 0034 0000 0000000000000000
+Frame 0035 0000 0000000000000000
+Frame 0036 0000 0000000000000000
+Frame 0037 0000 0000000000000000
+Frame 0038 0000 0000000000000000
+Frame 0039 0000 0000000000000000
+Frame 0040 0000 0000000000000000
+Frame 0041 0000 0000000000000000
+Frame 0042 0000 0000000000000000
+Frame 0043 0000 0000000000000000
+Frame 0044 0000 0000000000000000
+Frame 0045 0000 0000000000000000
+Frame 0046 0000 0000000000000000
+Frame 0047 0000 0000000000000000
+Frame 0048 0000 0000000000000000
+Frame 0049 0000 0000000000000000
+Frame 0050 0000 0000000000000000
+Frame 0051 0000 0000000000000000
+Frame 0052 0000 0000000000000000
+Frame 0053 0000 0000000000000000
+Frame 0054 0000 0000000000000000
+Frame 0055 0000 0000000000000000
+Frame 0056 0000 0000000000000000
+Frame 0057 0000 0000000000000000
+Frame 0058 0000 0000000000000000
+Frame 0059 0000 0000000000000000
+Frame 0060 0000 0000000000000000
+Frame 0061 0000 0000000000000000
+Frame 0062 0000 0000000000000000
+Frame 0063 0000 0000000000000000
+Frame 0064 0101 0000000000000001
+Frame 0065 0001 0000000000000001
+Frame 0066 0001 0000000000000000
+Frame 0067 0001 0000000000000000
+Frame 0068 0001 0000000000000000
+Frame 0069 0001 0000000000000000
+Frame 0070 0001 0000000000000000
+Frame 0071 0001 0000000000000000
+Frame 0072 0001 0000000000000000
+Frame 0073 0011 0000000000000000
+Frame 0074 0000 0000000000000000
+Frame 0075 0000 0000000000000000
+Frame 0076 0000 0000000000000000
+Frame 0077 0000 0000000000000000
+Frame 0078 0000 0000000000000000
+Frame 0079 0000 0000000000000000
+Frame 0080 0000 0000000000000000
+Frame 0081 0000 0000000000000000
+Frame 0082 0000 0000000000000000
+Frame 0083 0000 0000000000000000
+Frame 0084 0000 0000000000000000
+Frame 0085 0000 0000000000000000
+Frame 0086 0000 0000000000000000
+Frame 0087 0000 0000000000000000
+Frame 0088 0000 0000000000000000
+Frame 0089 0000 0000000000000000
+Frame 0090 0000 0000000000000000
+Frame 0091 0000 0000000000000000
+Frame 0092 0000 0000000000000000
+Frame 0093 0000 0000000000000000
+Frame 0094 0000 0000000000000000
+Frame 0095 0000 0000000000000000
+Frame 0096 0000 0000000000000000
+Frame 0097 0000 0000000000000000
+Frame 0098 0000 0000000000000000
+Frame 0099 0000 0000000000000000
+Frame 0100 0000 0000000000000000
+Frame 0101 0000 0000000000000000
+Frame 0102 0000 0000000000000000
+Frame 0103 0000 0000000000000000
+Frame 0104 0000 0000000000000000
+Frame 0105 0000 0000000000000000
+Frame 0106 0000 0000000000000000
+Frame 0107 0000 0000000000000000
+Frame 0108 0000 0000000000000000
+Frame 0109 0000 0000000000000000
+Frame 0110 0000 0000000000000000
+Frame 0111 0000 0000000000000000
+Frame 0112 0000 0000000000000000
+Frame 0113 0000 0000000000000000
+Frame 0114 0000 0000000000000000
+Frame 0115 0000 0000000000000000
+Frame 0116 0000 0000000000000000
+Frame 0117 0000 0000000000000000
+Frame 0118 0101 0000000000000001
+Frame 0119 0001 0000000000000001
+Frame 0120 0001 0000000000000001
+Frame 0121 0001 0000000000000001
+Frame 0122 0001 0000000000000001
+Frame 0123 0001 0000000000000001
+Frame 0124 0001 0000000000000001
+Frame 0125 0001 0000000000000001
+Frame 0126 0001 0000000000000000
+Frame 0127 0011 0000000000000000
+Frame 0128 0000 0000000000000000
+Frame 0129 0000 0000000000000000
+Frame 0130 0000 0000000000000000
+Frame 0131 0000 0000000000000000
+Frame 0132 0000 0000000000000000
+Frame 0133 0000 0000000000000000
+Frame 0134 0000 0000000000000000
+Frame 0135 0000 0000000000000000
+Frame 0136 0000 0000000000000000
+Frame 0137 0000 0000000000000000
+Frame 0138 0000 0000000000000000
+Frame 0139 0000 0000000000000000
+Frame 0140 0000 0000000000000000
+Frame 0141 0000 0000000000000000
+Frame 0142 0000 0000000000000000
+Frame 0143 0000 0000000000000000
+Frame 0144 0000 0000000000000000
+Frame 0145 0000 0000000000000000
+Frame 0146 0000 0000000000000000
+Frame 0147 0000 0000000000000000
+Frame 0148 0000 0000000000000000
+Frame 0149 0000 0000000000000000
+Frame 0150 0000 0000000000000000
+Frame 0151 0000 0000000000000000
+Frame 0152 0000 0000000000000000
+Frame 0153 0000 0000000000000000
+Frame 0154 0000 0000000000000000
+Frame 0155 0000 0000000000000000
+Frame 0156 0000 0000000000000000
+Frame 0157 0000 0000000000000000
+Frame 0158 0000 0000000000000000
+Frame 0159 0000 0000000000000000
+Frame 0160 0000 0000000000000000
+Frame 0161 0000 0000000000000000
+Frame 0162 0000 0000000000000000
+Frame 0163 0000 0000000000000000
+Frame 0164 0000 0000000000000000
+Frame 0165 0000 0000000000000000
+Frame 0166 0000 0000000000000000
+Frame 0167 0000 0000000000000000
+Frame 0168 0000 0000000000000000
+Frame 0169 0000 0000000000000000
+Frame 0170 0000 0000000000000000
+Frame 0171 0000 0000000000000000
diff --git a/L1Trigger/DemonstratorTools/test/gtt/verifyFirmwareOutput_cfg.py b/L1Trigger/DemonstratorTools/test/gtt/verifyFirmwareOutput_cfg.py
index ae64cf0329e65..132953bc08de7 100644
--- a/L1Trigger/DemonstratorTools/test/gtt/verifyFirmwareOutput_cfg.py
+++ b/L1Trigger/DemonstratorTools/test/gtt/verifyFirmwareOutput_cfg.py
@@ -11,7 +11,7 @@
'EMP', # default value
VarParsing.VarParsing.multiplicity.singleton,
VarParsing.VarParsing.varType.string,
- "File format (APx, EMP or X20)")
+ "File format (APx, EMP or X2O)")
options.parseArguments()
inputFiles = []
diff --git a/L1Trigger/L1THGCal/BuildFile.xml b/L1Trigger/L1THGCal/BuildFile.xml
index ac1f64cda7e43..4015804fd9067 100644
--- a/L1Trigger/L1THGCal/BuildFile.xml
+++ b/L1Trigger/L1THGCal/BuildFile.xml
@@ -7,6 +7,7 @@
+
diff --git a/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h b/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h
index 9172e808bf9ac..4ffca6c91b00e 100644
--- a/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h
+++ b/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h
@@ -11,9 +11,9 @@
#include "DataFormats/L1THGCal/interface/HGCalTowerMap.h"
typedef HGCalAlgoWrapperBaseT<
- std::pair>, const std::vector>>,
+ const std::vector>>,
std::pair,
- std::pair>
+ std::tuple>
HGCalHistoClusteringWrapperBase;
typedef HGCalAlgoWrapperBaseT>,
diff --git a/L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h b/L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h
index 6f4ba1c4f4331..2380d679e8220 100644
--- a/L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h
+++ b/L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h
@@ -82,6 +82,7 @@ class HGCalTriggerGeometryBase {
virtual bool disconnectedModule(const unsigned module_id) const = 0;
virtual unsigned lastTriggerLayer() const = 0;
virtual unsigned triggerLayer(const unsigned id) const = 0;
+ virtual const std::vector& triggerLayers() const = 0;
protected:
void setEEGeometry(const HGCalGeometry* geom) { hgc_ee_geometry_ = geom; }
diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h b/L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h
new file mode 100644
index 0000000000000..dd9fb58d60759
--- /dev/null
+++ b/L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h
@@ -0,0 +1,64 @@
+#ifndef __L1Trigger_L1THGCal_CentroidHelper_h__
+#define __L1Trigger_L1THGCal_CentroidHelper_h__
+
+#include
+
+namespace l1thgcfirmware {
+
+ class CentroidHelper {
+ public:
+ CentroidHelper() : CentroidHelper(0, 0, 0, 0, 0, 0, 0, false) {}
+ CentroidHelper(unsigned int clock, unsigned int index, unsigned int dataValid)
+ : CentroidHelper(clock, index, 0, 0, 0, 0, 0, dataValid) {}
+ CentroidHelper(unsigned int clock,
+ unsigned int index,
+ unsigned int column,
+ unsigned int row,
+ unsigned int energy,
+ unsigned int X,
+ unsigned int Y,
+ unsigned int dataValid)
+ : clock_(clock),
+ index_(index),
+ column_(column),
+ row_(row),
+ energy_(energy),
+ x_(X),
+ y_(Y),
+ dataValid_(dataValid) {}
+ ~CentroidHelper() {}
+
+ // Getters
+ unsigned int clock() const { return clock_; }
+ unsigned int index() const { return index_; }
+ unsigned int column() const { return column_; }
+ unsigned int row() const { return row_; }
+ unsigned int energy() const { return energy_; }
+ unsigned int X() const { return x_; }
+ unsigned int Y() const { return y_; }
+ bool dataValid() const { return dataValid_; }
+
+ // Setters
+ void setClock(const unsigned int clock) { clock_ = clock; }
+ void setIndex(const unsigned int index) { index_ = index; }
+
+ private:
+ unsigned int clock_;
+ unsigned int index_;
+ unsigned int column_;
+ unsigned int row_;
+ unsigned int energy_;
+ unsigned int x_;
+ unsigned int y_;
+ bool dataValid_;
+ };
+
+ typedef std::unique_ptr CentroidHelperPtr;
+ typedef std::vector CentroidHelperPtrCollection;
+ typedef std::vector CentroidHelperPtrCollections;
+
+ typedef std::shared_ptr CentroidHelperShrPtr;
+ typedef std::vector CentroidHelperShrPtrCollection;
+} // namespace l1thgcfirmware
+
+#endif
diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/DistServer.h b/L1Trigger/L1THGCal/interface/backend_emulator/DistServer.h
new file mode 100644
index 0000000000000..66da3a5c03798
--- /dev/null
+++ b/L1Trigger/L1THGCal/interface/backend_emulator/DistServer.h
@@ -0,0 +1,29 @@
+#ifndef __L1Trigger_L1THGCal_DistServer_h__
+#define __L1Trigger_L1THGCal_DistServer_h__
+
+#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h"
+
+#include
+
+namespace l1thgcfirmware {
+
+ class DistServer {
+ public:
+ DistServer(unsigned int nInputs, unsigned int nOutputs, unsigned int nInterleaving);
+ ~DistServer() {}
+
+ HGCalTriggerCellSAShrPtrCollection clock(HGCalTriggerCellSAShrPtrCollection&);
+
+ unsigned int nOutputs() const { return nOutputs_; }
+ unsigned int nInterleaving() const { return nInterleaving_; }
+
+ private:
+ unsigned int nOutputs_;
+ unsigned int nInterleaving_;
+
+ l1thgcfirmware::HGCalTriggerCellSAShrPtrCollections inputs_;
+ std::vector > addr_;
+ };
+} // namespace l1thgcfirmware
+
+#endif
diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h
new file mode 100644
index 0000000000000..8905fffde1f2d
--- /dev/null
+++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h
@@ -0,0 +1,297 @@
+#ifndef L1Trigger_L1THGCal_HGCalCluster_SA_h
+#define L1Trigger_L1THGCal_HGCalCluster_SA_h
+
+#include "HGCalTriggerCell_SA.h"
+#include "HGCalHistoClusteringConfig_SA.h"
+#include "DataFormats/L1THGCal/interface/HGCalCluster_HW.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "ap_int.h"
+
+namespace l1thgcfirmware {
+
+ class HGCalCluster {
+ public:
+ HGCalCluster(unsigned int clock, unsigned int index, bool frameValid, bool dataValid)
+ : clock_(clock),
+ index_(index),
+ layerBits_(0),
+ frameValid_(frameValid),
+ dataValid_(dataValid),
+ n_tc_(0),
+ e_(0),
+ e_em_(0),
+ e_em_core_(0),
+ e_h_early_(0),
+ w_(0),
+ n_tc_w_(0),
+ w2_(0),
+ wz_(0),
+ weta_(0),
+ wphi_(0),
+ wroz_(0),
+ wz2_(0),
+ weta2_(0),
+ wphi2_(0),
+ wroz2_(0),
+ layerbits_(0),
+ sat_tc_(false),
+ shapeq_(1),
+ sigma_e_quotient_(0),
+ sigma_e_fraction_(0),
+ mean_z_quotient_(0),
+ mean_z_fraction_(0),
+ mean_phi_quotient_(0),
+ mean_phi_fraction_(0),
+ mean_eta_quotient_(0),
+ mean_eta_fraction_(0),
+ mean_roz_quotient_(0),
+ mean_roz_fraction_(0),
+ sigma_z_quotient_(0),
+ sigma_z_fraction_(0),
+ sigma_phi_quotient_(0),
+ sigma_phi_fraction_(0),
+ sigma_eta_quotient_(0),
+ sigma_eta_fraction_(0),
+ sigma_roz_quotient_(0),
+ sigma_roz_fraction_(0),
+ first_layer_(0),
+ last_layer_(0),
+ shower_len_(0),
+ core_shower_len_(0),
+ e_em_over_e_quotient_(0),
+ e_em_over_e_fraction_(0),
+ e_em_core_over_e_em_quotient_(0),
+ e_em_core_over_e_em_fraction_(0),
+ e_h_early_over_e_quotient_(0),
+ e_h_early_over_e_fraction_(0) {}
+
+ ~HGCalCluster() {}
+
+ // Firmware representation of cluster sum (input to cluster properties step)
+ static constexpr int clusterSumWordLength = 64;
+ static constexpr int nWordsPerClusterSum = 8;
+ static constexpr int allClusterSumWordsLength = clusterSumWordLength * nWordsPerClusterSum;
+ typedef uint64_t ClusterSumWord;
+ typedef std::array ClusterSumWords;
+
+ std::pair sigma_energy(unsigned int N_TC_W,
+ unsigned long int Sum_W2,
+ unsigned int Sum_W);
+ std::pair mean_coordinate(unsigned int Sum_Wc, unsigned int Sum_W);
+ std::pair sigma_coordinate(unsigned int Sum_W,
+ unsigned long int Sum_Wc2,
+ unsigned int Sum_Wc);
+ std::pair energy_ratio(unsigned int E_N, unsigned int E_D);
+ std::vector showerLengthProperties(unsigned long int layerBits);
+
+ // Setters
+ void setClock(const unsigned int clock) { clock_ = clock; }
+ void setIndex(const unsigned int index) { index_ = index; }
+ void setDataValid(const bool dataValid) { dataValid_ = dataValid; }
+
+ void set_n_tc(unsigned int n_tc) { n_tc_ = n_tc; }
+ void set_e(unsigned int e) { e_ = e; }
+ void set_e_em(unsigned int e_em) { e_em_ = e_em; }
+ void set_e_em_core(unsigned int e_em_core) { e_em_core_ = e_em_core; }
+ void set_e_h_early(unsigned int e_h_early) { e_h_early_ = e_h_early; }
+ void set_w(unsigned int w) { w_ = w; }
+ void set_n_tc_w(unsigned int n_tc_w) { n_tc_w_ = n_tc_w; }
+ void set_w2(unsigned long int w2) { w2_ = w2; }
+ void set_wz(unsigned int wz) { wz_ = wz; }
+ void set_weta(unsigned int weta) { weta_ = weta; }
+ void set_wphi(unsigned int wphi) { wphi_ = wphi; }
+ void set_wroz(unsigned int wroz) { wroz_ = wroz; }
+ void set_wz2(unsigned long int wz2) { wz2_ = wz2; }
+ void set_weta2(unsigned long int weta2) { weta2_ = weta2; }
+ void set_wphi2(unsigned long int wphi2) { wphi2_ = wphi2; }
+ void set_wroz2(unsigned long int wroz2) { wroz2_ = wroz2; }
+ void set_layerbits(unsigned long int layerbits) { layerbits_ = layerbits; }
+ void set_sat_tc(bool sat_tc) { sat_tc_ = sat_tc; }
+ void set_shapeq(unsigned int shapeq) { shapeq_ = shapeq; }
+
+ void set_sigma_e_quotient(unsigned long int sigma_e_quotient) { sigma_e_quotient_ = sigma_e_quotient; }
+ void set_sigma_e_fraction(unsigned long int sigma_e_fraction) { sigma_e_fraction_ = sigma_e_fraction; }
+ void set_mean_z_quotient(unsigned long int mean_z_quotient) { mean_z_quotient_ = mean_z_quotient; }
+ void set_mean_z_fraction(unsigned long int mean_z_fraction) { mean_z_fraction_ = mean_z_fraction; }
+ void set_mean_phi_quotient(unsigned long int mean_phi_quotient) { mean_phi_quotient_ = mean_phi_quotient; }
+ void set_mean_phi_fraction(unsigned long int mean_phi_fraction) { mean_phi_fraction_ = mean_phi_fraction; }
+ void set_mean_eta_quotient(unsigned long int mean_eta_quotient) { mean_eta_quotient_ = mean_eta_quotient; }
+ void set_mean_eta_fraction(unsigned long int mean_eta_fraction) { mean_eta_fraction_ = mean_eta_fraction; }
+ void set_mean_roz_quotient(unsigned long int mean_roz_quotient) { mean_roz_quotient_ = mean_roz_quotient; }
+ void set_mean_roz_fraction(unsigned long int mean_roz_fraction) { mean_roz_fraction_ = mean_roz_fraction; }
+ void set_sigma_z_quotient(unsigned long int sigma_z_quotient) { sigma_z_quotient_ = sigma_z_quotient; }
+ void set_sigma_z_fraction(unsigned long int sigma_z_fraction) { sigma_z_fraction_ = sigma_z_fraction; }
+ void set_sigma_phi_quotient(unsigned long int sigma_phi_quotient) { sigma_phi_quotient_ = sigma_phi_quotient; }
+ void set_sigma_phi_fraction(unsigned long int sigma_phi_fraction) { sigma_phi_fraction_ = sigma_phi_fraction; }
+ void set_sigma_eta_quotient(unsigned long int sigma_eta_quotient) { sigma_eta_quotient_ = sigma_eta_quotient; }
+ void set_sigma_eta_fraction(unsigned long int sigma_eta_fraction) { sigma_eta_fraction_ = sigma_eta_fraction; }
+ void set_sigma_roz_quotient(unsigned long int sigma_roz_quotient) { sigma_roz_quotient_ = sigma_roz_quotient; }
+ void set_sigma_roz_fraction(unsigned long int sigma_roz_fraction) { sigma_roz_fraction_ = sigma_roz_fraction; }
+ void set_firstLayer(unsigned long int FirstLayer) { first_layer_ = FirstLayer; }
+ void set_lastLayer(unsigned long int LastLayer) { last_layer_ = LastLayer; }
+ void set_showerLen(unsigned long int ShowerLen) { shower_len_ = ShowerLen; }
+ void set_coreShowerLen(unsigned long int CoreShowerLen) { core_shower_len_ = CoreShowerLen; }
+ void set_e_em_over_e_quotient(unsigned long int quotient) { e_em_over_e_quotient_ = quotient; }
+ void set_e_em_over_e_fraction(unsigned long int fraction) { e_em_over_e_fraction_ = fraction; }
+ void set_e_em_core_over_e_em_quotient(unsigned long int quotient) { e_em_core_over_e_em_quotient_ = quotient; }
+ void set_e_em_core_over_e_em_fraction(unsigned long int fraction) { e_em_core_over_e_em_fraction_ = fraction; }
+ void set_e_h_early_over_e_quotient(unsigned long int quotient) { e_h_early_over_e_quotient_ = quotient; }
+ void set_e_h_early_over_e_fraction(unsigned long int fraction) { e_h_early_over_e_fraction_ = fraction; }
+
+ void add_constituent(HGCalTriggerCellSAShrPtr constituent) { constituents_.emplace_back(constituent); }
+
+ // Getters
+ unsigned int clock() const { return clock_; }
+ unsigned int index() const { return index_; }
+ bool frameValid() const { return frameValid_; }
+ bool dataValid() const { return dataValid_; }
+
+ unsigned int n_tc() const { return n_tc_; }
+ unsigned int e() const { return e_; }
+ unsigned int e_em() const { return e_em_; }
+ unsigned int e_em_core() const { return e_em_core_; }
+ unsigned int e_h_early() const { return e_h_early_; }
+ unsigned int w() const { return w_; }
+ unsigned int n_tc_w() const { return n_tc_w_; }
+ unsigned long int w2() const { return w2_; }
+ unsigned long int wz() const { return wz_; }
+ unsigned long int weta() const { return weta_; }
+ unsigned long int wphi() const { return wphi_; }
+ unsigned long int wroz() const { return wroz_; }
+ unsigned long int wz2() const { return wz2_; }
+ unsigned long int weta2() const { return weta2_; }
+ unsigned long int wphi2() const { return wphi2_; }
+ unsigned long int wroz2() const { return wroz2_; }
+ unsigned long int layerbits() const { return layerbits_; }
+ bool sat_tc() const { return sat_tc_; }
+ unsigned int shapeq() const { return shapeq_; }
+
+ unsigned long int sigma_e_quotient() const { return sigma_e_quotient_; }
+ unsigned long int sigma_e_fraction() const { return sigma_e_fraction_; }
+ unsigned long int mean_z_quotient() const { return mean_z_quotient_; }
+ unsigned long int mean_z_fraction() const { return mean_z_fraction_; }
+ unsigned long int mean_phi_quotient() const { return mean_phi_quotient_; }
+ unsigned long int mean_phi_fraction() const { return mean_phi_fraction_; }
+ unsigned long int mean_eta_quotient() const { return mean_eta_quotient_; }
+ unsigned long int mean_eta_fraction() const { return mean_eta_fraction_; }
+ unsigned long int mean_roz_quotient() const { return mean_roz_quotient_; }
+ unsigned long int mean_roz_fraction() const { return mean_roz_fraction_; }
+ unsigned long int sigma_z_quotient() const { return sigma_z_quotient_; }
+ unsigned long int sigma_z_fraction() const { return sigma_z_fraction_; }
+ unsigned long int sigma_phi_quotient() const { return sigma_phi_quotient_; }
+ unsigned long int sigma_phi_fraction() const { return sigma_phi_fraction_; }
+ unsigned long int sigma_eta_quotient() const { return sigma_eta_quotient_; }
+ unsigned long int sigma_eta_fraction() const { return sigma_eta_fraction_; }
+ unsigned long int sigma_roz_quotient() const { return sigma_roz_quotient_; }
+ unsigned long int sigma_roz_fraction() const { return sigma_roz_fraction_; }
+ unsigned long int firstLayer() const { return first_layer_; }
+ unsigned long int lastLayer() const { return last_layer_; }
+ unsigned long int showerLen() const { return shower_len_; }
+ unsigned long int coreShowerLen() const { return core_shower_len_; }
+ unsigned long int e_em_over_e_quotient() const { return e_em_over_e_quotient_; }
+ unsigned long int e_em_over_e_fraction() const { return e_em_over_e_fraction_; }
+ unsigned long int e_em_core_over_e_em_quotient() const { return e_em_core_over_e_em_quotient_; }
+ unsigned long int e_em_core_over_e_em_fraction() const { return e_em_core_over_e_em_fraction_; }
+ unsigned long int e_h_early_over_e_quotient() const { return e_h_early_over_e_quotient_; }
+ unsigned long int e_h_early_over_e_fraction() const { return e_h_early_over_e_fraction_; }
+
+ HGCalTriggerCellSAShrPtrCollection& constituents() { return constituents_; }
+
+ // Operators
+ const HGCalCluster& operator+=(HGCalCluster& hc);
+
+ // Format data into firmware representation
+ HGCalCluster_HW convertToL1TFormat( const ClusterAlgoConfig& config );
+ void formatFirstWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster );
+ void formatSecondWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster );
+ void formatThirdWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster );
+ void formatFourthWord( const ClusterAlgoConfig& config, HGCalCluster_HW& hwCluster );
+
+ // Conversion of roz to eta (and sigma roz)
+ double convertRozToEta( const ClusterAlgoConfig& config );
+ double convertSigmaRozRozToSigmaEtaEta( const ClusterAlgoConfig& config );
+
+ // Format data into firmware representation
+ void clearClusterSumWords();
+ ClusterSumWords formatClusterSumWords( const ClusterAlgoConfig& config );
+
+ private:
+ unsigned int clock_;
+ unsigned int index_;
+ unsigned int layerBits_;
+ bool frameValid_;
+ bool dataValid_;
+
+ unsigned int n_tc_;
+ unsigned int e_;
+ unsigned int e_em_;
+ unsigned int e_em_core_;
+ unsigned int e_h_early_;
+ unsigned int w_;
+ unsigned int n_tc_w_;
+ unsigned long int w2_;
+ unsigned int wz_;
+ unsigned int weta_;
+ unsigned int wphi_;
+ unsigned int wroz_;
+ unsigned long int wz2_;
+ unsigned long int weta2_;
+ unsigned long int wphi2_;
+ unsigned long int wroz2_;
+ unsigned long int layerbits_;
+ bool sat_tc_;
+ unsigned int shapeq_;
+ unsigned long int sigma_e_quotient_;
+ unsigned long int sigma_e_fraction_;
+ unsigned long int mean_z_quotient_;
+ unsigned long int mean_z_fraction_;
+ unsigned long int mean_phi_quotient_;
+ unsigned long int mean_phi_fraction_;
+ unsigned long int mean_eta_quotient_;
+ unsigned long int mean_eta_fraction_;
+ unsigned long int mean_roz_quotient_;
+ unsigned long int mean_roz_fraction_;
+ unsigned long int sigma_z_quotient_;
+ unsigned long int sigma_z_fraction_;
+ unsigned long int sigma_phi_quotient_;
+ unsigned long int sigma_phi_fraction_;
+ unsigned long int sigma_eta_quotient_;
+ unsigned long int sigma_eta_fraction_;
+ unsigned long int sigma_roz_quotient_;
+ unsigned long int sigma_roz_fraction_;
+ unsigned long int first_layer_;
+ unsigned long int last_layer_;
+ unsigned long int shower_len_;
+ unsigned long int core_shower_len_;
+ unsigned long int e_em_over_e_quotient_;
+ unsigned long int e_em_over_e_fraction_;
+ unsigned long int e_em_core_over_e_em_quotient_;
+ unsigned long int e_em_core_over_e_em_fraction_;
+ unsigned long int e_h_early_over_e_quotient_;
+ unsigned long int e_h_early_over_e_fraction_;
+
+ // Extra variables, not available in firmware
+ // Perhaps move to separate "extra" class?
+ HGCalTriggerCellSAShrPtrCollection constituents_;
+
+ // Firmware representation of cluster as sent on links to L1T
+ // ClusterWords packedData_;
+
+ // Firmware representation of cluster sum (input to cluster properties)
+ ClusterSumWords packedData_clustersSums_;
+ };
+
+ typedef std::vector HGCalClusterSACollection;
+ typedef std::unique_ptr HGCalClusterSAPtr;
+ typedef std::vector HGCalClusterSAPtrCollection;
+ typedef std::vector HGCalClusterSAPtrCollections;
+
+} // namespace l1thgcfirmware
+
+#endif
diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusterProperties_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusterProperties_SA.h
new file mode 100644
index 0000000000000..26b2fdf746c5d
--- /dev/null
+++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusterProperties_SA.h
@@ -0,0 +1,44 @@
+#ifndef __L1Trigger_L1THGCal_HGCalHistoClusterProperties_h__
+#define __L1Trigger_L1THGCal_HGCalHistoClusterProperties_h__
+
+#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h"
+#include "L1Trigger/L1THGCal/interface/backend_emulator/CentroidHelper.h"
+#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h"
+#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalCluster_SA.h"
+
+namespace l1thgcfirmware {
+
+ class HGCalHistoClusterProperties {
+ public:
+ HGCalHistoClusterProperties(const l1thgcfirmware::ClusterAlgoConfig& config);
+ ~HGCalHistoClusterProperties() {}
+
+ void runClusterProperties(const l1thgcfirmware::HGCalClusterSAPtrCollection& protoClustersIn,
+ const l1thgcfirmware::CentroidHelperPtrCollection& readoutFlags,
+ HGCalClusterSAPtrCollection& clustersOut) const;
+
+ private:
+ // Cluster property steps
+ void clusterSum(const l1thgcfirmware::HGCalClusterSAPtrCollection& protoClusters,
+ const l1thgcfirmware::CentroidHelperPtrCollection& readoutFlags,
+ l1thgcfirmware::HGCalClusterSAPtrCollection& clusterAccumulation,
+ l1thgcfirmware::HGCalClusterSAPtrCollection& clusterSums) const;
+ void clusterProperties(l1thgcfirmware::HGCalClusterSAPtrCollection& clusterSums) const;
+
+ // Helper functions
+ std::pair sigma_energy(unsigned int N_TC_W,
+ unsigned long int Sum_W2,
+ unsigned int Sum_W) const;
+ std::pair mean_coordinate(unsigned int Sum_Wc, unsigned int Sum_W) const;
+ std::pair sigma_coordinate(unsigned int Sum_W,
+ unsigned long int Sum_Wc2,
+ unsigned int Sum_Wc,
+ double scale = 0) const;
+ std::pair energy_ratio(unsigned int E_N, unsigned int E_D) const;
+ std::vector showerLengthProperties(unsigned long int layerBits) const;
+
+ const l1thgcfirmware::ClusterAlgoConfig& config_;
+ };
+} // namespace l1thgcfirmware
+
+#endif
\ No newline at end of file
diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h
new file mode 100644
index 0000000000000..cebf08e6ab3cb
--- /dev/null
+++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalHistoClusteringConfig_SA.h
@@ -0,0 +1,326 @@
+#ifndef __L1Trigger_L1THGCal_HGCalHistoCluteringConfig_SA_h__
+#define __L1Trigger_L1THGCal_HGCalHistoCluteringConfig_SA_h__
+
+#include