6#include "nr-eesm-error-model.h"
9#include "nr-phy-mac-common.h"
20NS_LOG_COMPONENT_DEFINE(
"NrEesmErrorModel");
21NS_OBJECT_ENSURE_REGISTERED(NrEesmErrorModel);
26static const std::vector<uint16_t> LiftingSizeTableBG = {
27 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20,
28 22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 88,
29 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384};
31std::vector<std::string> NrEesmErrorModel::m_bgTypeName = {
"BG1",
"BG2"};
36 NS_LOG_FUNCTION(
this);
41 NS_LOG_FUNCTION(
this);
47 static TypeId tid = TypeId(
"ns3::NrEesmErrorModel").SetParent<
NrErrorModel>();
53 const std::vector<int>& map,
62 double sinrExpSum =
SinrExp(sinr, map, mcs);
64 double SINR = -beta * log((a + sinrExpSum) / b);
65 SINR = std::max(SINR, 0.0);
67 NS_LOG_INFO(
" Effective SINR = " << SINR);
76 NS_LOG_FUNCTION(sinr << &map << (uint8_t)mcs);
77 NS_ABORT_MSG_IF(map.empty(),
78 " Error: number of allocated RBs cannot be 0 - EESM method - SinrEff function");
85 double sinrLin = sinr[i];
86 SINRexp = exp21d(-sinrLin / beta);
92const std::vector<double>&
93NrEesmErrorModel::GetSinrDbVectorFromSimulatedValues(NrEesmErrorModel::GraphType graphType,
95 uint32_t cbSizeIndex)
const
100const std::vector<double>&
101NrEesmErrorModel::GetBLERVectorFromSimulatedValues(NrEesmErrorModel::GraphType graphType,
103 uint32_t cbSizeIndex)
const
109NrEesmErrorModel::MappingSinrBler(
double sinr, uint8_t mcs, uint32_t cbSizeBit)
111 NS_LOG_FUNCTION(sinr << (uint8_t)mcs << (uint32_t)cbSizeBit);
113 "MCS out of range [0..27/28]: " <<
static_cast<uint8_t
>(mcs));
119 double sinr_db = 10 * log10(sinr);
120 GraphType bg_type = GetBaseGraphType(cbSizeBit, mcs);
123 NS_LOG_INFO(
"For sinr " << sinr <<
" and mcs " << +mcs <<
" CbSizebit " << cbSizeBit
124 <<
" we got bg type " << m_bgTypeName[bg_type]);
126 auto cbIt = cbMap.upper_bound(cbSizeBit);
128 if (cbIt != cbMap.begin())
133 if (sinr_db < GetSinrDbVectorFromSimulatedValues(bg_type, mcs, cbIt->first).front())
137 else if (sinr_db > GetSinrDbVectorFromSimulatedValues(bg_type, mcs, cbIt->first).back())
145 std::upper_bound(GetSinrDbVectorFromSimulatedValues(bg_type, mcs, cbIt->first).begin(),
146 GetSinrDbVectorFromSimulatedValues(bg_type, mcs, cbIt->first).end(),
149 if (sinrIt != GetSinrDbVectorFromSimulatedValues(bg_type, mcs, cbIt->first).begin())
155 std::distance(GetSinrDbVectorFromSimulatedValues(bg_type, mcs, cbIt->first).begin(),
157 bler = GetBLERVectorFromSimulatedValues(bg_type, mcs, cbIt->first).at(sinr_index);
160 NS_LOG_LOGIC(
"SINR effective: " << sinr <<
" BLER:" << bler);
164NrEesmErrorModel::GraphType
165NrEesmErrorModel::GetBaseGraphType(uint32_t tbSizeBit, uint8_t mcs)
const
169 GraphType bg_type = FIRST;
170 if (tbSizeBit <= 292 || ecr <= 0.25 || (tbSizeBit <= 3824 && ecr <= 0.67))
177std::pair<uint32_t, uint32_t>
178NrEesmErrorModel::CodeBlockSegmentation(uint32_t B, GraphType bg_type)
const
182 if (bg_type == FIRST)
189 NS_ASSERT(bg_type == SECOND);
223 C = ceil((
double)B / ((
double)(Kcb - L)));
228 uint32_t K1 = B1 / C;
232 auto ZcIt = std::upper_bound(LiftingSizeTableBG.begin(),
233 --LiftingSizeTableBG.end(),
234 (
static_cast<double>(K1) / Kb) + 0.001);
238 if (bg_type == FIRST)
244 NS_ASSERT(bg_type == SECOND);
248 NS_LOG_INFO(
"EESMErrorModel: TBS of " << B <<
" needs of " << B1 <<
" bits distributed in " << C
249 <<
" CBs of " << K <<
" bits");
250 return std::make_pair(K, C);
253Ptr<NrErrorModelOutput>
255 const std::vector<int>& map,
260 return GetTbBitDecodificationStats(sinr, map, size * 8, mcs, sinrHistory);
266 std::stringstream ss;
268 for (
const auto& v : map)
276Ptr<NrErrorModelOutput>
277NrEesmErrorModel::GetTbBitDecodificationStats(
const SpectrumValue& sinr,
278 const std::vector<int>& map,
281 const NrErrorModelHistory& sinrHistory)
283 NS_LOG_FUNCTION(
this);
286 double tbSinr =
SinrEff(sinr, map, mcs, 0, map.size());
287 double SINR = tbSinr;
288 double sinrExpSum =
SinrExp(sinr, map, mcs);
290 NS_LOG_DEBUG(
" mcs " << +mcs <<
" TBSize in bit " << sizeBit <<
" history elements: "
291 << sinrHistory.size() <<
" SINR of the tx: " << tbSinr << std::endl
292 <<
"MAP: " <<
PrintMap(map) << std::endl
293 <<
"SINR: " << sinr);
295 if (!sinrHistory.empty())
297 SINR =
ComputeSINR(sinr, map, mcs, sizeBit, sinrHistory);
300 NS_LOG_DEBUG(
" SINR after processing all retx (if any): " << SINR <<
" SINR last tx" << tbSinr);
303 GraphType bg_type = GetBaseGraphType(sizeBit, mcs);
304 NS_LOG_INFO(
"BG type selection: " << bg_type);
307 uint32_t B = sizeBit + 24;
308 std::pair<uint32_t, uint32_t> cbSeg = CodeBlockSegmentation(B, bg_type);
309 uint32_t K = cbSeg.first;
310 uint32_t C = cbSeg.second;
311 NS_LOG_INFO(
"EESMErrorModel: TBS of " << B <<
" bits distributed in " << C <<
" CBs of " << K
314 uint8_t mcs_eq = mcs;
315 if ((!sinrHistory.empty()) && (mcs > 0))
320 NS_LOG_INFO(
" MCS of tx " << +mcs <<
" Equivalent MCS for PHY abstraction (just for HARQ-IR) "
323 double errorRate = 1.0;
326 double cbler = MappingSinrBler(SINR, mcs_eq, K);
327 errorRate = 1.0 - pow(1.0 - cbler, C);
331 errorRate = MappingSinrBler(SINR, mcs_eq, K);
334 NS_LOG_DEBUG(
"Calculated Error rate " << errorRate);
337 Ptr<NrEesmErrorModelOutput> ret = Create<NrEesmErrorModelOutput>(errorRate);
338 ret->m_sinrEff = SINR;
341 if (sinrHistory.empty())
343 ret->m_sinrExp = sinrExpSum;
347 double m_sinrExpPrevious =
348 DynamicCast<NrEesmErrorModelOutput>(sinrHistory.back())->m_sinrExp;
349 ret->m_sinrExp = m_sinrExpPrevious + sinrExpSum;
351 ret->m_infoBits = sizeBit;
360 NS_LOG_FUNCTION(
this);
362 NS_ABORT_MSG_UNLESS(cqi >= 0 && cqi <= 15,
"CQI must be in [0..15] = " << cqi);
370 NS_LOG_FUNCTION(
this);
382 [[maybe_unused]]
Mode mode)
const
384 NS_LOG_FUNCTION(
this);
386 const uint32_t rscElement = usefulSc * rbNum;
390 const double spectralEfficiency = rscElement * Qm * Rcode * rank;
392 return static_cast<uint32_t
>(std::floor(spectralEfficiency / 8));
398 GraphType bgType = GetBaseGraphType(tbSize * 8, mcs);
401 return LiftingSizeTableBG.back() * 22 / 8;
403 NS_ASSERT(bgType == SECOND);
404 return LiftingSizeTableBG.back() * 10 / 8;
410 NS_LOG_FUNCTION(
this);
Ptr< NrErrorModelOutput > GetTbDecodificationStats(const SpectrumValue &sinr, const std::vector< int > &map, uint32_t size, uint8_t mcs, const NrErrorModelHistory &sinrHistory) override
Get an output for the decodification error probability of a given transport block,...
virtual double GetMcsEq(uint8_t mcsTx) const =0
Get the "Equivalent MCS" after retransmission combining.
uint32_t GetMaxCbSize(uint32_t tbSize, uint8_t mcs) const override
Get the maximum code block size in Bytes, as per NR. It depends on the LDPC base graph type.
double SinrEff(const SpectrumValue &sinr, const std::vector< int > &map, uint8_t mcs, double a, double b) const
compute the effective SINR for the specified MCS and SINR, according to the EESM method.
uint32_t GetPayloadSize(uint32_t usefulSc, uint8_t mcs, uint8_t rank, uint32_t rbNum, Mode mode) const override
Get the payload size in Bytes, following the MCSs in NR. It follows TS 38.214 Section 5....
virtual const std::vector< double > * GetBetaTable() const =0
static TypeId GetTypeId()
GetTypeId.
virtual const std::vector< double > * GetSpectralEfficiencyForMcs() const =0
virtual const std::vector< uint8_t > * GetMcsMTable() const =0
double SinrExp(const SpectrumValue &sinr, const std::vector< int > &map, uint8_t mcs) const
compute the sum of exponential SINRs for the specified MCS and SINR, according to the EESM method,...
uint8_t GetMaxMcs() const override
Get the maximum MCS. It depends on NR tables being used.
virtual const std::vector< double > * GetMcsEcrTable() const =0
~NrEesmErrorModel() override
~NrEesmErrorModel
std::string PrintMap(const std::vector< int > &map) const
function to print the RB map
virtual double ComputeSINR(const SpectrumValue &sinr, const std::vector< int > &map, uint8_t mcs, uint32_t sizeBit, const NrErrorModel::NrErrorModelHistory &sinrHistory) const =0
Compute the effective SINR after retransmission combining.
virtual const SimulatedBlerFromSINR * GetSimulatedBlerFromSINR() const =0
virtual const std::vector< double > * GetSpectralEfficiencyForCqi() const =0
NrEesmErrorModel()
NrEesmErrorModel constructor.
Interface for calculating the error probability for a transport block.
std::vector< Ptr< NrErrorModelOutput > > NrErrorModelHistory
Vector of previous output.
Mode
Indicate the mode (UL or DL)