1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
/****************************************************************************
*
* This is a part of PPS offline software.
* Authors: D.J.Damiao , M.E.Pol
****************************************************************************/
#include "EventFilter/CTPPSRawToDigi/interface/CTPPSTotemDataFormatter.h"
#include "EventFilter/CTPPSRawToDigi/interface/CounterChecker.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h"
#include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h"
#include "EventFilter/CTPPSRawToDigi/interface/DiamondVFATFrame.h"
#include "DataFormats/CTPPSDigi/interface/TotemRPDigi.h"
#include "CondFormats/DataRecord/interface/TotemReadoutRcd.h"
#include "DataFormats/CTPPSDigi/interface/TotemFEDInfo.h"
#include <cinttypes>
#include <cstdint>
#include <iostream>
#include <iomanip>
using namespace std;
using namespace edm;
typedef uint64_t word;
CTPPSTotemDataFormatter::CTPPSTotemDataFormatter(std::map<TotemFramePosition, TotemVFATInfo> const &mapping)
: m_WordCounter(0), m_DigiCounter(0) {
int s32 = sizeof(Word32);
int s64 = sizeof(Word64);
int s8 = sizeof(char);
if (s8 != 1 || s32 != 4 * s8 || s64 != 2 * s32) {
LogError("UnexpectedSizes") << " unexpected sizes: "
<< " size of char is: " << s8 << ", size of Word32 is: " << s32
<< ", size of Word64 is: " << s64 << ", send exception";
}
}
void CTPPSTotemDataFormatter::formatRawData(unsigned int lvl1_ID,
RawData &fedRawData,
const Digis &digis,
std::vector<PPSStripIndex> iDdet2fed) {
std::map<int, vector<std::array<uint16_t, 12>>> words;
for (auto const &itDig : digis) {
int fedId;
uint32_t rawId = itDig.first;
const DetDigis &detDigis = itDig.second;
std::array<uint16_t, 12> buf, bufCRC;
std::map<uint32_t, vector<int>> mapIdCh;
for (auto const &it : detDigis) {
m_DigiCounter++;
const int nCH = 128;
int nStrip = it.stripNumber();
int chipPosition = nStrip / nCH;
int channel = nStrip - chipPosition * nCH; //channel from DIGI
uint32_t newrawId = rawId + 8192 * chipPosition; //8192 - distance between chipIds
mapIdCh[newrawId].push_back(channel);
}
for (auto &pId : mapIdCh) {
PPSStripIndex myTest = {pId.first, 0, 0, 0, 0};
// the range has always at most one element
auto range = std::equal_range(iDdet2fed.begin(), iDdet2fed.end(), myTest, compare);
if (range.first != range.second) {
auto i = range.first - iDdet2fed.begin();
for (int b = 0; b < 12; b++) {
buf[b] = 0;
bufCRC[b] = 0;
}
TotemRPDetId chipId(iDdet2fed.at(i).id);
for (auto &ch : pId.second) {
int chInWord = ch / 16;
buf[9 - chInWord] |= (1 << (ch % 16)); //data[8->1]
bufCRC[chInWord + 1] = buf[9 - chInWord];
}
fedId = iDdet2fed.at(i).fedid;
int idxInFiber = iDdet2fed.at(i).idxinfiber;
int gohId = iDdet2fed.at(i).gohid;
unsigned int hFlag = 0x90; //vmRaw
buf[0] = (hFlag << 8) | (gohId << 4) | (idxInFiber << 0); //
buf[1] = (pId.first >> 15); //data[9]
bufCRC[9] = buf[1];
Word16 crc_fin = 0xffff;
for (int i = 11; i >= 1; i--)
crc_fin = VFATFrame::calculateCRC(crc_fin, bufCRC[i]);
buf[10] = crc_fin; //data[0]
buf[11] = (15 << 12) | (0 << 8) | (12 << 0); //build trailer as RawDataUnpacker
m_WordCounter++;
words[fedId].push_back(buf);
} // range
} // mapIdCh
} //digis
typedef std::map<int, vector<std::array<uint16_t, 12>>>::const_iterator RI;
std::map<int, vector<uint16_t>> words16;
for (auto &itFed : words) {
int fedId = itFed.first;
int wordsS = words.find(fedId)->second.size();
//due to OrbitCounter block at RawDataUnpacker
words16[fedId].emplace_back(0);
words16[fedId].emplace_back(0);
//writing data in 16-bit words
for (int k = 0; k < wordsS; k++) {
for (int b = 0; b < 12; b++) {
words16[fedId].push_back(words.find(fedId)->second.at(k)[b]);
}
}
// since raw words are written in the form of 64-bit packets
// add extra 16-bit words to make number of words even if necessary
while (words16.find(fedId)->second.size() % 4 != 0)
words16[fedId].emplace_back(0);
// size in Bytes; create output structure
auto dataSize = (words16.find(fedId)->second.size()) * sizeof(Word16);
int nHeaders = 1;
int nTrailers = 1;
dataSize += (nHeaders + nTrailers) * sizeof(Word64);
FEDRawData rawData{dataSize};
// get begining of data;
Word64 *word = reinterpret_cast<Word64 *>(rawData.data());
// write one header
FEDHeader::set(reinterpret_cast<unsigned char *>(word), 0, lvl1_ID, 0, fedId, 3);
word++;
// write data
unsigned int nWord16InFed = words16.find(fedId)->second.size();
for (unsigned int i = 0; i < nWord16InFed; i += 4) {
*word = (Word64(words16.find(fedId)->second[i + 3]) << 48) | (Word64(words16.find(fedId)->second[i + 2]) << 32) |
(Word64(words16.find(fedId)->second[i + 1]) << 16) | words16.find(fedId)->second[i];
word++;
}
// write one trailer
FEDTrailer::set(reinterpret_cast<unsigned char *>(word), dataSize / sizeof(Word64), 0, 0, 0);
word++;
// check memory
if (word != reinterpret_cast<Word64 *>(rawData.data() + dataSize)) {
string s = "** PROBLEM in CTPPSTotemDataFormatter !!!";
throw cms::Exception(s);
}
fedRawData[fedId] = rawData;
} // end of rawData
}
|