Skip to content

Commit

Permalink
Merge pull request #45606 from p2l1-gtEmulator/pattern-writing
Browse files Browse the repository at this point in the history
Phase-2 GT interface update and slice test pattern writers
  • Loading branch information
cmsbuild authored Sep 11, 2024
2 parents 20dc5ff + 20188f2 commit 58c198d
Show file tree
Hide file tree
Showing 26 changed files with 1,249 additions and 578 deletions.
16 changes: 15 additions & 1 deletion DataFormats/L1Trigger/interface/P2GTCandidate.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace l1t {
typedef ap_int<14> hwEta_t;
typedef ap_int<18> hwZ0_t;
typedef ap_uint<11> hwIsolationPT_t;
typedef ap_uint<4> hwQualityFlags_t;
typedef ap_uint<6> hwQualityFlags_t;
typedef ap_uint<10> hwQualityScore_t;
typedef ap_uint<1> hwCharge_t;
typedef ap_int<12> hwD0_t;
Expand All @@ -43,6 +43,7 @@ namespace l1t {
typedef ap_int<10> hwSeed_z0_t;
typedef ap_uint<16> hwScalarSumPT_t;
typedef ap_uint<5> hwNumber_of_tracks_t;
typedef ap_uint<4> hwNumber_of_displaced_tracks_t;
typedef ap_uint<12> hwSum_pT_pv_t;
typedef ap_uint<2> hwType_t;
typedef ap_uint<8> hwNumber_of_tracks_in_pv_t;
Expand Down Expand Up @@ -117,6 +118,10 @@ namespace l1t {
hwNumber_of_tracks_ = hwNumber_of_tracks.to_int();
}

void setHwNumber_of_displaced_tracks(hwNumber_of_displaced_tracks_t hwNumber_of_displaced_tracks) {
hwNumber_of_displaced_tracks_ = hwNumber_of_displaced_tracks.to_int();
}

void setHwSum_pT_pv(hwSum_pT_pv_t hwSum_pT_pv) { hwSum_pT_pv_ = hwSum_pT_pv.to_int(); }
void setHwType(hwType_t hwType) { hwType_ = hwType.to_int(); }
void setHwNumber_of_tracks_in_pv(hwNumber_of_tracks_in_pv_t hwNumber_of_tracks_in_pv) {
Expand Down Expand Up @@ -238,6 +243,13 @@ namespace l1t {
return static_cast<int>(hwNumber_of_tracks_);
}

hwNumber_of_displaced_tracks_t hwNumber_of_displaced_tracks() const {
if (!hwNumber_of_displaced_tracks_) {
throw std::invalid_argument("Object doesn't have hwNumber_of_displaced_tracks");
}
return static_cast<int>(hwNumber_of_displaced_tracks_);
}

hwSum_pT_pv_t hwSum_pT_pv() const {
if (!hwSum_pT_pv_) {
throw std::invalid_argument("Object doesn't have sum_pT_pv");
Expand Down Expand Up @@ -285,6 +297,7 @@ namespace l1t {
int hwSeed_z0_toInt() const { return hwSeed_z0().to_int(); }
int hwScalarSumPT_toInt() const { return hwScalarSumPT().to_int(); }
int hwNumber_of_tracks_toInt() const { return hwNumber_of_tracks().to_int(); }
int hwNumber_of_displaced_tracks_toInt() const { return hwNumber_of_displaced_tracks().to_int(); }
int hwSum_pT_pv_toInt() const { return hwSum_pT_pv().to_int(); }
int hwType_toInt() const { return hwType().to_int(); }
int hwNumber_of_tracks_in_pv_toInt() const { return hwNumber_of_tracks_in_pv().to_int(); }
Expand Down Expand Up @@ -329,6 +342,7 @@ namespace l1t {
Optional<int> hwSeed_z0_;
Optional<int> hwScalarSumPT_;
Optional<int> hwNumber_of_tracks_;
Optional<int> hwNumber_of_displaced_tracks_;

// TODO ?
Optional<int> hwSum_pT_pv_;
Expand Down
3 changes: 2 additions & 1 deletion DataFormats/L1Trigger/src/P2GTCandidate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ namespace l1t {
hwQualityFlags_ == rhs.hwQualityFlags_ && hwCharge_ == rhs.hwCharge_ && hwD0_ == rhs.hwD0_ &&
hwBeta_ == rhs.hwBeta_ && hwMass_ == rhs.hwMass_ && hwIndex_ == rhs.hwIndex_ &&
hwSeed_pT_ == rhs.hwSeed_pT_ && hwSeed_z0_ == rhs.hwSeed_z0_ && hwScalarSumPT_ == rhs.hwScalarSumPT_ &&
hwNumber_of_tracks_ == rhs.hwNumber_of_tracks_ && hwSum_pT_pv_ == rhs.hwSum_pT_pv_ &&
hwNumber_of_tracks_ == rhs.hwNumber_of_tracks_ &&
hwNumber_of_displaced_tracks_ == rhs.hwNumber_of_displaced_tracks_ && hwSum_pT_pv_ == rhs.hwSum_pT_pv_ &&
hwType_ == rhs.hwType_ && hwNumber_of_tracks_in_pv_ == rhs.hwNumber_of_tracks_in_pv_ &&
hwNumber_of_tracks_not_in_pv_ == rhs.hwNumber_of_tracks_not_in_pv_;
}
Expand Down
3 changes: 2 additions & 1 deletion DataFormats/L1Trigger/src/classes_def.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@


<class name="l1t::P2GTCandidate::Optional<int>"/>
<class name="l1t::P2GTCandidate" ClassVersion="10">
<class name="l1t::P2GTCandidate" ClassVersion="11">
<version ClassVersion="11" checksum="2947772579"/>
<version ClassVersion="10" checksum="2728416623"/>
</class>
<class name="l1t::P2GTCandidateCollection"/>
Expand Down
99 changes: 96 additions & 3 deletions L1Trigger/Phase2L1GT/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,19 @@ process.TripleTkMuon533 = l1tGTTripleObjectCond.clone(
tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"),
minPt = cms.double(5),
maxAbsEta = cms.double(2.4),
minQualityScore = cms.uint32(0)
qualityFlags = cms.uint32(0b0001)
),
collection2 = cms.PSet(
tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"),
minPt = cms.double(3),
maxAbsEta = cms.double(2.4),
minQualityScore = cms.uint32(0)
qualityFlags = cms.uint32(0b0001)
),
collection3 = cms.PSet(
tag = cms.InputTag("l1tGTProducer", "GMTTkMuons"),
minPt = cms.double(3),
maxAbsEta = cms.double(2.4),
minQualityScore = cms.uint32(0)
qualityFlags = cms.uint32(0b0001)
),
# Correlations are ambiguous (can be {1,2}, {1,3}, or {2,3}), correlXY PSets are thus required.
correl12 = cms.PSet(
Expand Down Expand Up @@ -116,9 +116,12 @@ Possible cuts on single quantities are:
| `maxRelIsolationPt` | $\mathrm{isolationPT} < X \cdot p_T$ | `cms.double` | `ceil(X * pT_lsb * 2**18 / isolationPT)` |
| `minPrimVertDz`* | $\| z_0 - Z_{0,i} \| > X $ | `cms.double` | `floor(X / z0_lsb)` |
| `maxPrimVertDz`* | $\| z_0 - Z_{0,i} \| < X $ | `cms.double` | `ceil(X / z0_lsb)` |
| `minPtMultiplicityCut`** | $\sum \left( p_T > X\right) \geq N$ | `cms.double` | `floor(X / pT_lsb)` |

\* : To select a $Z_0$ index $i$ from the `GTTPrimaryVert` collection for the comparison use `primVertex = cms.uint32(i)`. This parameter is mandatory when using a `maxPrimVertDz` cut.

\** : Requires additional parameter $N$ with `minPtMultiplicityN = cms.uint32(N)`.

### $\eta$-regional cuts

Certain cuts can also be specified $\eta$-region dependent, to allow different thresholds in different regions. In order to use this feature, one has to first provide the lower bounds for the regions via `regionsAbsEtaLowerBounds`. This parameter takes an `cms.vdouble`, whose length determines the number of $\eta$-regions. A region then ranges from the specified lower bound (inclusive) up to the next region's lower bound (exclusive). The last region's upper bound is always the maximum allowed $|\eta| = 2\pi$. One can use additional global $\eta$ or $|\eta|$ cuts to exclude large $|\eta|$ values, effectively overriding the last region's upper bound. The following cuts can be specified per each $\eta$-region:
Expand Down Expand Up @@ -196,3 +199,93 @@ process.pDoubleTkEle25_12 = cms.Path(process.DoubleTkEle2512)

algorithms.append(cms.PSet(expression = cms.string("pSingleTkMuon22 or pDoubleTkEle25_12")))
```

## Firmware pattern writers

There are 3 types of Global Trigger pattern writers currently implemented.

* `L1GTAlgoBoardWriter`: Used to write out the algorithm bits into 2 channels. With config

| Name | Datatype | Description |
|:-----|:----------:|:--------------|
| `filename` | `cms.string` | The filename prefix to use for pattern files (required) |
| `fileExtension` | `cms.string` | `txt`, `txt.gz` or `txt.xz` (default: `txt`) |
| `algoBlocksTag` | `cms.InputTag` | AlgoBlock producer input tag to use (required) |
| `maxFrames` | `cms.unit32` | Maximum number of frames (default: 1024) |
| `maxEvents` | `cms.unit32` | Maximum number of events (default: events that fit into `maxFrames`) |
| `channels` | `cms.vuint32` | Vector of 2 channel numbers for output (required) |
| `algoBitMask` | `cms.vuint64` | Vector of 9 64 bit masks (default: all set to 1) |
| `patternFormat` | `cms.string` | `APx`, `EMPv1`, `EMPv2` or `X2O` (default: `EMPv2`) |

* `L1GTFinOrBoardWriter`: Used to write out Final OR bits (beforeBxMaskAndPrescale, beforePrescale and final) each on a different channel for the low bits (0 - 575), mid bits (576 - 1151) and high bits (1152 - 1727). 9 channels in total + one channel for the passing Final OR trigger types. Config:

| Name | Datatype | Description |
|:-----|:----------:|:--------------|
| `filename` | `cms.string` | The filename prefix to use for pattern files (required) |
| `fileExtension` | `cms.string` | `txt`, `txt.gz` or `txt.xz` (default: `txt`) |
| `algoBlocksTag` | `cms.InputTag` | AlgoBlock producer input tag to use (required) |
| `maxFrames` | `cms.unit32` | Maximum number of frames (default: 1024) |
| `maxEvents` | `cms.unit32` | Maximum number of events (default: events that fit into `maxFrames`) |
| `channelsLow` | `cms.vuint32` | Vector of 3 channel numbers for low bits (0 - 575) (required) |
| `channelsMid` | `cms.vuint32` | Vector of 3 channel numbers for mid bits (576 - 1151) (required) |
| `channelsHigh` | `cms.vuint32` | Vector of 3 channel numbers for high bits (1152 - 1727) (required) |
| `channelFinOr` | `cms.uint32` | Channel for FinalOr trigger types (required) |
| `patternFormat` | `cms.string` | `APx`, `EMPv1`, `EMPv2` or `X2O` (default: `EMPv2`) |

* `L1GTObjectBoardWriter`: Used to write input and output object patterns using the upstream provided pack functions.

| Name | Datatype | Description |
|:-----|:----------:|:--------------|
| `filename` | `cms.string` | The filename prefix to use for pattern files (required) |
| `fileExtension` | `cms.string` | `txt`, `txt.gz` or `txt.xz` (default: `txt`) |
| `maxFrames` | `cms.unit32` | Maximum number of frames (default: 1024) |
| `maxEvents` | `cms.unit32` | Maximum number of events (default: events that fit into `maxFrames`) |
| `patternFormat` | `cms.string` | `APx`, `EMPv1`, `EMPv2` or `X2O` (default: `EMPv2`) |
| `bufferFileType`| `cms.string` | Either `input` or `output` (required) |
| `InputChannels.GCT_1` | `cms.vuint32` | Channels for GCT link 1 (required if `bufferFileType` = `input`) |
| `InputChannels.GMT_1` | `cms.vuint32` | Channels for GMT link 1 (required if `bufferFileType` = `input`) |
| `InputChannels.GTT_1` | `cms.vuint32` | Channels for GTT link 1 (required if `bufferFileType` = `input`) |
| `InputChannels.GTT_2` | `cms.vuint32` | Channels for GTT link 2 (required if `bufferFileType` = `input`) |
| `InputChannels.GTT_3` | `cms.vuint32` | Channels for GTT link 3 (required if `bufferFileType` = `input`) |
| `InputChannels.GTT_4` | `cms.vuint32` | Channels for GTT link 4 (required if `bufferFileType` = `input`) |
| `InputChannels.CL2_1` | `cms.vuint32` | Channels for CL2 link 1 (required if `bufferFileType` = `input`) |
| `InputChannels.CL2_2` | `cms.vuint32` | Channels for CL2 link 2 (required if `bufferFileType` = `input`) |
| `InputChannels.CL2_3` | `cms.vuint32` | Channels for CL2 link 3 (required if `bufferFileType` = `input`) |
| `OutputChannels.GTTPromptJets` | `cms.vuint32` | Channels for collection GTTPromptJets (required if `bufferFileType` = `output`) |
| `OutputChannels.GTTDisplacedJets` | `cms.vuint32` | Channels for collection GTTDisplacedJets (required if `bufferFileType` = `output`) |
| `OutputChannels.GTTPromptHtSum` | `cms.vuint32` | Channels for collection GTTPromptHtSum (required if `bufferFileType` = `output`) |
| `OutputChannels.GTTDisplacedHtSum` | `cms.vuint32` | Channels for collection GTTDisplacedHtSum (required if `bufferFileType` = `output`) |
| `OutputChannels.GTTEtSum` | `cms.vuint32` | Channels for collection GTTEtSum (required if `bufferFileType` = `output`) |
| `OutputChannels.GTTPrimaryVert` | `cms.vuint32` | Channels for collection GTTPrimaryVert (required if `bufferFileType` = `output`) |
| `OutputChannels.GMTSaPromptMuons` | `cms.vuint32` | Channels for collection GMTSaPromptMuons (required if `bufferFileType` = `output`) |
| `OutputChannels.GMTSaDisplacedMuons` | `cms.vuint32` | Channels for collection GMTSaDisplacedMuons (required if `bufferFileType` = `output`) |
| `OutputChannels.GMTTkMuons` | `cms.vuint32` | Channels for collection GMTTkMuons (required if `bufferFileType` = `output`) |
| `OutputChannels.CL2JetsSC4` | `cms.vuint32` | Channels for collection CL2JetsSC4 (required if `bufferFileType` = `output`) |
| `OutputChannels.CL2JetsSC8` | `cms.vuint32` | Channels for collection CL2JetsSC8 (required if `bufferFileType` = `output`) |
| `OutputChannels.CL2Photons` | `cms.vuint32` | Channels for collection CL2Photons (required if `bufferFileType` = `output`) |
| `OutputChannels.CL2Electrons` | `cms.vuint32` | Channels for collection CL2Electrons (required if `bufferFileType` = `output`) |
| `OutputChannels.CL2Taus` | `cms.vuint32` | Channels for collection CL2Taus (required if `bufferFileType` = `output`) |
| `OutputChannels.CL2EtSum` | `cms.vuint32` | Channels for collection CL2EtSum (required if `bufferFileType` = `output`) |
| `OutputChannels.CL2HtSum` | `cms.vuint32` | Channels for collection CL2HtSum (required if `bufferFileType` = `output`) |

Note: In order to get consistency across multiple pattern files written by multiple writers it is recommended to produce patterns in single threaded mode only (i.e. `process.options.numberOfThreads = 1`).

Default configurations for `L1GTAlgoBoardWriter` and `L1GTObjectBoardWriter` in input and output direction can be pulled into the configuration for each of the two prototype implementations VU9P and VU13P via:

```python
# Serenity VU9P prototype board
process.load('L1Trigger.Phase2L1GT.l1tGTBoardWriterVU9P_cff')

process.pBoardDataInputVU9P = cms.EndPath(process.BoardDataInputVU9P)
process.pBoardDataOutputObjectsVU9P = cms.EndPath(process.BoardDataOutputObjectsVU9P)
process.pAlgoBitBoardDataVU9P = cms.EndPath(process.AlgoBitBoardDataVU9P)
```

```python
# Serenity VU13P prototype board
process.load('L1Trigger.Phase2L1GT.l1tGTBoardWriterVU13P_cff')

process.pBoardDataInputVU13P = cms.EndPath(process.BoardDataInputVU13P)
process.pBoardDataOutputObjectsVU13P = cms.EndPath(process.BoardDataOutputObjectsVU13P)
process.pAlgoBitBoardDataVU13P = cms.EndPath(process.AlgoBitBoardDataVU13P)
```
74 changes: 51 additions & 23 deletions L1Trigger/Phase2L1GT/plugins/L1GTAlgoBoardWriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "L1Trigger/DemonstratorTools/interface/utilities.h"

#include "FWCore/Utilities/interface/EDGetToken.h"
#include "FWCore/Utilities/interface/EDMException.h"

#include "DataFormats/L1Trigger/interface/P2GTAlgoBlock.h"

Expand All @@ -24,6 +25,7 @@
#include <vector>
#include <algorithm>
#include <string>
#include <array>

using namespace l1t;

Expand All @@ -37,6 +39,9 @@ class L1GTAlgoBoardWriter : public edm::one::EDAnalyzer<> {
void analyze(const edm::Event&, const edm::EventSetup&) override;
void endJob() override;

unsigned int eventCounter_;
unsigned int maxEvents_;

const std::array<unsigned int, 2> channels_;
const std::array<unsigned long long, 9> algoBitMask_;
const edm::EDGetTokenT<P2GTAlgoBlockMap> algoBlocksToken_;
Expand All @@ -46,17 +51,33 @@ class L1GTAlgoBoardWriter : public edm::one::EDAnalyzer<> {
std::size_t tmuxCounter_;
};

template <typename T, std::size_t N>
static std::array<T, N> convert(std::vector<T> vec, const char* name) {
if (vec.size() != N) {
throw edm::Exception(edm::errors::Configuration)
<< "The parameter '" << name << "' should have " << N << " elements, but has " << vec.size()
<< " elements in the configuration.\n";
}
std::array<T, N> a;
std::copy_n(std::make_move_iterator(vec.begin()), N, a.begin());
return a;
}

L1GTAlgoBoardWriter::L1GTAlgoBoardWriter(const edm::ParameterSet& config)
: channels_(config.getParameter<std::array<unsigned int, 2>>("channels")),
algoBitMask_(config.getParameter<std::array<unsigned long long, 9>>("algoBitMask")),
algoBlocksToken_(consumes<P2GTAlgoBlockMap>(config.getParameter<edm::InputTag>("algoBlocksTag"))),
: eventCounter_(0),
maxEvents_(config.getUntrackedParameter<unsigned int>("maxEvents")),
channels_(
convert<unsigned int, 2>(config.getUntrackedParameter<std::vector<unsigned int>>("channels"), "channels")),
algoBitMask_(convert<unsigned long long, 9>(
config.getUntrackedParameter<std::vector<unsigned long long>>("algoBitMask"), "algoBitMask")),
algoBlocksToken_(consumes<P2GTAlgoBlockMap>(config.getUntrackedParameter<edm::InputTag>("algoBlocksTag"))),
boardDataWriter_(
l1t::demo::parseFileFormat(config.getParameter<std::string>("patternFormat")),
config.getParameter<std::string>("outputFilename"),
config.getParameter<std::string>("outputFileExtension"),
l1t::demo::parseFileFormat(config.getUntrackedParameter<std::string>("patternFormat")),
config.getUntrackedParameter<std::string>("filename"),
config.getUntrackedParameter<std::string>("fileExtension"),
9,
2,
config.getParameter<unsigned int>("maxLines"),
config.getUntrackedParameter<unsigned int>("maxFrames"),
[](const std::array<unsigned int, 2>& channels) {
l1t::demo::BoardDataWriter::ChannelMap_t channelMap;
for (unsigned int channel : channels) {
Expand Down Expand Up @@ -94,6 +115,12 @@ void L1GTAlgoBoardWriter::analyze(const edm::Event& event, const edm::EventSetup
}

tmuxCounter_ = (tmuxCounter_ + 1) % 2;
eventCounter_++;

if (maxEvents_ != 0 && eventCounter_ == maxEvents_) {
boardDataWriter_.flush();
eventCounter_ = 0;
}
}

void L1GTAlgoBoardWriter::endJob() {
Expand All @@ -106,22 +133,23 @@ void L1GTAlgoBoardWriter::endJob() {

void L1GTAlgoBoardWriter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.add<std::string>("outputFilename");
desc.add<std::string>("outputFileExtension", "txt");
desc.add<edm::InputTag>("algoBlocksTag");
desc.add<std::vector<unsigned int>>("channels");
desc.add<std::vector<unsigned long long>>("algoBitMask",
{0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull});
desc.add<unsigned int>("maxLines", 1024);
desc.add<std::string>("patternFormat", "EMPv2");
desc.addUntracked<std::string>("filename");
desc.addUntracked<std::string>("fileExtension", "txt");
desc.addUntracked<edm::InputTag>("algoBlocksTag");
desc.addUntracked<unsigned int>("maxEvents", 0);
desc.addUntracked<std::vector<unsigned int>>("channels");
desc.addUntracked<std::vector<unsigned long long>>("algoBitMask",
{0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull,
0xffffffffffffffffull});
desc.addUntracked<unsigned int>("maxFrames", 1024);
desc.addUntracked<std::string>("patternFormat", "EMPv2");

descriptions.addDefault(desc);
}
Expand Down
3 changes: 3 additions & 0 deletions L1Trigger/Phase2L1GT/plugins/L1GTDoubleObjectCond.cc
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ bool L1GTDoubleObjectCond::filter(edm::StreamID, edm::Event& event, const edm::E
}
}

condition_result &= collection1Cuts_.checkCollection(*col1);
condition_result &= collection2Cuts_.checkCollection(*col2);

if (condition_result) {
std::unique_ptr<P2GTCandidateVectorRef> triggerCol1 = std::make_unique<P2GTCandidateVectorRef>();

Expand Down
Loading

0 comments on commit 58c198d

Please sign in to comment.