CbmRoot
Loading...
Searching...
No Matches
sts/ReadoutConfig.cxx
Go to the documentation of this file.
1/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer], Felix Weiglhofer */
4#include "ReadoutConfig.h"
5
7#include "CbmStsAddress.h"
8#include "ChannelMaskSet.h"
9#include "Exceptions.h"
10
11#include <cassert>
12#include <iomanip>
13
14using std::pair;
15using std::setw;
16
17using namespace cbm::algo;
18
20
22{
23 size_t febsPerCrob = FEBsPerCrob();
24 switch (febsPerCrob) {
25 case 5: return FEBType::FEB8_1;
26 case 1: return FEBType::FEB8_5;
27 }
28 throw FatalError("Invalid number of FEBs per CROB: {}", febsPerCrob);
29}
30
31const std::vector<sts::ReadoutSetup::Elink>& sts::ReadoutSetup::GetElinks(FEBType type) const
32{
33 switch (type) {
34 case FEBType::FEB8_1: return elinksFeb8_1;
35 case FEBType::FEB8_5: return elinksFeb8_5;
36 }
37 throw FatalError("Unknown FEB type: {}", static_cast<int>(type));
38}
39
41{
42 Init(config, chanMaskSet);
43}
44
46{
47 std::vector<uint16_t> result;
48 for (auto& entry : fReadoutConfig)
49 result.push_back(entry.first);
50 return result;
51}
52
54{
55 size_t result = 0;
56 auto it = fReadoutConfig.find(equipmentId);
57 if (it != fReadoutConfig.end()) result = fReadoutConfig[equipmentId].size();
58 return result;
59}
60
62{
63 size_t result = 0;
64 for (auto& entry : fReadoutConfig) {
65 result += entry.second.size();
66 }
67 return result;
68}
69
70void sts::ReadoutConfig::Init(const ReadoutSetup& config, const ChannelMaskSet& chanMaskSet)
71{
72 // The readout hierarchy is: component - CROB - FEB - ASIC (elink). Each elink
73 // connects one ASIC. One FEB comprises 8 ASICs and reads out one side of a module (sensor).
74 // In this setup, there is only one CROB per component. The code below is formulate such
75 // as to support also multiple CROBs per component. In that case, the elinks are numbered
76 // consecutively within one component.
77
78 // Constants
79 const uint16_t numModules = config.modules.size(); // Number of modules in the setup
80 const uint16_t numComp = config.components.size(); // Number of components
81 const uint16_t numCrobPerComp = config.components.at(0).feb2module.size(); // Number of CROBs per component
82 // const uint16_t numFebsPerCrob = config.components.at(0).feb2module.at(0).size(); // Number of FEBs per CROB
83 const uint16_t numAsicsPerFeb = config.numAsicsPerFeb; // Number of ASICs per FEB
84 const uint16_t numAsicsPerMod = 2 * numAsicsPerFeb; // Number of ASICs per module
85 const uint16_t numElinksPerCrob = 42; // Number of elinks per CROB
86 const uint16_t numChanPerAsic = 128;
87 const uint16_t numElinksPerComp = numCrobPerComp * numElinksPerCrob;
88
89 // Constructing the map (equipmentId, eLink) -> (module, ASIC within module)
90 int32_t febBaseIdx = 0;
91 for (uint16_t compIdx = 0; compIdx < numComp; compIdx++) {
92 const auto& component = config.components.at(compIdx);
93 uint16_t equipment = component.equipmentId;
94 fReadoutConfig[equipment].resize(numElinksPerComp);
95 const int32_t numFebsPerCrob = component.FEBsPerCrob();
96 for (uint16_t crobIdx = 0; crobIdx < numCrobPerComp; crobIdx++) {
97 for (uint16_t elinkIdx = 0; elinkIdx < numElinksPerCrob; elinkIdx++) {
98
99 int32_t moduleAddress = -1;
100 uint16_t asicInModule = 0;
101 bool isPulser = false;
102
103 uint16_t elinkId = numElinksPerCrob * crobIdx + elinkIdx; // elink within component
104 const auto& elinks = config.GetElinks(component.GetFEBType());
105 const auto& elink = elinks.at(elinkId);
106
107 int16_t feb = elink.toFeb; // FEB within CROB
108
109 if (feb == -1) {
110 continue;
111 }
112
113 int16_t moduleIdx = component.feb2module[crobIdx][feb]; // Module index
114
115 if (moduleIdx == -1) {
116 continue;
117 }
118
119 isPulser = component.febIsPulser.at(crobIdx).at(feb); // Pulser flag
120
121 assert(moduleIdx < numModules);
122 const auto& module = config.modules.at(moduleIdx);
123 moduleAddress = module.address; // Module address
124 bool moduleType = module.type; // 0 or 1
125 int16_t moduleSide = component.feb2moduleSide[crobIdx][feb]; // 0 or 1, -1 is inactive
126 int16_t febType = (moduleType == 0 ? moduleSide : !moduleSide); // 0 = FEB A, 1 = FEB B
127 uint32_t asicIndex = (febType == 0 ? elink.toAsicFebA : elink.toAsicFebB);
128 uint32_t asicInFeb = asicIndex % numAsicsPerFeb; // ASIC number within FEB
129 // Asic number is counted downward from numAsicsPerMod - 1 for p side
130 asicInModule = (moduleSide == 1 ? asicInFeb : numAsicsPerMod - 1 - asicInFeb);
131
132 // Init channel mask
133 const int32_t febId = feb + febBaseIdx;
134 auto mapIt = chanMaskSet.values.find(febId);
135 if (mapIt != chanMaskSet.values.end()) {
136 const auto& mask = mapIt->second;
137
138 for (uint32_t chan = 0; chan < numChanPerAsic; chan++) {
139 const uint32_t chanInFeb = chan + numChanPerAsic * asicInFeb;
140 if (mask.Contains(chanInFeb)) {
141 std::vector<bool>& chanMask = fMaskMap[equipment][elinkIdx];
142 if (chanMask.empty()) {
143 chanMask.resize(numChanPerAsic, false);
144 }
145 chanMask[chan] = true;
146 }
147 }
148 }
149
150 fReadoutConfig[equipment][elinkIdx] = {moduleAddress, asicInModule, isPulser};
151
152 } //# elink
153 } //# CROB
154 febBaseIdx += numCrobPerComp * numFebsPerCrob; // Add the proper offset for the current CROB
155 } //# component
156}
157
158sts::ReadoutConfig::Entry sts::ReadoutConfig::Map(uint16_t equipmentId, uint16_t elinkId)
159{
160 Entry result{-1, 0, false};
161 auto equipIter = fReadoutConfig.find(equipmentId);
162 if (equipIter != fReadoutConfig.end()) {
163 if (elinkId < equipIter->second.size()) {
164 result = equipIter->second.at(elinkId);
165 }
166 }
167 return result;
168}
169
170std::vector<bool> sts::ReadoutConfig::MaskMap(uint16_t equipmentId, uint16_t elinkId)
171{
172 std::vector<bool> result;
173 auto equipIter = fMaskMap.find(equipmentId);
174 if (equipIter != fMaskMap.end()) {
175 auto elinkMap = equipIter->second;
176 auto elinkIter = elinkMap.find(elinkId);
177 if (elinkIter != elinkMap.end()) {
178 result = elinkIter->second;
179 }
180 }
181 return result;
182}
183
184uint32_t sts::ReadoutConfig::AdcCutMap(uint16_t equipmentId, uint16_t elinkId)
185{
186 uint32_t result = 0;
187 auto equipIter = fAdcCutMap.find(equipmentId);
188 if (equipIter != fAdcCutMap.end()) {
189 auto elinkMap = equipIter->second;
190 auto elinkIter = elinkMap.find(elinkId);
191 if (elinkIter != elinkMap.end()) {
192 result = elinkIter->second;
193 }
194 }
195 return result;
196}
197
199{
200
201 std::stringstream ss;
202 for (auto& equipment : fReadoutConfig) {
203 auto eqId = equipment.first;
204 for (size_t elink = 0; elink < equipment.second.size(); elink++) {
205 auto address = equipment.second.at(elink).moduleAddress;
206 auto asicNr = equipment.second.at(elink).asicNumber;
207 ss << "\n Equipment " << eqId << " elink " << setw(2) << elink;
208 ss << " ASIC " << setw(2) << asicNr << " module " << address;
209 if (address != -1) {
210 ss << " Unit " << setw(2) << CbmStsAddress::GetElementId(address, kStsUnit);
211 ss << " Ladd " << setw(2) << CbmStsAddress::GetElementId(address, kStsLadder);
212 ss << " Hlad " << setw(2) << CbmStsAddress::GetElementId(address, kStsHalfLadder);
213 ss << " Modu " << setw(2) << CbmStsAddress::GetElementId(address, kStsModule);
214 }
215 else
216 ss << " Inactive";
217 } //# elink
218 } //# component
219 return ss.str();
220}
@ kStsModule
@ kStsLadder
@ kStsHalfLadder
@ kStsUnit
#define CBM_YAML_INSTANTIATE(type)
Explicitly instantiate the Read and Dump functions for a type.
Definition Yaml.h:305
void Init(const ReadoutSetup &, const ChannelMaskSet &)
Initialisation of readout map.
std::string PrintReadoutMap()
Debug output of readout map.
ReadoutConfig()=default
Empty mapping.
std::vector< bool > MaskMap(uint16_t equipId, uint16_t elink)
API: Mapping from component and elink to channel mask flags.
Entry Map(u16 equipId, u16 elink)
API: Mapping from component and elink to address / ASIC number + pulser flag.
std::vector< u16 > GetEquipmentIds()
Equipment in the configuration.
size_t GetNumElinks()
Total number of elinks for STS.
uint32_t AdcCutMap(uint16_t equipId, uint16_t elink)
API: Mapping from component and elink to minimum adc cut.
uint32_t GetElementId(int32_t address, int32_t level)
Get the index of an element.
std::uint16_t u16
Definition Definitions.h:19
Indicates an unrecoverable error. Should tear down the process.
Definition Exceptions.h:34
std::map< size_t, MaskedChannels > values
Readout setup / Hardware cabling for STS Used to create the hardware mapping for the STS unpacker.
std::vector< Module > modules
const std::vector< Elink > & GetElinks(FEBType type) const
std::vector< Elink > elinksFeb8_5
std::vector< Elink > elinksFeb8_1
std::vector< Component > components