From 79230ab8eebc026c420b2824e1f533fe16551f09 Mon Sep 17 00:00:00 2001 From: Marco Miozzo Date: Thu, 18 Oct 2012 13:58:10 +0200 Subject: [PATCH] Update LteMiErrorModel with BLER curves for HARQ retx ( MCS0 rv2 and rv3 still lacks) --- src/lte/model/lte-amc.cc | 15 +- src/lte/model/lte-enb-phy.cc | 2 +- src/lte/model/lte-mi-error-model.cc | 521 +++++++++++----------------- src/lte/model/lte-mi-error-model.h | 26 +- src/lte/model/lte-spectrum-phy.cc | 46 +-- src/lte/model/lte-spectrum-phy.h | 5 +- src/lte/model/lte-ue-phy.cc | 8 +- 7 files changed, 246 insertions(+), 377 deletions(-) diff --git a/src/lte/model/lte-amc.cc b/src/lte/model/lte-amc.cc index 35dc7ee33..8b3cb5b7b 100644 --- a/src/lte/model/lte-amc.cc +++ b/src/lte/model/lte-amc.cc @@ -345,18 +345,21 @@ LteAmc::CreateCqiFeedbacks (const SpectrumValue& sinr, uint8_t rbgSize) if ((rbId % rbgSize == 0)||((it+1)==sinr.ConstValuesEnd ())) { uint8_t mcs = 0; - double ber = 0.0; + TbStats_t tbStats; while (mcs < 28) { - ber = LteMiErrorModel::GetTbError (sinr, rbgMap, (uint16_t)GetTbSizeFromMcs (mcs, rbgSize) / 8, mcs); - if (ber > 0.1) - break; + HarqProcessInfoList_t harqInfoList; + tbStats = LteMiErrorModel::GetTbDecodificationStats (sinr, rbgMap, (uint16_t)GetTbSizeFromMcs (mcs, rbgSize) / 8, mcs, harqInfoList); + if (tbStats.tbler > 0.1) + { + break; + } mcs++; } - NS_LOG_DEBUG (this << "\t RBG " << rbId << " MCS " << (uint16_t)mcs << " BER " << ber); + NS_LOG_DEBUG (this << "\t RBG " << rbId << " MCS " << (uint16_t)mcs << " TBLER " << tbStats.tbler); int rbgCqi = 0; - if ((ber > 0.1)&&(mcs==0)) + if ((tbStats.tbler > 0.1)&&(mcs==0)) { rbgCqi = 0; // any MCS can guarantee the 10 % of BER } diff --git a/src/lte/model/lte-enb-phy.cc b/src/lte/model/lte-enb-phy.cc index 46d4ae2a1..a44d4a000 100644 --- a/src/lte/model/lte-enb-phy.cc +++ b/src/lte/model/lte-enb-phy.cc @@ -478,7 +478,7 @@ LteEnbPhy::StartSubFrame (void) { rbMap.push_back (i); } - m_uplinkSpectrumPhy->AddExpectedTb ((*dciIt).GetDci ().m_rnti, (*dciIt).GetDci ().m_tbSize, (*dciIt).GetDci ().m_mcs, rbMap, 0 /* always SISO*/, 0 /* no HARQ proc id in UL*/, 0.0 /* MI TBD */, false /* UL*/); + m_uplinkSpectrumPhy->AddExpectedTb ((*dciIt).GetDci ().m_rnti, (*dciIt).GetDci ().m_ndi, (*dciIt).GetDci ().m_tbSize, (*dciIt).GetDci ().m_mcs, rbMap, 0 /* always SISO*/, 0 /* no HARQ proc id in UL*/, false /* UL*/); if ((*dciIt).GetDci ().m_ndi==1) { NS_LOG_DEBUG (this << " RNTI " << (*dciIt).GetDci ().m_rnti << " NEW TB"); diff --git a/src/lte/model/lte-mi-error-model.cc b/src/lte/model/lte-mi-error-model.cc index ba3b4b612..44e265e86 100644 --- a/src/lte/model/lte-mi-error-model.cc +++ b/src/lte/model/lte-mi-error-model.cc @@ -46,6 +46,34 @@ NS_LOG_COMPONENT_DEFINE ("LteMiErrorModel"); namespace ns3 { + + // global table of the effective code rates (ECR)s that have BLER performance curves + double BlerCurvesEcrMap[38] = { + // QPSK (M=2) + 0.000041, 0.000512, 0.00064, // ECRs of MCS0 retx + 0.08, 0.1, 0.11, 0.15, 0.19, 0.24, 0.3, 0.37, 0.44, 0.51, // ECRs of MCSs + // 16QAM (M=4) + 0.0081, 0.027, 0.09, // ECRs of MCS10 retx + 0.3, 0.33, 0.37, 0.42, 0.48, 0.54, 0.6,// ECRs of MCSs + // 64QAM (M=6) + 0.034, 0.079, 0.185,// ECRs of MCS17 retx + 0.43, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.89, 0.92// ECRs of MCSs + }; + + // Table codifing standard MCSs ECR to available ECRs + uint8_t McsEcrBlerTableMapping[29] = { + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 16, 17, 18, 19, 20, 21, 22, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 + }; + + // Table of ECR of the standard MCSs + double McsEcrTable [29] = {0.08, 0.1, 0.11, 0.15, 0.19, 0.24, 0.3, 0.37, 0.44, 0.51, 0.3, 0.33, 0.37, 0.42, 0.48, 0.54, 0.6, 0.43, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.89, 0.92 + }; + + // Table with ECRs obtained with retransmissions with BLER curves + double HarqRetxEcr[9] = {0.00064, 0.000512, 0.000041, 0.09, 0.027, 0.0081, 0.185, 0.079, 0.034 + }; // PCFICH-PDCCH Error model based on 3GPP R4-081920 "LTE PDCCH/PCFICH // Demodulation Performance Results with Implementation Margin" @@ -122,136 +150,172 @@ double MI_map_64qam_axis[MI_MAP_64QAM_SIZE] = { -double bEcrTable [9][29] = { +double bEcrTable [9][38] = { // CB of 40 bits { - 0.1777, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.01572, // QPSK retx + 0.1777, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // QPSK + -1.000, -1.000, -1.000, // 16QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM }, // CB of 104 bits { - 0.1423, 0.1753, 0.1882, 0.2499, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.01224, // QPSK retx + 0.1423, 0.1753, 0.1882, 0.2499, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // QPSK + -1.000, -1.000, -1.000, // 16QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM }, // CB of 160 { - 0.1354, 0.1655, 0.1812, 0.2351, 0.2873, 0.3462, -1.000, -1.000, -1.000, - -1.0000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.01148, // QPSK retx + 0.1354, 0.1655, 0.1812, 0.2351, 0.2873, 0.3462, -1.000, -1.000, -1.000, -1.0000, // QPSK + -1.000, -1.000, -1.000, // 16QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM }, // CB of 256 { - 0.1304, 0.1584, 0.1735, 0.2265, 0.2782, 0.3340, 0.3927, 0.4785, 0.5566, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.01094, // QPSK retx + 0.1304, 0.1584, 0.1735, 0.2265, 0.2782, 0.3340, 0.3927, 0.4785, 0.5566, -1.000, // QPSK + -1.000, -1.000, -1.000, // 16QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM }, // CB of 512 { - 0.1257, 0.1528, 0.1667, 0.2188, 0.2680, 0.3229, 0.3818, 0.4607, 0.5373, - 0.6081, 0.7451, 0.4049, 0.4472, 0.4975, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.01048, // QPSK retx + 0.1257, 0.1528, 0.1667, 0.2188, 0.2680, 0.3229, 0.3818, 0.4607, 0.5373, 0.6081, // QPSK + 0.07198, 0.16632, 0.3737, // 16 QAM retx + 0.7451, 0.4049, 0.4472, 0.4975, -1.000, -1.000, -1.000, //16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM }, // CB of 1024 { - 0.1224, 0.1497, 0.1638, 0.2139, 0.2636, 0.3195, 0.3768, 0.4520, 0.5269, - 0.5963, 0.7412, 0.3979, 0.4399, 0.4894, 0.6422, 0.6034, 0.6619, 0.7538, - 0.7743, 0.5627, 0.6089, 0.6577, 0.7049, 0.7508, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.01026, // QPSK retx + 0.1224, 0.1497, 0.1638, 0.2139, 0.2636, 0.3195, 0.3768, 0.4520, 0.5269, 0.5963, // QPSK + 0.07228, 0.1652, 0.36928, // 16QAM retx + 0.7412, 0.3979, 0.4399, 0.4894, 0.6422, 0.6034, 0.6619, // 16QAM + 0.21138, 0.42448, 0.77898, // 64QAM retx + 0.7538, 0.7743, 0.5627, 0.6089, 0.6577, 0.7049, 0.7508, -1.000, -1.000, -1.000, -1.000, -1.000 //64QAM }, // CB of 2560 { - 0.1211, 0.1480, 0.1615, 0.2119, 0.2611, 0.3157, 0.3735, 0.4458, 0.5205, - 0.5902, 0.7376, 0.3939, 0.4351, 0.4851, 0.6365, 0.5976, 0.6554, 0.7442, - 0.7701, 0.5619, 0.6056, 0.6521, 0.6982, 0.7441, 0.7874, 0.8315, 0.8735, - 0.9089, 0.9369 + -1.000, -1.000, 0.01008, // QPSK retx + 0.1211, 0.1480, 0.1615, 0.2119, 0.2611, 0.3157, 0.3735, 0.4458, 0.5205, 0.5902, // QPSK + 0.0592, 0.15188, 0.36016, // 16 QAM retx + 0.7376, 0.3939, 0.4351, 0.4851, 0.6365, 0.5976, 0.6554, // 16QAM + 0.20886, 0.41926, 0.76674, // 64 QAM retx + 0.7442, 0.7701, 0.5619, 0.6056, 0.6521, 0.6982, 0.7441, 0.7874, 0.8315, 0.8735, 0.9089, 0.9369 // 64QAM }, // CB of 4032 { - 0.1208, 0.1477, 0.1612, 0.2112, 0.2606, 0.3153, 0.3728, 0.4441, 0.5185, - 0.5882, 0.7349, 0.3921, 0.4338, 0.4871, 0.6535, 0.5940, 0.6527, 0.7430, - 0.7699, 0.5591, 0.6027, 0.6512, 0.6981, 0.7437, 0.7873, 0.8301, 0.8702, - 0.9082, 0.9339 + -1.000, -1.000, 0.01008, // QPSK retx + 0.1208, 0.1477, 0.1612, 0.2112, 0.2606, 0.3153, 0.3728, 0.4441, 0.5185, 0.5882, // QPSK + 0.06074, 0.1527, 0.36034, // 16 QAM retx + 0.7349, 0.3921, 0.4338, 0.4871, 0.6535, 0.5940, 0.6527, // 16QAM + 0.2088, 0.41928, 0.76588, // 64QAM retx + 0.7430, 0.7699, 0.5591, 0.6027, 0.6512, 0.6981, 0.7437, 0.7873, 0.8301, 0.8702, 0.9082, 0.9339 // 64QAM }, // CB of 6144 { - 0.1207, 0.1474, 0.1612, 0.2111, 0.2605, 0.3153, 0.3726, 0.4439, 0.5193, - 0.5882, 0.7369, 0.3921, 0.4339, 0.4833, 0.6339, 0.5952, 0.6528, 0.7420, - 0.7664, 0.5600, 0.6027, 0.6494, 0.6948, 0.7407, 0.7842, 0.8284, 0.8692, - 0.9058, 0.9325 + -1.000, -1.000, 0.01006, // QPSK retx + 0.1207, 0.1474, 0.1612, 0.2111, 0.2605, 0.3153, 0.3726, 0.4439, 0.5193, 0.5882, // QPSK + 0.06302, 0.15566, 0.36364, // 16QAM retx + 0.7369, 0.3921, 0.4339, 0.4833, 0.6339, 0.5952, 0.6528, // 16QAM + 0.20874, 0.41872, 0.76562, // 64QAM retx + 0.7420, 0.7664, 0.5600, 0.6027, 0.6494, 0.6948, 0.7407, 0.7842, 0.8284, 0.8692, 0.9058, 0.9325 // 64QAM }, }; -double cEcrTable [9][29] = { +double cEcrTable [9][38] = { // CB of 40 bits { - 0.0342, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.00359, // QPSK retx + 0.0342, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // QPSK + -1.000, -1.000, -1.000, // 16QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64 QAM }, // CB of 104 bits { - 0.0198, 0.0239, 0.0248, 0.0320, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.00193, // QPSK retx + 0.0198, 0.0239, 0.0248, 0.0320, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // QPSK + -1.000, -1.000, -1.000, // 16QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM }, // CB of 160 bits { - 0.0157, 0.0190, 0.0204, 0.0252, 0.0310, 0.0348, -1.0000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.00159, // QPSK retx + 0.0157, 0.0190, 0.0204, 0.0252, 0.0310, 0.0348, -1.0000, -1.000, -1.000, -1.000, //QPSK + -1.000, -1.000, -1.000, // 16QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM }, // CB of 256 bits { - 0.0123, 0.0149, 0.0163, 0.0212, 0.0252, 0.0298, 0.0304, 0.0341, 0.0382, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.00119, // QPSK retx + 0.0123, 0.0149, 0.0163, 0.0212, 0.0252, 0.0298, 0.0304, 0.0341, 0.0382, -1.000, // QPSK + -1.000, -1.000, -1.000, // 16QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, // 16QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 }, // CB of 512 bits { - 0.0085, 0.0106, 0.0109, 0.0140, 0.0178, 0.0217, 0.0219, 0.0249, 0.0270, - 0.0292, 0.0293, 0.0206, 0.0220, 0.0235, 0.0257, -1.000, -1.000, -1.000, - -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.00091, // QPSK retx + 0.0085, 0.0106, 0.0109, 0.0140, 0.0178, 0.0217, 0.0219, 0.0249, 0.0270, 0.0292, // QPSK + 0.00797, 0.01357, 0.0234, // 16QAM retx + 0.0293, 0.0206, 0.0220, 0.0235, 0.0257, -1.000, -1.000, // 16 QAM + -1.000, -1.000, -1.000, // 64QAM retx + -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000, -1.000 }, // CB of 1024 bits { - 0.0061, 0.0074, 0.0078, 0.0102, 0.0121, 0.0138, 0.0163, 0.0178, 0.0207, - 0.0198, 0.0203, 0.0137, 0.0154, 0.0164, 0.0183, 0.0188, 0.0188, 0.0220, - 0.0215, 0.0157, 0.0169, 0.0185, 0.0189, 0.0200, -1.000, -1.000, -1.000, - -1.000, -1.000 + -1.000, -1.000, 0.00059, // QPSK retx + 0.0061, 0.0074, 0.0078, 0.0102, 0.0121, 0.0138, 0.0163, 0.0178, 0.0207, 0.0198, // QPSK + 0.00615, 0.01013, 0.01681, // 16QAM retx + 0.0203, 0.0137, 0.0154, 0.0164, 0.0183, 0.0188, 0.0188, // 16QAM + 0.01053, 0.01869, 0.02261, // 64QAM retx + 0.0220, 0.0215, 0.0157, 0.0169, 0.0185, 0.0189, 0.0200, -1.000, -1.000, -1.000, -1.000, -1.000 // 64QAM }, // CB of 2560 bits { - 0.0040, 0.0047, 0.0050, 0.0063, 0.0079, 0.0091, 0.0101, 0.0117, 0.0123, - 0.0129, 0.0123, 0.0091, 0.0095, 0.0102, 0.0116, 0.0114, 0.0119, 0.0116, - 0.0123, 0.0096, 0.0104, 0.0109, 0.0108, 0.0118, 0.0122, 0.0117, 0.0110, - 0.0097, 0.0085 + -1.000, -1.000, 0.00039, // QPSK retx + 0.0040, 0.0047, 0.0050, 0.0063, 0.0079, 0.0091, 0.0101, 0.0117, 0.0123, 0.0129, // QPSK + 0.00213, 0.00475, 0.00921, // 16QAM retx + 0.0123, 0.0091, 0.0095, 0.0102, 0.0116, 0.0114, 0.0119, // 16QAM + 0.00637, 0.01161, 0.01273, // 64QAM retx + 0.0116, 0.0123, 0.0096, 0.0104, 0.0109, 0.0108, 0.0118, 0.0122, 0.0117, 0.0110, 0.0097, 0.0085 // 64QAM }, // CB of 4032 bits { - 0.0032, 0.0038, 0.0039, 0.0051, 0.0063, 0.0072, 0.0079, 0.0084, 0.0100, - 0.0106, 0.0106, 0.0074, 0.0078, 0.0090, 0.0095, 0.0089, 0.0092, 0.0101, - 0.0096, 0.0080, 0.0081, 0.0090, 0.0091, 0.0095, 0.0096, 0.0094, 0.0086, - 0.0078, 0.0071 + -1.000, -1.000, 0.00029, // QPSK retx + 0.0032, 0.0038, 0.0039, 0.0051, 0.0063, 0.0072, 0.0079, 0.0084, 0.0100, 0.0106, // QPSK + 0.00193, 0.00405, 0.00777, // 16QAM retx + 0.0106, 0.0074, 0.0078, 0.0090, 0.0095, 0.0089, 0.0092, // 16 QAM + 0.00565, 0.00981, 0.01143, // 64QAM retx + 0.0101, 0.0096, 0.0080, 0.0081, 0.0090, 0.0091, 0.0095, 0.0096, 0.0094, 0.0086, 0.0078, 0.0071 // 64QAM }, // CB of 6144 bits { - 0.0025, 0.0032, 0.0032, 0.0042, 0.0054, 0.0059, 0.0064, 0.0073, 0.0081, - 0.0076, 0.0083, 0.0058, 0.0064, 0.0070, 0.0077, 0.0074, 0.0080, 0.0080, - 0.0080, 0.0061, 0.0066, 0.0069, 0.0080, 0.0081, 0.0080, 0.0077, 0.0068, - 0.0066, 0.0058 + -1.000, -1.000, 0.00025, // QPSK retx + 0.0025, 0.0032, 0.0032, 0.0042, 0.0054, 0.0059, 0.0064, 0.0073, 0.0081, 0.0076, // QPSK + 0.00175, 0.00367, 0.006223, // 16QAM retx + 0.0083, 0.0058, 0.0064, 0.0070, 0.0077, 0.0074, 0.0080, // 16QAM + 0.00437, 0.00785, 0.00873, + 0.0080, 0.0080, 0.0061, 0.0066, 0.0069, 0.0080, 0.0081, 0.0080, 0.0077, 0.0068, 0.0066, 0.0058 // 64QAM } }; @@ -269,7 +333,7 @@ LteMiErrorModel::Mib (const SpectrumValue& sinr, const std::vector& map, ui { SpectrumValue sinrCopy = sinr; double sinrLin = sinrCopy[map.at (i)]; - if (mcs <= 10) // QPSK + if (mcs <= MI_QPSK_MAX_ID) // QPSK { int tr = 0; while ((tr& map, ui } else { - if (mcs > 10 && mcs < 20 ) // 16-QAM + if (mcs > MI_QPSK_MAX_ID && mcs <= MI_16QAM_MAX_ID ) // 16-QAM { int tr = 0; while ((tr& map, ui double -LteMiErrorModel::MappingMiBler (double mib, uint8_t mcs, uint16_t cbSize) +LteMiErrorModel::MappingMiBler (double mib, uint8_t ecrId, uint16_t cbSize) { - NS_LOG_FUNCTION (mib << (uint32_t) mcs << (uint32_t) cbSize); + NS_LOG_FUNCTION (mib << (uint32_t) ecrId << (uint32_t) cbSize); double b = 0; double c = 0; - NS_ASSERT_MSG (mcs < 29, "MCS out of range [0..28]"); + if (ecrId<2) + { + ecrId = 2; // Minimum ECR with available BLER curves + } + NS_ASSERT_MSG (ecrId <= MI_64QAM_BLER_MAX_ID, "ECR out of range [0..37]: " << (uint16_t) ecrId); int cbIndex = 1; while ((cbIndex < 9)&&(cbMiSizeTable[cbIndex]<= cbSize)) { cbIndex++; } cbIndex--; - NS_LOG_LOGIC (" MCS " << (uint16_t)mcs << " TBS " << TbsIndex[mcs] << " CB size " << cbSize << " CB size curve " << cbMiSizeTable[cbIndex]); + NS_LOG_LOGIC (" ECR " << (uint16_t)ecrId << " CB size " << cbSize << " CB size curve " << cbMiSizeTable[cbIndex]); - b = bEcrTable[cbIndex][mcs]; + b = bEcrTable[cbIndex][ecrId]; if (b<0.0) { //take the lowest CB size including this CB for removing CB size @@ -355,10 +423,10 @@ LteMiErrorModel::MappingMiBler (double mib, uint8_t mcs, uint16_t cbSize) int i = cbIndex; while ((i<9)&&(b<0)) { - b = bEcrTable[i++][mcs]; + b = bEcrTable[i++][ecrId]; } } - c = cEcrTable[cbIndex][mcs]; + c = cEcrTable[cbIndex][ecrId]; if (c<0.0) { //take the lowest CB size including this CB for removing CB size @@ -366,7 +434,7 @@ LteMiErrorModel::MappingMiBler (double mib, uint8_t mcs, uint16_t cbSize) int i = cbIndex; while ((i<9)&&(c<0)) { - c = cEcrTable[i++][mcs]; + c = cEcrTable[i++][ecrId]; } } // see IEEE802.16m EMD formula 55 of section 4.3.2.1 @@ -376,241 +444,6 @@ LteMiErrorModel::MappingMiBler (double mib, uint8_t mcs, uint16_t cbSize) } -double -LteMiErrorModel::GetTbError (const SpectrumValue& sinr, const std::vector& map, uint16_t size, uint8_t mcs) -{ - NS_LOG_FUNCTION (sinr << &map << (uint32_t) size << (uint32_t) mcs); - - double MI = Mib(sinr, map, mcs); - // estimate CB size (according to sec 5.1.2 of TS 36.212) - uint16_t Z = 6144; // max size of a codeblock (including CRC) - uint32_t B = size * 8; -// B = 1234; - uint32_t L = 0; - uint32_t C = 0; // no. of codeblocks - uint32_t Cplus = 0; // no. of codeblocks with size K+ - uint32_t Kplus = 0; // no. of codeblocks with size K+ - uint32_t Cminus = 0; // no. of codeblocks with size K+ - uint32_t Kminus = 0; // no. of codeblocks with size K+ - uint32_t B1 = 0; - uint32_t deltaK = 0; - if (B <= Z) - { - // only one codeblock - L = 0; - C = 1; - B1 = B; - } - else - { - L = 24; - C = ceil ((double)B / ((double)(Z-L))); - B1 = B + C * L; - } - // first segmentation: K+ = minimum K in table such that C * K >= B1 -// uint i = 0; -// while (B1 > cbSizeTable[i] * C) -// { -// // NS_LOG_INFO (" K+ " << cbSizeTable[i] << " means " << cbSizeTable[i] * C); -// i++; -// } -// uint16_t KplusId = i; -// Kplus = cbSizeTable[i]; - - // implement a modified binary search - int min = 0; - int max = 187; - int mid = 0; - do - { - mid = (min+max) / 2; - if (B1 > cbSizeTable[mid]*C) - { - if (B1 < cbSizeTable[mid+1]*C) - { - break; - } - else - { - min = mid + 1; - } - } - else - { - if (B1 > cbSizeTable[mid-1]*C) - { - break; - } - else - { - max = mid - 1; - } - } - } while ((cbSizeTable[mid]*C != B1) && (min < max)); - // adjust binary search to the largest integer value of K containing B1 - if (B1 > cbSizeTable[mid]*C) - { - mid ++; - } - - uint16_t KplusId = mid; - Kplus = cbSizeTable[mid]; - - - if (C==1) - { - Cplus = 1; - Cminus = 0; - Kminus = 0; - } - else - { - // second segmentation size: K- = maximum K in table such that K < K+ - Kminus = cbSizeTable[KplusId-1 > 0 ? KplusId-1 : 0]; - deltaK = Kplus - Kminus; - Cminus = floor ((((double) C * Kplus) - (double)B1) / (double)deltaK); - Cplus = C - Cminus; - } - NS_LOG_INFO ("--------------------LteMiErrorModel: TB size of " << B << " needs of " << B1 << " bits reparted in " << C << " CBs as "<< Cplus << " block(s) of " << Kplus << " and " << Cminus << " of " << Kminus); - - double errorRate = 1.0; - if (C!=1) - { - double cbler = MappingMiBler (MI, mcs, Kplus); - errorRate *= pow (1.0 - cbler, Cplus); - cbler = MappingMiBler (MI, mcs, Kminus); - errorRate *= pow (1.0 - cbler, Cminus); - errorRate = 1.0 - errorRate; - } - else - { - errorRate = MappingMiBler (MI, mcs, Kplus); - } - - NS_LOG_LOGIC (" Error rate " << errorRate); - - return errorRate; -} - - -TbStats_t -LteMiErrorModel::GetTbDecodificationStats (const SpectrumValue& sinr, const std::vector& map, uint16_t size, uint8_t mcs, double mi) -{ - NS_LOG_FUNCTION (sinr << &map << (uint32_t) size << (uint32_t) mcs); - - double MI = Mib(sinr, map, mcs) + mi; - // estimate CB size (according to sec 5.1.2 of TS 36.212) - uint16_t Z = 6144; // max size of a codeblock (including CRC) - uint32_t B = size * 8; -// B = 1234; - uint32_t L = 0; - uint32_t C = 0; // no. of codeblocks - uint32_t Cplus = 0; // no. of codeblocks with size K+ - uint32_t Kplus = 0; // no. of codeblocks with size K+ - uint32_t Cminus = 0; // no. of codeblocks with size K+ - uint32_t Kminus = 0; // no. of codeblocks with size K+ - uint32_t B1 = 0; - uint32_t deltaK = 0; - if (B <= Z) - { - // only one codeblock - L = 0; - C = 1; - B1 = B; - } - else - { - L = 24; - C = ceil ((double)B / ((double)(Z-L))); - B1 = B + C * L; - } - // first segmentation: K+ = minimum K in table such that C * K >= B1 -// uint i = 0; -// while (B1 > cbSizeTable[i] * C) -// { -// // NS_LOG_INFO (" K+ " << cbSizeTable[i] << " means " << cbSizeTable[i] * C); -// i++; -// } -// uint16_t KplusId = i; -// Kplus = cbSizeTable[i]; - - // implement a modified binary search - int min = 0; - int max = 187; - int mid = 0; - do - { - mid = (min+max) / 2; - if (B1 > cbSizeTable[mid]*C) - { - if (B1 < cbSizeTable[mid+1]*C) - { - break; - } - else - { - min = mid + 1; - } - } - else - { - if (B1 > cbSizeTable[mid-1]*C) - { - break; - } - else - { - max = mid - 1; - } - } - } while ((cbSizeTable[mid]*C != B1) && (min < max)); - // adjust binary search to the largest integer value of K containing B1 - if (B1 > cbSizeTable[mid]*C) - { - mid ++; - } - - uint16_t KplusId = mid; - Kplus = cbSizeTable[mid]; - - - if (C==1) - { - Cplus = 1; - Cminus = 0; - Kminus = 0; - } - else - { - // second segmentation size: K- = maximum K in table such that K < K+ - Kminus = cbSizeTable[KplusId-1 > 0 ? KplusId-1 : 0]; - deltaK = Kplus - Kminus; - Cminus = floor ((((double) C * Kplus) - (double)B1) / (double)deltaK); - Cplus = C - Cminus; - } - NS_LOG_INFO ("--------------------LteMiErrorModel: TB size of " << B << " needs of " << B1 << " bits reparted in " << C << " CBs as "<< Cplus << " block(s) of " << Kplus << " and " << Cminus << " of " << Kminus); - - double errorRate = 1.0; - if (C!=1) - { - double cbler = MappingMiBler (MI, mcs, Kplus); - errorRate *= pow (1.0 - cbler, Cplus); - cbler = MappingMiBler (MI, mcs, Kminus); - errorRate *= pow (1.0 - cbler, Cminus); - errorRate = 1.0 - errorRate; - } - else - { - errorRate = MappingMiBler (MI, mcs, Kplus); - } - - NS_LOG_LOGIC (" Error rate " << errorRate); - TbStats_t ret; - ret.error = errorRate; - ret.mi = MI; - return ret; -} - double LteMiErrorModel::GetPcfichPdcchError (const SpectrumValue& sinr) @@ -819,22 +652,64 @@ LteMiErrorModel::GetTbDecodificationStats (const SpectrumValue& sinr, const std: NS_LOG_INFO ("--------------------LteMiErrorModel: TB size of " << B << " needs of " << B1 << " bits reparted in " << C << " CBs as "<< Cplus << " block(s) of " << Kplus << " and " << Cminus << " of " << Kminus); double errorRate = 1.0; + uint8_t ecrId = 0; + if (miHistory.size ()==0) + { + // first tx -> get ECR from MCS + ecrId = McsEcrBlerTableMapping[mcs]; + NS_LOG_DEBUG ("NO HARQ MCS " << (uint16_t)mcs << " ECR id " << (uint16_t)ecrId); + } + else + { + NS_LOG_DEBUG ("HARQ!!!!!!!!!!! " << miHistory.size ()); + // harq retx -> get closest ECR to Reff from available ones + if (mcs <= MI_QPSK_MAX_ID) + { + // Modulation order 2 + uint8_t i = MI_QPSK_MAX_ID; + while ((BlerCurvesEcrMap[i]>Reff)&&(i>0)) + { + i--; + } + ecrId = i; + } + else if (mcs <= MI_16QAM_MAX_ID) + { + // Modulation order 4 + uint8_t i = MI_16QAM_MAX_ID; + while ((BlerCurvesEcrMap[i]>Reff)&&(i>MI_QPSK_MAX_ID)) + { + i--; + } + ecrId = i; + } + else + { + // Modulation order 6 + uint8_t i = MI_64QAM_MAX_ID; + while ((BlerCurvesEcrMap[i]>Reff)&&(i>MI_16QAM_MAX_ID)) + { + i--; + } + ecrId = i; + } + } if (C!=1) { - double cbler = MappingMiBler (MI, mcs, Kplus); + double cbler = MappingMiBler (MI, ecrId, Kplus); errorRate *= pow (1.0 - cbler, Cplus); - cbler = MappingMiBler (MI, mcs, Kminus); + cbler = MappingMiBler (MI, ecrId, Kminus); errorRate *= pow (1.0 - cbler, Cminus); errorRate = 1.0 - errorRate; } else { - errorRate = MappingMiBler (MI, mcs, Kplus); + errorRate = MappingMiBler (MI, ecrId, Kplus); } NS_LOG_LOGIC (" Error rate " << errorRate); TbStats_t ret; - ret.error = errorRate; + ret.tbler = errorRate; ret.mi = tbMi; return ret; } diff --git a/src/lte/model/lte-mi-error-model.h b/src/lte/model/lte-mi-error-model.h index ce3fe3409..14277e684 100644 --- a/src/lte/model/lte-mi-error-model.h +++ b/src/lte/model/lte-mi-error-model.h @@ -49,10 +49,16 @@ namespace ns3 { const uint16_t MI_MAP_QPSK_SIZE = 766; const uint16_t MI_MAP_16QAM_SIZE = 843; const uint16_t MI_MAP_64QAM_SIZE = 725; + const uint16_t MI_QPSK_MAX_ID = 9; + const uint16_t MI_16QAM_MAX_ID = 16; + const uint16_t MI_64QAM_MAX_ID = 28; // 29,30 and 31 are reserved + const uint16_t MI_QPSK_BLER_MAX_ID = 12; // MI_QPSK_MAX_ID + 3 RETX + const uint16_t MI_16QAM_BLER_MAX_ID = 22; + const uint16_t MI_64QAM_BLER_MAX_ID = 37; struct TbStats_t { - double error; + double tbler; double mi; }; @@ -81,17 +87,7 @@ public: * \param cbSize the size of the CB * \return the code block error rate */ - static double MappingMiBler (double mib, uint8_t mcs, uint16_t cbSize); - - /** - * \brief run the error-model algorithm for the specified TB - * \param sinr the perceived sinrs in the whole bandwidth - * \param map the actives RBs for the TB - * \param size the size in bytes of the TB - * \param mcs the MCS of the TB - * \return the TB error rate - */ - static double GetTbError (const SpectrumValue& sinr, const std::vector& map, uint16_t size, uint8_t mcs); + static double MappingMiBler (double mib, uint8_t ecrId, uint16_t cbSize); /** * \brief run the error-model algorithm for the specified TB @@ -99,11 +95,9 @@ public: * \param map the actives RBs for the TB * \param size the size in bytes of the TB * \param mcs the MCS of the TB - * \param cumulatedMi MI of past transmissions (in case of retx) - * \return the TB error rate + * \param miHistory MI of past transmissions (in case of retx) + * \return the TB error rate and MI */ - static TbStats_t GetTbDecodificationStats (const SpectrumValue& sinr, const std::vector& map, uint16_t size, uint8_t mcs, double cumulatedMi); - static TbStats_t GetTbDecodificationStats (const SpectrumValue& sinr, const std::vector& map, uint16_t size, uint8_t mcs, HarqProcessInfoList_t miHistory); /** diff --git a/src/lte/model/lte-spectrum-phy.cc b/src/lte/model/lte-spectrum-phy.cc index aa1071f35..1919f408d 100644 --- a/src/lte/model/lte-spectrum-phy.cc +++ b/src/lte/model/lte-spectrum-phy.cc @@ -775,9 +775,9 @@ LteSpectrumPhy::UpdateSinrPerceived (const SpectrumValue& sinr) void -LteSpectrumPhy::AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std::vector map, uint8_t layer, uint8_t harqId, double miCumulated, bool downlink) +LteSpectrumPhy::AddExpectedTb (uint16_t rnti, uint8_t ndi, uint16_t size, uint8_t mcs, std::vector map, uint8_t layer, uint8_t harqId, bool downlink) { - NS_LOG_FUNCTION (this << " rnti: " << rnti << " size " << size << " mcs " << (uint16_t)mcs << " layer " << (uint16_t)layer << " MI " << miCumulated); + NS_LOG_FUNCTION (this << " rnti: " << rnti << " NDI " << (uint16_t)ndi << " size " << size << " mcs " << (uint16_t)mcs << " layer " << (uint16_t)layer); TbId_t tbId; tbId.m_rnti = rnti; tbId.m_layer = layer; @@ -790,7 +790,7 @@ LteSpectrumPhy::AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std:: } // insert new entry std::vector rv; - tbInfo_t tbInfo = {size, mcs, map, harqId, miCumulated, downlink, false}; + tbInfo_t tbInfo = {ndi, size, mcs, map, harqId, 0.0, downlink, false}; m_expectedTbs.insert (std::pair (tbId,tbInfo)); } @@ -819,33 +819,35 @@ LteSpectrumPhy::EndRxData () { if (m_dataErrorModelEnabled) { -// double errorRate = LteMiErrorModel::GetTbError (m_sinrPerceived, (*itTb).second.rbBitmap, (*itTb).second.size, (*itTb).second.mcs); // retrieve HARQ info HarqProcessInfoList_t harqInfoList; - uint16_t ulHarqId = 0; // TODO 0 means current HARQ porc under evaluation - if ((*itTb).second.downlink) + if ((*itTb).second.ndi == 0) { - harqInfoList = m_harqPhyModule->GetHarqProcessInfoDl ((*itTb).second.harqProcessId, (*itTb).first.m_layer); + // TB retxed: retrieve HARQ history + uint16_t ulHarqId = 0; + if ((*itTb).second.downlink) + { + harqInfoList = m_harqPhyModule->GetHarqProcessInfoDl ((*itTb).second.harqProcessId, (*itTb).first.m_layer); + } + else + { + harqInfoList = m_harqPhyModule->GetHarqProcessInfoUl ((*itTb).first.m_rnti, ulHarqId); + } } - else - { - harqInfoList = m_harqPhyModule->GetHarqProcessInfoUl ((*itTb).first.m_rnti, ulHarqId); - } -// TbStats_t tbStats = LteMiErrorModel::GetTbDecodificationStats (m_sinrPerceived, (*itTb).second.rbBitmap, (*itTb).second.size, (*itTb).second.mcs, (*itTb).second.mi); TbStats_t tbStats = LteMiErrorModel::GetTbDecodificationStats (m_sinrPerceived, (*itTb).second.rbBitmap, (*itTb).second.size, (*itTb).second.mcs, harqInfoList); (*itTb).second.mi = tbStats.mi; - (*itTb).second.corrupt = m_random->GetValue () > tbStats.error ? false : true; + (*itTb).second.corrupt = m_random->GetValue () > tbStats.tbler ? false : true; // DEBUG: force error for testing HARQ - if ((*itTb).second.downlink) - { +// if ((*itTb).second.downlink) +// { // if (((*itTb).second.harqProcessId == 0)&&(Simulator::Now ().GetNanoSeconds ()<=20000000)) - if ((errors<1) && ( ((*itTb).first.m_rnti==1)||((*itTb).first.m_rnti==3)) ) - { - (*itTb).second.corrupt = true; - errors++; - } - } - NS_LOG_DEBUG (this << "RNTI " << (*itTb).first.m_rnti << " size " << (*itTb).second.size << " mcs " << (uint32_t)(*itTb).second.mcs << " bitmap " << (*itTb).second.rbBitmap.size () << " layer " << (uint16_t)(*itTb).first.m_layer << " ErrorRate " << tbStats.error << " corrupted " << (*itTb).second.corrupt); +// if ((errors<1) && ( ((*itTb).first.m_rnti==1)||((*itTb).first.m_rnti==3)) ) +// { +// (*itTb).second.corrupt = true; +// errors++; +// } +// } + NS_LOG_DEBUG (this << "RNTI " << (*itTb).first.m_rnti << " size " << (*itTb).second.size << " mcs " << (uint32_t)(*itTb).second.mcs << " bitmap " << (*itTb).second.rbBitmap.size () << " layer " << (uint16_t)(*itTb).first.m_layer << " TBLER " << tbStats.tbler << " corrupted " << (*itTb).second.corrupt); } // for (uint16_t i = 0; i < (*itTb).second.rbBitmap.size (); i++) diff --git a/src/lte/model/lte-spectrum-phy.h b/src/lte/model/lte-spectrum-phy.h index 9fd94ec32..10b3cd35d 100644 --- a/src/lte/model/lte-spectrum-phy.h +++ b/src/lte/model/lte-spectrum-phy.h @@ -60,6 +60,7 @@ struct TbId_t struct tbInfo_t { + uint8_t ndi; uint16_t size; uint8_t mcs; std::vector rbBitmap; @@ -321,15 +322,15 @@ public: * * * \param rnti the rnti of the source of the TB + * \param ndi new data indicator flag * \param size the size of the TB * \param mcs the MCS of the TB * \param map the map of RB(s) used * \param layer the layer (in case of MIMO tx) * \param harqId the id of the HARQ process (valid only for DL) - * \param miCumulated the MI cumulated (in case of HARQ retx) * \param downlink true when the TB is for DL */ - void AddExpectedTb (uint16_t rnti, uint16_t size, uint8_t mcs, std::vector map, uint8_t layer, uint8_t harqId, double miCumulated, bool downlink); + void AddExpectedTb (uint16_t rnti, uint8_t ndi, uint16_t size, uint8_t mcs, std::vector map, uint8_t layer, uint8_t harqId, bool downlink); /** diff --git a/src/lte/model/lte-ue-phy.cc b/src/lte/model/lte-ue-phy.cc index a37dd8a32..e2d95b96a 100644 --- a/src/lte/model/lte-ue-phy.cc +++ b/src/lte/model/lte-ue-phy.cc @@ -549,13 +549,7 @@ LteUePhy::ReceiveLteControlMessageList (std::list > msgLi NS_LOG_DEBUG (this << " UE " << m_rnti << " DL-DCI " << dci.m_rnti << " bitmap " << dci.m_rbBitmap); for (uint8_t i = 0; i < dci.m_tbsSize.size (); i++) { - double miCumulated = 0.0; - if (dci.m_ndi.at (i)!=0) - { - // TODO : retrieve MI info on retransmissions - miCumulated = 0.0; - } - m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i, dci.m_harqProcess, miCumulated, true /* DL */); + m_downlinkSpectrumPhy->AddExpectedTb (dci.m_rnti, dci.m_ndi.at (i), dci.m_tbsSize.at (i), dci.m_mcs.at (i), dlRb, i, dci.m_harqProcess, true /* DL */); } SetSubChannelsForReception (dlRb);