Skip to content

Commit a9d51ca

Browse files
authored
Merge pull request #48421 from smorovic/151x-FEDRawDataBuffer
[DAQ] Phase-2 raw data product
2 parents 22c605f + 7e21eeb commit a9d51ca

26 files changed

+1147
-258
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#ifndef DataFormats_FEDRawData_RawDataBuffer_h
2+
#define DataFormats_FEDRawData_RawDataBuffer_h
3+
4+
/** \class RawDataBuffer
5+
* A product storing raw data for all SourceIDs in a Event, intended
6+
* for persistent storage in ROOT Streamer or root files.
7+
* For Phase-2 source ID is 32-bit, so map is used instead of linear vector
8+
* as in the FEDRawDataCollection. Legacy mode is added to use it for
9+
* Phase-1 data.
10+
* IMPORTANT: this is not a final format version for Phase-2 and only intended
11+
* for detector development. It will not be frozen until the end of LS3.
12+
* \author S. Morovic
13+
*/
14+
15+
#include "DataFormats/Common/interface/traits.h"
16+
#include "FWCore/Utilities/interface/Exception.h"
17+
18+
#include <vector>
19+
#include <map>
20+
#include <span>
21+
22+
/*
23+
* Phase2 source or FED wrapper pointing to a span of RawDataBuffer data
24+
* */
25+
26+
class RawFragmentWrapper {
27+
private:
28+
uint32_t sourceId_;
29+
bool valid_;
30+
uint32_t size_;
31+
std::span<const unsigned char> span_;
32+
33+
public:
34+
RawFragmentWrapper() : sourceId_(0), valid_(false) {}
35+
RawFragmentWrapper(uint32_t sourceId, std::span<const unsigned char>&& span)
36+
: sourceId_(sourceId), valid_(true), span_(span) {}
37+
std::span<const unsigned char> const& data() const { return span_; }
38+
std::span<const unsigned char> dataHeader(uint32_t expSize) const {
39+
if (expSize > span_.size())
40+
throw cms::Exception("RawFragmentWrapper") << "Expected trailer too large: " << expSize << " > " << span_.size();
41+
return span_.subspan(0, expSize);
42+
}
43+
std::span<const unsigned char> dataTrailer(uint32_t expSize) const {
44+
if (expSize > span_.size())
45+
throw cms::Exception("RawFragmentWrapper") << "Expected trailer too large: " << expSize << " > " << span_.size();
46+
return span_.subspan(span_.size() - expSize, expSize);
47+
}
48+
std::span<const unsigned char> payload(uint32_t expSizeHeader, uint32_t expSizeTrailer) const {
49+
if (expSizeHeader + expSizeTrailer > span_.size())
50+
throw cms::Exception("RawFragmentWrapper")
51+
<< "Trailer and header too large: " << expSizeHeader << " + " << expSizeTrailer << " > " << span_.size();
52+
return span_.subspan(expSizeHeader, span_.size() - expSizeTrailer - expSizeHeader);
53+
}
54+
55+
uint32_t size() const { return span_.size(); }
56+
uint32_t sourceId() const { return sourceId_; }
57+
bool isValid() const { return valid_; }
58+
};
59+
60+
/*
61+
* Contains metadata vector with source ID or FED ID offsets and size
62+
* and data buffer as vector of bytes
63+
*/
64+
65+
class RawDataBuffer : public edm::DoNotRecordParents {
66+
public:
67+
RawDataBuffer();
68+
RawDataBuffer(uint32_t preallocSize);
69+
70+
unsigned char* addSource(uint32_t sourceId, unsigned char const* buf, uint32_t size);
71+
void setPhase1Range() { phase1Range_ = true; }
72+
73+
const RawFragmentWrapper fragmentData(uint32_t sourceId) const;
74+
const RawFragmentWrapper fragmentData(
75+
std::map<uint32_t, std::pair<uint32_t, uint32_t>>::const_iterator const& it) const;
76+
77+
unsigned char getByte(unsigned int pos) const { return data_.at(pos); }
78+
std::vector<unsigned char> data() const { return data_; }
79+
std::map<uint32_t, std::pair<uint32_t, uint32_t>> const& map() const { return map_; }
80+
81+
private:
82+
uint32_t usedSize_ = 0;
83+
std::map<uint32_t, std::pair<uint32_t, uint32_t>> map_; //map of source id fragment offset and size pairs
84+
std::vector<unsigned char> data_; //raw data byte vector
85+
bool phase1Range_ = false;
86+
};
87+
88+
#endif
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
#ifndef DataFormats_FEDRawData_SLinkRocketHeaders_h
2+
#define DataFormats_FEDRawData_SLinkRocketHeaders_h
3+
4+
#include "FWCore/Utilities/interface/Exception.h"
5+
6+
//#include <memory>
7+
#include <span>
8+
9+
/*
10+
* DTH Orbit header, event fragment trailer and SlinkRocket Header and Trailer accompanying
11+
* slink payload. Format that is sent is is low-endian for multi-byte fields
12+
*
13+
* Version 1 DTH and Version 3 SLinkRocket
14+
*
15+
* */
16+
17+
constexpr uint32_t SLR_MAX_EVENT_LEN = (1 << 20) - 1;
18+
constexpr uint32_t SLR_WORD_NUM_BYTES_SHIFT = 4;
19+
20+
//SLinkExpress classes
21+
22+
//begin and end event markers
23+
constexpr uint8_t SLR_BOE = 0x55;
24+
constexpr uint8_t SLR_EOE = 0xaa;
25+
26+
//minimal SLinkRocket version overlay
27+
class SLinkRocketHeader_version {
28+
public:
29+
SLinkRocketHeader_version() {}
30+
uint8_t version() const { return version_; }
31+
bool verifyMarker() const { return boe_ == SLR_BOE; }
32+
33+
private:
34+
uint32_t source_id_;
35+
uint16_t l1a_types_;
36+
uint8_t phys_type_;
37+
uint8_t emu_status_ : 2, res1_ : 6;
38+
uint64_t event_id_ : 44, res2_ : 8, version_ : 4, boe_ : 8;
39+
};
40+
41+
class SLinkRocketHeader_v3 {
42+
public:
43+
SLinkRocketHeader_v3(uint32_t source_id, uint16_t l1a_types, uint8_t l1a_phys, uint8_t emu_status, uint64_t event_id)
44+
: source_id_(source_id),
45+
l1a_types_(l1a_types),
46+
phys_type_(l1a_phys),
47+
emu_status_(emu_status),
48+
event_id_(event_id) {}
49+
50+
uint32_t sourceID() const { return source_id_; }
51+
uint16_t l1aTypes() const { return l1a_types_; }
52+
uint8_t l1aPhysType() const { return phys_type_; }
53+
uint8_t emuStatus() const { return emu_status_; }
54+
uint64_t globalEventID() const { return event_id_; }
55+
uint8_t version() const { return version_; }
56+
bool verifyMarker() const { return boe_ == SLR_BOE; }
57+
58+
private:
59+
uint32_t source_id_;
60+
uint16_t l1a_types_;
61+
uint8_t phys_type_;
62+
uint8_t emu_status_ : 2, res1_ : 6;
63+
uint64_t event_id_ : 44, res2_ : 8, version_ : 4 = 3, boe_ : 8 = SLR_BOE;
64+
};
65+
66+
class SLinkRocketTrailer_v3 {
67+
public:
68+
SLinkRocketTrailer_v3(
69+
uint16_t status, uint16_t crc, uint32_t orbit_id, uint16_t bx_id, uint32_t evtlen_word_count, uint16_t daq_crc)
70+
: crc_(crc), orbit_id_(orbit_id), bx_id_(bx_id), event_length_wcount_(evtlen_word_count), daq_crc_(daq_crc) {
71+
status_.all_ = status;
72+
}
73+
74+
uint16_t status() const { return status_.all_; }
75+
uint16_t crc() const { return crc_; }
76+
uint32_t orbitID() const { return orbit_id_; }
77+
uint16_t bxID() const { return bx_id_; }
78+
uint32_t eventLenBytes() const { return uint32_t(event_length_wcount_) << SLR_WORD_NUM_BYTES_SHIFT; }
79+
uint16_t daqCRC() const { return daq_crc_; }
80+
bool verifyMarker() const { return eoe_ == SLR_EOE; }
81+
82+
private:
83+
union {
84+
struct {
85+
uint16_t fed_crc_error_ : 1, /* FED CRC error was detected by DTH and corrected */
86+
slink_crc_error_ : 1, /* Set when the slink receviver finds a mistmatch between calculated crc and daq_crc. It should never happen */
87+
source_id_error_ : 1, /* SOURCE_ID is not expected */
88+
sync_lost_error_ : 1, /* Sync lost detected by DTH */
89+
fragment_cut_ : 1, /* Fragment was cut */
90+
res_ : 11;
91+
} bits_;
92+
uint16_t all_;
93+
} status_;
94+
uint16_t crc_; /* CRC filled by the FED */
95+
uint32_t orbit_id_;
96+
uint32_t bx_id_ : 12,
97+
event_length_wcount_ : 20; /* Length is encoded in multiples of 128 bits (16 bytes). I.e needs to be shifter by 4 */
98+
uint32_t reserved_ : 8, daq_crc_ : 16, /* CRC filled by the slink sender */
99+
eoe_ : 8 = SLR_EOE;
100+
};
101+
102+
/*
103+
* version-independent header view parent class
104+
* */
105+
106+
class SLinkRocketHeaderView {
107+
public:
108+
virtual ~SLinkRocketHeaderView() = default;
109+
virtual uint32_t sourceID() const = 0;
110+
virtual uint16_t l1aTypes() const = 0;
111+
virtual uint8_t l1aPhysType() const = 0;
112+
virtual uint8_t emuStatus() const = 0;
113+
virtual uint64_t globalEventID() const = 0;
114+
virtual uint8_t version() const = 0;
115+
virtual bool verifyMarker() const = 0;
116+
};
117+
118+
/*
119+
* header v3 view abstraction
120+
* */
121+
122+
class SLinkRocketHeaderView_v3 : public SLinkRocketHeaderView {
123+
public:
124+
SLinkRocketHeaderView_v3(const void* header) : header_(static_cast<const SLinkRocketHeader_v3*>(header)) {}
125+
126+
uint32_t sourceID() const override { return header_->sourceID(); }
127+
uint16_t l1aTypes() const override { return header_->l1aTypes(); }
128+
uint8_t l1aPhysType() const override { return header_->l1aPhysType(); }
129+
uint8_t emuStatus() const override { return header_->emuStatus(); }
130+
uint64_t globalEventID() const override { return header_->globalEventID(); }
131+
uint8_t version() const override { return header_->version(); }
132+
bool verifyMarker() const override { return header_->verifyMarker(); }
133+
134+
private:
135+
const SLinkRocketHeader_v3* header_;
136+
};
137+
138+
static inline std::unique_ptr<SLinkRocketHeaderView> makeSLinkRocketHeaderView(const void* buf) {
139+
auto version = static_cast<const SLinkRocketHeader_version*>(buf)->version();
140+
if (version == 3)
141+
return std::unique_ptr<SLinkRocketHeaderView>(
142+
static_cast<SLinkRocketHeaderView*>(new SLinkRocketHeaderView_v3(buf)));
143+
throw cms::Exception("SLinkRocketHeaderView::makeView")
144+
<< "unknown SLinkRocketHeader version: " << (unsigned int)version;
145+
}
146+
147+
static inline std::unique_ptr<SLinkRocketHeaderView> makeSLinkRocketHeaderView(std::span<const unsigned char> const& s) {
148+
if (s.size() < sizeof(SLinkRocketHeader_version))
149+
throw cms::Exception("SLinkRocketHeaderView::makeView")
150+
<< "size is smaller than SLink header version fields: " << s.size();
151+
auto version = static_cast<const SLinkRocketHeader_version*>(static_cast<const void*>(&s[0]))->version();
152+
if (version == 3 && s.size() != sizeof(SLinkRocketHeader_v3))
153+
throw cms::Exception("SLinkRocketHeaderView::makeView") << "SLinkRocketHeader v3 size mismatch: got " << s.size()
154+
<< " expected:" << sizeof(SLinkRocketHeader_v3) << " bytes";
155+
156+
return makeSLinkRocketHeaderView(static_cast<const void*>(&s[0]));
157+
}
158+
159+
/*
160+
* version-independent trailer view parent class
161+
* */
162+
163+
class SLinkRocketTrailerView {
164+
public:
165+
virtual ~SLinkRocketTrailerView() = default;
166+
virtual uint16_t status() const = 0;
167+
virtual uint16_t crc() const = 0;
168+
virtual uint32_t orbitID() const = 0;
169+
virtual uint16_t bxID() const = 0;
170+
virtual uint32_t eventLenBytes() const = 0;
171+
virtual uint16_t daqCRC() const = 0;
172+
virtual bool verifyMarker() const = 0;
173+
};
174+
175+
/*
176+
* trailer v3 view abstraction
177+
* */
178+
179+
class SLinkRocketTrailerView_v3 : public SLinkRocketTrailerView {
180+
public:
181+
SLinkRocketTrailerView_v3(const void* trailer) : trailer_(static_cast<const SLinkRocketTrailer_v3*>(trailer)) {}
182+
uint16_t status() const override { return trailer_->status(); }
183+
uint16_t crc() const override { return trailer_->crc(); }
184+
uint32_t orbitID() const override { return trailer_->orbitID(); }
185+
uint16_t bxID() const override { return trailer_->bxID(); }
186+
uint32_t eventLenBytes() const override { return trailer_->eventLenBytes(); }
187+
uint16_t daqCRC() const override { return trailer_->daqCRC(); }
188+
bool verifyMarker() const override { return trailer_->verifyMarker(); }
189+
190+
private:
191+
const SLinkRocketTrailer_v3* trailer_;
192+
};
193+
194+
static inline std::unique_ptr<SLinkRocketTrailerView> makeSLinkRocketTrailerView(const void* buf, uint8_t version) {
195+
if (version == 3)
196+
return std::unique_ptr<SLinkRocketTrailerView>(
197+
static_cast<SLinkRocketTrailerView*>(new SLinkRocketTrailerView_v3(buf)));
198+
throw cms::Exception("SLinkRocketTrailerView::makeView")
199+
<< "unknown SLinkRocketHeader version: " << (unsigned int)version;
200+
}
201+
202+
static inline std::unique_ptr<SLinkRocketTrailerView> makeSLinkRocketTrailerView(
203+
std::span<const unsigned char> const& s, uint8_t version) {
204+
if (version == 3 && s.size() < sizeof(SLinkRocketTrailer_v3))
205+
throw cms::Exception("SLinkRocketTrailerView::makeView")
206+
<< "SLinkRocketTrailer v3 size mismatch: got " << s.size() << " expected " << sizeof(SLinkRocketTrailer_v3)
207+
<< " bytes";
208+
return makeSLinkRocketTrailerView(static_cast<const void*>(&s[0]), version);
209+
}
210+
#endif
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef DataFormats_FEDRawData_SourceIdNumbering_h
2+
#define DataFormats_FEDRawData_SourceIdNumbering_h
3+
4+
/** \class SourceIDNumbering
5+
*
6+
* This placeholdeer class will hold the fed numbering scheme for the CMS Source IDs
7+
* for Phase-2 readout. * No two sources should have the same id. Each subdetector
8+
* will have a reserved range. Gaps between ranges might give flexibility to the
9+
* numbering. Total available range is unsigned 32-bit.
10+
*
11+
* \author S. Morovic - UCSD
12+
*/
13+
14+
class SourceIdNumbering {
15+
public:
16+
enum {
17+
//dummy range definition for testing. This is not stable and will possible be reassigned
18+
MinDummySourceID = 0xfffffff0,
19+
MaxDummySourceID = 0xfffffffe,
20+
MAXSourceID = 0xffffffff
21+
};
22+
};
23+
24+
#endif // SourceIdNumbering_H
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/** \file
2+
* implementation of DaqRawDataBuffer
3+
*
4+
* \author N. Amapane - S. Argiro'
5+
*/
6+
7+
#include <DataFormats/FEDRawData/interface/RawDataBuffer.h>
8+
#include <DataFormats/FEDRawData/interface/FEDNumbering.h>
9+
#include <DataFormats/FEDRawData/interface/SourceIDNumbering.h>
10+
11+
RawDataBuffer::RawDataBuffer() {}
12+
RawDataBuffer::RawDataBuffer(uint32_t preallocSize) : usedSize_(0), data_(preallocSize) {}
13+
14+
unsigned char* RawDataBuffer::addSource(uint32_t sourceId, unsigned char const* buf, uint32_t size) {
15+
auto maxSize = data_.size();
16+
if ((uint64_t)usedSize_ + (uint64_t)size > maxSize)
17+
throw cms::Exception("RawDataBuffer") << "RawDataBuffer size overflow adding ID " << sourceId << ": " << usedSize_
18+
<< " + " << size << " > " << maxSize;
19+
20+
if (phase1Range_) {
21+
if (sourceId > FEDNumbering::lastFEDId())
22+
throw cms::Exception("RawDataBuffer") << "FED ID " << sourceId << " out of range";
23+
} else {
24+
if (size % 16)
25+
throw cms::Exception("RawDataBuffer")
26+
<< "source " << sourceId << " data not multiple of 16 bytes (" << size << ")";
27+
if (size < 32)
28+
throw cms::Exception("RawDataBuffer") << "source " << sourceId << " data is too small: " << size << " bytes";
29+
}
30+
31+
void* targetAddr = (void*)(&data_[usedSize_]);
32+
//allow also buffer preparation without copy if source pointer is null
33+
if (buf != nullptr)
34+
memcpy(targetAddr, (void*)buf, size);
35+
auto usedSize = usedSize_;
36+
map_.emplace(sourceId, std::make_pair(usedSize, size));
37+
usedSize_ += size;
38+
return (unsigned char*)targetAddr;
39+
}
40+
41+
const RawFragmentWrapper RawDataBuffer::fragmentData(uint32_t sourceId) const {
42+
if (phase1Range_ && sourceId > FEDNumbering::lastFEDId())
43+
throw cms::Exception("RawDataBuffer") << "can not fetch out of range FED ID " << sourceId;
44+
auto it = map_.find(sourceId);
45+
if (it == map_.end()) {
46+
return RawFragmentWrapper();
47+
}
48+
const auto& desc = it->second;
49+
std::span<const unsigned char>&& byte_span{reinterpret_cast<const unsigned char*>(this->data_.data() + desc.first),
50+
desc.second};
51+
return RawFragmentWrapper(sourceId, std::move(byte_span));
52+
}
53+
54+
const RawFragmentWrapper RawDataBuffer::fragmentData(
55+
std::map<uint32_t, std::pair<uint32_t, uint32_t>>::const_iterator const& it) const {
56+
if (it == map_.end()) {
57+
return RawFragmentWrapper();
58+
}
59+
const auto& desc = it->second;
60+
std::span<const unsigned char>&& byte_span{reinterpret_cast<const unsigned char*>(this->data_.data() + desc.first),
61+
desc.second};
62+
return RawFragmentWrapper(it->first, std::move(byte_span));
63+
}

DataFormats/FEDRawData/src/classes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <vector>
22
#include <DataFormats/FEDRawData/interface/FEDRawData.h>
33
#include <DataFormats/FEDRawData/interface/FEDRawDataCollection.h>
4+
#include <DataFormats/FEDRawData/interface/RawDataBuffer.h>
45
#include <DataFormats/FEDRawData/interface/FEDHeader.h>
56
#include <DataFormats/FEDRawData/interface/FEDTrailer.h>
67
#include <DataFormats/FEDRawData/src/fed_header.h>

0 commit comments

Comments
 (0)