5G-LENA nr-v3.3-120-gdac69c56
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-mac-scheduler-cqi-management.cc
1// Copyright (c) 2019 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#define NS_LOG_APPEND_CONTEXT \
6 if (m_getCellId) \
7 { \
8 std::clog << " [ CellId " << GetCellId() << ", bwpId " << GetBwpId() << "] "; \
9 }
10#include "nr-mac-scheduler-cqi-management.h"
11
12#include "nr-amc.h"
13
14#include "ns3/log.h"
15#include "ns3/nr-spectrum-value-helper.h"
16
17namespace ns3
18{
19
20NS_LOG_COMPONENT_DEFINE("NrMacSchedulerCQIManagement");
21
22void
24 uint32_t expirationTime,
25 [[maybe_unused]] uint32_t tbs,
27 const std::shared_ptr<NrMacSchedulerUeInfo>& ueInfo,
28 const std::vector<bool>& rbgMask,
29 uint32_t numRbPerRbg,
30 const Ptr<const SpectrumModel>& model) const
31{
32 NS_LOG_FUNCTION(this);
33 NS_ASSERT(!rbgMask.empty());
34
35 NS_LOG_INFO("Computing SB CQI for UE " << ueInfo->m_rnti);
36
37 ueInfo->m_ulCqi.m_sinr = params.m_ulCqi.m_sinr;
38 ueInfo->m_ulCqi.m_cqiType = NrMacSchedulerUeInfo::CqiInfo::SB;
39 ueInfo->m_ulCqi.m_timer = expirationTime;
40
41 std::vector<int> rbAssignment(params.m_ulCqi.m_sinr.size(), 0);
42
43 for (uint32_t i = 0; i < rbgMask.size(); ++i)
44 {
45 if (rbgMask.at(i) == 1)
46 {
47 for (uint32_t k = 0; k < numRbPerRbg; ++k)
48 {
49 rbAssignment[i * numRbPerRbg + k] = 1;
50 }
51 }
52 }
53
54 SpectrumValue specVals(model);
55 Values::iterator specIt = specVals.ValuesBegin();
56
57 std::stringstream out;
58
59 for (uint32_t ichunk = 0; ichunk < model->GetNumBands(); ichunk++)
60 {
61 NS_ASSERT(specIt != specVals.ValuesEnd());
62 if (rbAssignment[ichunk] == 1)
63 {
64 *specIt = ueInfo->m_ulCqi.m_sinr.at(ichunk);
65 out << ueInfo->m_ulCqi.m_sinr.at(ichunk) << " ";
66 }
67 else
68 {
69 out << "0.0 ";
70 *specIt = 0.0;
71 }
72
73 specIt++;
74 }
75
76 NS_LOG_INFO("Values of SINR to pass to the AMC: " << out.str());
77
78 // MCS updated inside the function; crappy API... but we can't fix everything
79 ueInfo->m_ulCqi.m_wbCqi = GetAmcUl()->CreateCqiFeedbackWbTdma(specVals, ueInfo->m_ulMcs);
80 NS_LOG_DEBUG("Calculated MCS for RNTI " << ueInfo->m_rnti << " is " << ueInfo->m_ulMcs);
81}
82
83void
84NrMacSchedulerCQIManagement::InstallGetBwpIdFn(const std::function<uint16_t()>& fn)
85{
86 NS_LOG_FUNCTION(this);
87 m_getBwpId = fn;
88}
89
90void
91NrMacSchedulerCQIManagement::InstallGetCellIdFn(const std::function<uint16_t()>& fn)
92{
93 NS_LOG_FUNCTION(this);
94 m_getCellId = fn;
95}
96
97void
98NrMacSchedulerCQIManagement::InstallGetStartMcsDlFn(const std::function<uint8_t()>& fn)
99{
100 NS_LOG_FUNCTION(this);
101 m_getStartMcsDl = fn;
102}
103
104void
105NrMacSchedulerCQIManagement::InstallGetStartMcsUlFn(const std::function<uint8_t()>& fn)
106{
107 NS_LOG_FUNCTION(this);
108 m_getStartMcsUl = fn;
109}
110
111void
112NrMacSchedulerCQIManagement::InstallGetNrAmcDlFn(const std::function<Ptr<const NrAmc>()>& fn)
113{
114 NS_LOG_FUNCTION(this);
115 m_getAmcDl = fn;
116}
117
118void
119NrMacSchedulerCQIManagement::InstallGetNrAmcUlFn(const std::function<Ptr<const NrAmc>()>& fn)
120{
121 NS_LOG_FUNCTION(this);
122 m_getAmcUl = fn;
123}
124
125void
127 const std::shared_ptr<NrMacSchedulerUeInfo>& ueInfo,
128 uint32_t expirationTime,
129 int8_t maxDlMcs,
130 uint16_t bandwidthInRbgs) const
131{
132 NS_LOG_FUNCTION(this);
133
134 ueInfo->m_dlCqi.m_timer = expirationTime;
135 ueInfo->m_dlCqi.m_cqiType = NrMacSchedulerUeInfo::CqiInfo::WB;
136 ueInfo->m_dlCqi.m_wbCqi = info.m_wbCqi;
137 ueInfo->m_dlMcs =
138 std::min(static_cast<uint8_t>(GetAmcDl()->GetMcsFromCqi(ueInfo->m_dlCqi.m_wbCqi)),
139 static_cast<uint8_t>(maxDlMcs));
140
141 ueInfo->m_dlCqi.m_sbCqi = info.m_sbCqis;
142 ueInfo->m_dlSbMcsInfo.clear();
143 if (!info.m_sbCqis.empty())
144 {
145 // Map sub-band CQI to MCS per RBG
146 ueInfo->m_dlSbMcsInfo.resize(info.m_sbCqis.size());
147 ueInfo->m_rbgToSb.resize(bandwidthInRbgs);
148
149 // Determine sub-band size
150 size_t rbgsPerSb = 1;
151 while (static_cast<std::size_t>(bandwidthInRbgs / rbgsPerSb) >
152 ueInfo->m_dlCqi.m_sbCqi.size())
153 {
154 rbgsPerSb <<= 1;
155 }
156
157 // Precompute MCS, spectral efficiency and SINR, which can be used later to determine which
158 // MCS we should use for a given set of allocated RBGs
159 size_t sb = 0;
160 for (auto sbCqi : ueInfo->m_dlCqi.m_sbCqi)
161 {
162 auto mcs = m_getAmcDl()->GetMcsFromCqi(sbCqi);
163 auto specEff = m_getAmcDl()->GetSpectralEfficiencyForCqi(sbCqi);
164 auto sinr = m_getAmcDl()->GetSinrFromSpectralEfficiency(specEff);
165
166 // Divide estimated SINR by the rank number, to get the equivalent at rank 1
167 sinr /= info.m_ri;
168
169 // We don't need double precision for this
170 ueInfo->m_dlSbMcsInfo[sb] = {sbCqi, mcs, (float)specEff, (float)sinr};
171
172 for (auto rbg = sb * rbgsPerSb;
173 rbg < std::min<size_t>(bandwidthInRbgs, (sb + 1) * rbgsPerSb);
174 rbg++)
175 {
176 ueInfo->m_rbgToSb[rbg] = sb;
177 }
178 sb++;
179 }
180 }
181
182 NS_LOG_INFO("Calculated MCS for UE " << ueInfo->m_rnti << " is "
183 << static_cast<uint32_t>(ueInfo->m_dlMcs));
184
185 NS_LOG_INFO("Updated WB CQI of UE "
186 << ueInfo->m_rnti << " to " << static_cast<uint32_t>(ueInfo->m_dlCqi.m_wbCqi)
187 << ". It will expire in " << ueInfo->m_dlCqi.m_timer << " slots.");
188
189 if (info.m_optPrecMat)
190 {
191 // Set the number of layers (rank) directly to m_ri (do not decode m_ri)
192 NS_ASSERT(info.m_ri > 0);
193 ueInfo->m_dlRank = info.m_ri;
194
195 // Set the precoding matrix
196 ueInfo->m_dlPrecMats = info.m_optPrecMat;
197 }
198}
199
200void
202 const std::unordered_map<uint16_t, std::shared_ptr<NrMacSchedulerUeInfo>>& ueMap) const
203{
204 NS_LOG_FUNCTION(this);
205
206 for (const auto& itUe : ueMap)
207 {
208 const std::shared_ptr<NrMacSchedulerUeInfo>& ue = itUe.second;
209
210 if (ue->m_dlCqi.m_timer == 0)
211 {
212 ue->m_dlCqi.m_wbCqi = 1; // lowest value for trying a transmission
213 ue->m_dlCqi.m_cqiType = NrMacSchedulerUeInfo::CqiInfo::WB;
214 ue->m_dlMcs = GetStartMcsDl();
215 }
216 else
217 {
218 ue->m_dlCqi.m_timer -= 1;
219 }
220 }
221}
222
223void
225 const std::unordered_map<uint16_t, std::shared_ptr<NrMacSchedulerUeInfo>>& ueMap) const
226{
227 NS_LOG_FUNCTION(this);
228
229 for (const auto& itUe : ueMap)
230 {
231 const std::shared_ptr<NrMacSchedulerUeInfo>& ue = itUe.second;
232
233 if (ue->m_ulCqi.m_timer == 0)
234 {
235 ue->m_ulCqi.m_wbCqi = 1; // lowest value for trying a transmission
236 ue->m_ulCqi.m_cqiType = NrMacSchedulerUeInfo::CqiInfo::WB;
237 ue->m_ulMcs = GetStartMcsUl();
238 }
239 else
240 {
241 ue->m_ulCqi.m_timer -= 1;
242 }
243 }
244}
245
246uint16_t
247NrMacSchedulerCQIManagement::GetBwpId() const
248{
249 return m_getBwpId();
250}
251
252uint16_t
253NrMacSchedulerCQIManagement::GetCellId() const
254{
255 return m_getCellId();
256}
257
258uint8_t
259NrMacSchedulerCQIManagement::GetStartMcsDl() const
260{
261 return m_getStartMcsDl();
262}
263
264uint8_t
265NrMacSchedulerCQIManagement::GetStartMcsUl() const
266{
267 return m_getStartMcsUl();
268}
269
270Ptr<const NrAmc>
271NrMacSchedulerCQIManagement::GetAmcDl() const
272{
273 return m_getAmcDl();
274}
275
276Ptr<const NrAmc>
277NrMacSchedulerCQIManagement::GetAmcUl() const
278{
279 return m_getAmcUl();
280}
281
282} // namespace ns3
void RefreshUlCqiMaps(const std::unordered_map< uint16_t, std::shared_ptr< NrMacSchedulerUeInfo > > &m_ueMap) const
Refresh the UL CQI for all the UE.
void InstallGetCellIdFn(const std::function< uint16_t()> &fn)
Install a function to retrieve the cell id.
void RefreshDlCqiMaps(const std::unordered_map< uint16_t, std::shared_ptr< NrMacSchedulerUeInfo > > &m_ueMap) const
Refresh the DL CQI for all the UE.
void InstallGetBwpIdFn(const std::function< uint16_t()> &fn)
Install a function to retrieve the bwp id.
void UlSBCQIReported(uint32_t expirationTime, uint32_t tbs, const NrMacSchedSapProvider::SchedUlCqiInfoReqParameters &params, const std::shared_ptr< NrMacSchedulerUeInfo > &ueInfo, const std::vector< bool > &rbgMask, uint32_t numRbPerRbg, const Ptr< const SpectrumModel > &model) const
An UL SB CQI has been reported for the specified UE.
void DlCqiReported(const DlCqiInfo &info, const std::shared_ptr< NrMacSchedulerUeInfo > &ueInfo, uint32_t expirationTime, int8_t maxDlMcs, uint16_t bandwidthInRbgs) const
A wideband CQI has been reported for the specified UE.
The DlCqiInfo struct.
Ptr< const ComplexMatrixArray > m_optPrecMat
Precoding matrix for each RB.
uint8_t m_wbCqi
Wideband CQI.
std::vector< uint8_t > m_sbCqis
Subband CQI values.
uint8_t m_ri
the rank indicator, or simply the rank number
enum ns3::NrMacSchedulerUeInfo::CqiInfo::CqiType WB
CQI type.