Project
Loading...
Searching...
No Matches
ChipMappingITS.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12// \file ChipMappingITS.cxx
13// \brief Autimatically generated ITS chip <-> module mapping
14
15#include <fairlogger/Logger.h>
17#include <cassert>
18#include <sstream>
19#include <iomanip>
20
21using namespace o2::itsmft;
22
23constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NModulesAlongStaveSB;
24
25constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NChipsPerModuleSB;
26constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NModulesPerStaveSB;
27constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NCablesPerStaveSB;
28
29constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NStavesSB;
30constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NChipsPerStaveSB;
31constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NChipsPerCableSB;
32constexpr std::array<int, ChipMappingITS::NSubB> ChipMappingITS::NChipsSB;
33constexpr std::array<int, ChipMappingITS::NLayers> ChipMappingITS::NStavesOnLr;
34constexpr std::array<int, ChipMappingITS::NLayers> ChipMappingITS::FirstStaveOnLr;
35
36constexpr std::array<uint8_t, ChipMappingITS::NLayers> ChipMappingITS::RUTypeLr;
37
38constexpr std::array<uint8_t, ChipMappingITS::NSubB> ChipMappingITS::GBTHeaderFlagSB;
39constexpr std::uint8_t ChipMappingITS::ChipOBModSW2HW[14];
40constexpr std::uint8_t ChipMappingITS::ChipOBModHW2SW[15];
41
43{
44 // FEE ID field in RDH is 16-bit wide
45 // Each RU has 10-bit DIPSWITCH, use bits 9:2 as an 8bit ID field to be mapped to FEE ID field in RDH
46
47 // | Lr |Stave Count| Bin. pref | Range of Binary Addresses
48 // | |= RU Count | Stave addr|
49 // |----------------------------------------------------------
50 // | L0 | 12 |b 0000xxxx | 0000_0000 : 0000_1011 (0 – 11)
51 // | L1 | 16 |b 0001xxxx | 0001_0000 : 0001_1111 (0 – 15)
52 // | L2 | 20 |b 001xxxxx | 001_00000 : 001_10011 (0 – 19)
53 // | L3 | 24 |b 010xxxxx | 010_00000 : 010_10111 (0 – 23)
54 // | L4 | 30 |b 011xxxxx | 011_00000 : 011_11101 (0 – 29)
55 // | L5 | 42 |b 10xxxxxx | 10_000000 : 10_101001 (0 – 41)
56 // | L6 | 48 |b 11xxxxxx | 11_000000 : 11_101111 (0 – 47)
57
58 // FEEId format:
59 // 15|14 12|11 10 |9 8|7 6|5 0|
60 // 0| Layer | Reserve | Fiber | 00 | StaveNumber |
61
62 // init chips info
63 uint32_t maxRUHW = composeFEEId(NLayers - 1, NStavesOnLr[NLayers - 1], NLinks - 1); // Max possible FEE ID
64 assert(maxRUHW < 0xffff);
65 mFEEId2RUSW.resize(maxRUHW + 1, 0xff);
66
67 // IB: single cable per chip
68 int ctrChip = 0;
69 mChipInfoEntrySB[IB] = ctrChip;
70 mCablePos[IB].resize(NChipsPerStaveSB[IB], 0xff);
71 mCableHW2SW[IB].resize(NChipsPerStaveSB[IB], 0xff);
72 mCableHW2Pos[IB].resize(NChipsPerStaveSB[IB], 0xff);
73 mCableHWFirstChip[IB].resize(NChipsPerStaveSB[IB], 0xff);
74 for (int i = 0; i < NChipsPerStaveSB[IB]; i++) {
75 auto& cInfo = mChipsInfo[ctrChip++];
76 cInfo.id = i;
77 cInfo.moduleHW = 0;
78 cInfo.moduleSW = 0;
79 cInfo.chipOnModuleSW = i;
80 cInfo.chipOnModuleHW = i;
81 cInfo.cableHW = i; //1-to-1 mapping
82 cInfo.cableHWPos = i; //1-to-1 mapping
83 cInfo.cableSW = i; //1-to-1 mapping
84 cInfo.chipOnCable = 0; // every chip is master
85 mCableHW2SW[IB][cInfo.cableHW] = cInfo.cableSW;
86 mCableHW2Pos[IB][cInfo.cableHW] = cInfo.cableHWPos;
87 mCablesOnStaveSB[IB] |= 0x1 << cInfo.cableHWPos; // account in lanes pattern
88 mCableHWFirstChip[IB][i] = 0; // stave and module are the same
89 }
90
91 // [i][j] gives lane id for lowest(i=0) and highest(i=1) 7 chips of HW module (j+1) (1-4 for ML, 1-7 for OL)
92 const int LANEID[2][7] = {{0, 1, 2, 3, 4, 5, 6}, {6, 5, 4, 3, 2, 1, 0}};
93 const int maxModulesPerStave = NModulesPerStaveSB[OB];
94 const int chipsOnCable = 7;
95 for (int bid = MB; bid <= OB; bid++) { // MB and OB staves have similar layout
96 mChipInfoEntrySB[bid] = ctrChip;
97 mCablePos[bid].resize(NChipsPerStaveSB[bid], 0xff);
98 mCableHW2SW[bid].resize(NChipsPerStaveSB[bid], 0xff);
99 mCableHW2Pos[bid].resize(NChipsPerStaveSB[bid], 0xff);
100 mCableHWFirstChip[bid].resize(NChipsPerStaveSB[bid], 0xff);
101 for (int i = 0; i < NChipsPerStaveSB[bid]; i++) {
102 auto& cInfo = mChipsInfo[ctrChip++];
103 int hstave = i / (NChipsPerStaveSB[bid] / 2);
104 cInfo.id = i;
105 cInfo.moduleSW = i / NChipsPerModuleSB[bid]; // SW module ID (within the stave)
106 cInfo.moduleHW = 1 + cInfo.moduleSW % (NModulesPerStaveSB[bid] / 2); // identification within the HS
107
108 cInfo.chipOnModuleSW = i % NChipsPerModuleSB[bid];
109 cInfo.chipOnModuleHW = ChipOBModSW2HW[cInfo.chipOnModuleSW];
110
111 bool lower7 = cInfo.chipOnModuleSW < (NChipsPerModuleSB[bid] / 2);
112
113 uint8_t connector = 2 * hstave + lower7, connectorInv = 2 * hstave + (!lower7);
114 cInfo.cableHW = (connector << 3) + LANEID[!lower7][cInfo.moduleHW - 1];
115 cInfo.cableSW = i / chipsOnCable;
116 cInfo.cableHWPos = LANEID[lower7][cInfo.moduleHW - 1] + connectorInv * maxModulesPerStave / 2;
117 mCablesOnStaveSB[bid] |= 0x1 << cInfo.cableHWPos; // account in lanes pattern
118 cInfo.chipOnCable = cInfo.chipOnModuleSW % (NChipsPerModuleSB[bid] / 2); // each cable serves half module
119 mCableHW2SW[bid][cInfo.cableHW] = cInfo.cableSW;
120 mCableHW2Pos[bid][cInfo.cableHW] = cInfo.cableHWPos;
121 if (cInfo.chipOnCable == 0) {
122 mCableHWFirstChip[bid][cInfo.cableHW] = cInfo.moduleSW * NChipsPerModuleSB[bid];
123 }
124 }
125 }
126 for (int bid = 0; bid < NSubB; bid++) {
127 int pos = 0;
128 for (int ic = 0; ic < 32; ic++) {
129 if (mCablesOnStaveSB[bid] & (0x1 << ic)) {
130 mCablePos[bid][pos++] = ic;
131 }
132 }
133 if (pos != NCablesPerStaveSB[bid]) {
134 throw std::runtime_error(fmt::format("counted number of cables {} does not match expected {} on subBarel{}", pos, NCablesPerStaveSB[bid], bid));
135 }
136 }
137
138 int ctrStv = 0;
139 uint16_t chipCount = 0;
140 for (int ilr = 0; ilr < NLayers; ilr++) {
141 for (int ist = 0; ist < NStavesOnLr[ilr]; ist++) {
142 auto& sInfo = mStavesInfo[ctrStv];
143 sInfo.idSW = ctrStv++;
144
145 // map FEEIds (RU read out by at most 3 GBT links) to SW ID
146 sInfo.idHW = composeFEEId(ilr, ist, 0); // FEEId for link 0
147 mFEEId2RUSW[sInfo.idHW] = sInfo.idSW;
148 for (int lnk = 1; lnk < NLinks; lnk++) {
149 mFEEId2RUSW[composeFEEId(ilr, ist, lnk)] = sInfo.idSW;
150 }
151 sInfo.layer = ilr;
152 sInfo.ruType = RUTypeLr[ilr];
153 sInfo.nCables = NCablesPerStaveSB[sInfo.ruType];
154 sInfo.firstChipIDSW = chipCount;
155 chipCount += NChipsPerStaveSB[sInfo.ruType];
156 }
157 }
158
159 // MB lookup
160 for (int ichw = 0; ichw <= MaxHWCableID[MB]; ichw++) { // loop over HW cables
161 for (int ihw = 0; ihw < 15; ihw++) { // init with invalid IDs
162 HWCableHWChip2ChipOnRU_MB[ichw][ihw] = 0xff;
163 }
164 }
165 for (int ichip = 0; ichip < NChipsPerStaveSB[MB]; ichip++) {
166 const auto& chInfo = mChipsInfo[NChipsPerStaveSB[IB] + ichip];
167 HWCableHWChip2ChipOnRU_MB[chInfo.cableHW][chInfo.chipOnModuleHW] = uint8_t(ichip);
168 }
169
170 // OB lookup
171 for (int ichw = 0; ichw <= MaxHWCableID[OB]; ichw++) { // loop over HW cables
172 for (int ihw = 0; ihw < 15; ihw++) { // init with invalid IDs
173 HWCableHWChip2ChipOnRU_OB[ichw][ihw] = 0xff;
174 }
175 }
176 for (int ichip = 0; ichip < NChipsPerStaveSB[OB]; ichip++) {
177 const auto& chInfo = mChipsInfo[NChipsPerStaveSB[IB] + NChipsPerStaveSB[MB] + ichip];
178 HWCableHWChip2ChipOnRU_OB[chInfo.cableHW][chInfo.chipOnModuleHW] = uint8_t(ichip);
179 }
180 assert(ctrStv == getNRUs());
181}
182
183//______________________________________________
185{
186 int ctrChip = 0;
187 const std::string bnames[3] = {"IB", "MB", "OB"};
188 const int lrpr[3] = {0, 3, 5};
189 for (int ib = 0; ib < NSubB; ib++) {
190 printf("\n\nSubBarrel %s\nCablesPattern %s\n", bnames[ib].c_str(), std::bitset<32>(mCablesOnStaveSB[ib]).to_string().c_str());
191 const auto ruInfo = getRUInfoSW(getFirstStavesOnLr(lrpr[ib]));
192 for (int i = 0; i < NChipsPerStaveSB[ib]; i++) {
193 printf("%s | %s\n", mChipsInfo[ctrChip++].asString().c_str(), getChipNameHW(i + ruInfo->firstChipIDSW).c_str());
194 }
195 }
196}
197
198//______________________________________________
199void ChipMappingITS::expandChipInfoSW(int idSW, int& lay, int& sta, int& ssta, int& mod, int& chipInMod) const
200{
201 // convert SW chip ID to detailed info SW info
202 ChipInfo chi;
203 getChipInfoSW(idSW, chi);
204 const auto staveInfo = getRUInfoSW(chi.ru);
205 lay = staveInfo->layer;
206 sta = staveInfo->idSW;
207 mod = chi.chOnRU->moduleSW;
208 chipInMod = chi.chOnRU->chipOnModuleSW;
209 ssta = lay < 3 || (mod < NModulesAlongStaveSB[chi.ruType]) ? 0 : 1;
210}
211
212//______________________________________________
213void ChipMappingITS::expandChipInfoHW(int idSW, int& lay, int& sta, int& ssta, int& mod, int& chipInMod) const
214{
215 // convert SW chip ID to detailed info HW info
216 ChipInfo chi;
217 getChipInfoSW(idSW, chi);
218 const auto staveInfo = getRUInfoSW(chi.ru);
219 lay = staveInfo->layer;
220 sta = staveInfo->idSW - getFirstStavesOnLr(lay); // stave relative to layer
221 mod = lay < 3 ? 0 : 1 + (chi.chOnRU->moduleSW % NModulesAlongStaveSB[chi.ruType]); // module on the substave
222 ssta = chi.chOnRU->moduleSW / NModulesAlongStaveSB[chi.ruType];
223 chipInMod = chi.chOnRU->chipOnModuleHW;
224}
225
226//______________________________________________
227std::string ChipMappingITS::getChipNameHW(int idSW) const
228{
229 // convert global SW chip ID to name in HW conventions
230 int lay, sta, ssta, mod, cinmod;
231 expandChipInfoHW(idSW, lay, sta, ssta, mod, cinmod);
232 std::stringstream strs;
233 strs << 'L' << lay << '_' << std::setfill('0') << std::setw(2) << sta;
234 if (lay > 2) {
235 strs << (ssta ? 'U' : 'L') << "_M" << mod;
236 }
237 strs << "_C" << std::setfill('0') << std::setw(2) << cinmod;
238
239 return strs.str();
240}
241
243void ChipMappingITS::imposeFEEId2RUSW(uint16_t feeID, uint16_t ruSW)
244{
245 // test if it is legitimate
246 uint16_t lr, ruOnLr, link;
247 expandFEEId(feeID, lr, ruOnLr, link);
248 if (lr >= NLayers || ruOnLr >= NStavesOnLr[lr] || link >= NLinks) {
249 LOG(fatal) << "Invalid FEE#0x" << std::hex << feeID << std::dec << ": corresponds to Lr#" << lr
250 << " StaveOnLr#" << ruOnLr << " GBTLinkOnRU#" << link;
251 }
252 if (ruSW >= getNRUs()) {
253 LOG(fatal) << "Invalid SW RUid " << ruSW << " (cannot exceed " << getNRUs() << ")";
254 }
255 mFEEId2RUSW[feeID] = ruSW;
256}
257
258std::vector<ChipMappingITS::Overlaps> ChipMappingITS::getOverlapsInfo() const
259{
260 std::vector<ChipMappingITS::Overlaps> v(getNChips());
261 for (int id = 0; id < getNChips(); id++) {
262 auto& vval = v[id];
263 int lay, sta, ssta, mod, chip;
264 expandChipInfoSW(id, lay, sta, ssta, mod, chip);
265 int ruTp = getRUType(sta);
266 if (ruTp == IB) {
267 int chOnLr = id - getFirstChipsOnLayer(lay), chPerSStave = getNChipsOnRUType(ruTp);
268 vval.rowSide[ChipMappingITS::Overlaps::LowRow] = getFirstChipsOnLayer(lay) + (chOnLr - chPerSStave + getNChipsOnLayer(lay)) % getNChipsOnLayer(lay); // chips overlapping from rowMin side with other chips high row side
269 vval.rowSide[ChipMappingITS::Overlaps::HighRow] = getFirstChipsOnLayer(lay) + (chOnLr + chPerSStave + getNChipsOnLayer(lay)) % getNChipsOnLayer(lay); // chips overlapping from rowMax side with other chips low row side
272 } else {
273 int staOv = sta, modOv = mod;
274 auto NChipsModule = NChipsPerModuleSB[ruTp];
275 if (ssta == 0) {
276 modOv += getNModulesPerStave(ruTp) / 2;
277 if (chip >= NChipsModule / 2) { // overlap is possible only with ssta=1 of previous stave, otherwise only with ssta=1 of the same stave; only from high row side with other chips high row side
278 staOv = getFirstStavesOnLr(lay) + (sta - getFirstStavesOnLr(lay) - 1 + getNStavesOnLr(lay)) % getNStavesOnLr(lay); // stave below
279 }
280 } else {
281 modOv -= getNModulesPerStave(ruTp) / 2;
282 if (chip < NChipsModule / 2) { // overlap is possible only with ssta=0 of the next stave, otherwise only with ssta=0 of the same stave and only from high row side with other chips high row side
283 staOv = getFirstStavesOnLr(lay) + (sta - getFirstStavesOnLr(lay) + 1 + getNStavesOnLr(lay)) % getNStavesOnLr(lay); // stave above
284 }
285 }
286 vval.rowSide[ChipMappingITS::Overlaps::HighRow] = getGlobalChipIDSW(lay, staOv, modOv, NChipsModule - 1 - chip);
288 }
289 }
290 return v;
291}
std::string asString(TDataMember const &dm, char *pointer)
int32_t i
uint16_t pos
Definition RawData.h:3
void expandChipInfoSW(int idSW, int &lay, int &sta, int &ssta, int &mod, int &chipInMod) const
expand SW chip ID to HW id's for layer, stave, substave, module, chipOnModule
uint16_t getGlobalChipIDSW(int lay, int staSW, int modSW, int chipInModSW) const
get SW id of the RU from RU HW id
static constexpr int MB
int getNChipsOnRUType(int ruType) const
get RU type from the sequential ID of the RU
static constexpr int IB
static constexpr int getNChips()
number of chips per barrel
static constexpr int getFirstStavesOnLr(int l)
numbes of chips per layer
static constexpr int getNModulesPerStave(int ruType)
static constexpr int NSubB
std::vector< Overlaps > getOverlapsInfo() const
static constexpr int getNChipsOnLayer(int lr)
static constexpr int getNRUs()
total number of chips
void expandChipInfoHW(int idSW, int &lay, int &sta, int &ssta, int &mod, int &chipInMod) const
convert global SW chip ID to name in HW conventions
static constexpr int OB
int getRUType(int ruID) const
convert HW id of chip in the module to SW ID (sequential ID on the module)
void expandFEEId(uint16_t feeID, uint16_t &lr, uint16_t &ruOnLr, uint16_t &link) const
impose user defined FEEId -> ruSW (staveID) conversion, to be used only for forced decoding of corrup...
void getChipInfoSW(int chipSW, ChipInfo &chInfo) const
get chipID on module from chip global SW ID, cable SW ID and stave (RU) info
static constexpr int NLinks
uint16_t composeFEEId(uint16_t lr, uint16_t ruOnLr, uint16_t link) const
decompose FEEid to layer, stave (ru) relative to layer, link, see documentation in the constructor
static constexpr int NLayers
std::string getChipNameHW(int idSW) const
impose user defined FEEId -> ruSW (staveID) conversion, to be used only for forced decoding of corrup...
void imposeFEEId2RUSW(uint16_t feeID, uint16_t ruSW)
modify linkID field in FEEId
const RUInfo * getRUInfoSW(int ruSW) const
get info on sw RU
static constexpr int getNStavesOnLr(int l)
first staves of layer
static constexpr int getFirstChipsOnLayer(int lr)
const GLdouble * v
Definition glcorearb.h:832
GLuint id
Definition glcorearb.h:650
const ChipOnRUInfo * chOnRU
Definition RUInfo.h:59
std::uint16_t ru
Definition RUInfo.h:63
std::uint16_t ruType
Definition RUInfo.h:64
std::uint8_t moduleSW
Definition RUInfo.h:43
std::uint8_t chipOnModuleHW
Definition RUInfo.h:46
std::uint8_t chipOnModuleSW
Definition RUInfo.h:45
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"