5G-LENA nr-v3.1-69-g2dd513a7
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
nr-test-harq.cc
Go to the documentation of this file.
1// Copyright (c) 2021 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
2//
3// SPDX-License-Identifier: GPL-2.0-only
4
5#include <ns3/nr-eesm-cc-t1.h>
6#include <ns3/nr-eesm-error-model.h>
7#include <ns3/nr-eesm-ir-t1.h>
8#include <ns3/nr-spectrum-value-helper.h>
9#include <ns3/ptr.h>
10#include <ns3/spectrum-value.h>
11#include <ns3/test.h>
12
13#include <cmath>
14#include <iostream>
15
28namespace ns3
29{
30
31class TestHarqTestCase : public TestCase
32{
33 public:
34 TestHarqTestCase(std::vector<std::vector<double>> rxSinrDb,
35 std::vector<double> refEffSinrPerRx,
36 uint16_t mcs,
37 uint16_t tbSize,
38 const std::string& name)
39 : TestCase(name),
40 m_rxSinrDb(rxSinrDb),
41 m_refEffSinrPerRx(refEffSinrPerRx),
42 m_mcs(mcs),
43 m_tbSize(tbSize)
44 {
45 }
46
47 private:
48 void DoRun() override;
49 void ValidateHarqForTwoRx();
50 NrErrorModel::NrErrorModelHistory GetTbDecodStats(std::vector<double> sinrRx,
52 std::string harqType) const;
53 std::vector<std::vector<double>> m_rxSinrDb;
55 std::vector<double> m_refEffSinrPerRx;
57 uint16_t m_mcs{0};
58 uint16_t m_tbSize{0};
59};
60
62TestHarqTestCase::GetTbDecodStats(std::vector<double> sinrRx,
64 std::string harqType) const
65{
66 uint8_t nRbsRx = sinrRx.size();
67
68 Ptr<const SpectrumModel> spectModelRx =
70 SpectrumValue sinrRxSpecVal(spectModelRx);
71
72 for (size_t i = 0; i < sinrRx.size(); i++)
73 {
74 sinrRxSpecVal[i] = pow(10.0, sinrRx.at(i) / 10.0);
75 }
76
77 std::vector<int> rbMap;
78 int rbIndex = 0;
79 for (uint8_t i = 0; i < sinrRx.size(); i++, rbIndex++)
80 {
81 rbMap.push_back(rbIndex);
82 }
83
84 Ptr<NrErrorModelOutput> output;
85 if (harqType == "IR")
86 {
87 Ptr<NrEesmIrT1> errorModelIr = CreateObject<NrEesmIrT1>();
88 output = errorModelIr->GetTbDecodificationStats(sinrRxSpecVal,
89 rbMap,
90 m_tbSize,
91 m_mcs,
92 harqHistory);
93 }
94 else if (harqType == "CC")
95 {
96 Ptr<NrEesmCcT1> errorModelCc = CreateObject<NrEesmCcT1>();
97 output = errorModelCc->GetTbDecodificationStats(sinrRxSpecVal,
98 rbMap,
99 m_tbSize,
100 m_mcs,
101 harqHistory);
102 }
103 else
104 {
105 NS_FATAL_ERROR("Unknown HARQ type. Use IR or CC");
106 }
107
109 history.push_back(output);
110 return history;
111}
112
113void
114TestHarqTestCase::ValidateHarqForTwoRx()
115{
116 std::vector<double> sinrRx1 = m_rxSinrDb.at(0);
117 std::vector<double> sinrRx2 = m_rxSinrDb.at(1);
119
120 // Incremental Redundancy
121 history = GetTbDecodStats(sinrRx1, history, "IR");
122 auto outputIr = history.at(0);
123 auto eesmOutputIr = DynamicCast<NrEesmErrorModelOutput>(outputIr);
124 double sinrEffIr = eesmOutputIr->m_sinrEff;
125
126 // std::cout << "sinrEff IR Rx1 = " << sinrEffIr << std::endl;
127 NS_TEST_ASSERT_MSG_EQ_TOL(sinrEffIr,
128 m_refEffSinrPerRx.at(0),
129 0.001,
130 "Resulted effective SINR of IR for RX 1 should be equal to the test "
131 "value with tol +-0.001");
132
133 history = GetTbDecodStats(sinrRx2, history, "IR");
134 outputIr = history.at(0);
135 eesmOutputIr = DynamicCast<NrEesmErrorModelOutput>(outputIr);
136 sinrEffIr = eesmOutputIr->m_sinrEff;
137
138 // std::cout << "sinrEff IR Rx2 = " << sinrEffIr << std::endl;
139 NS_TEST_ASSERT_MSG_EQ_TOL(sinrEffIr,
140 m_refEffSinrPerRx.at(1),
141 0.001,
142 "Resulted effective SINR of IR for RX 2 should be equal to the test "
143 "value with tol +-0.001");
144
145 history.clear();
146 // Chase Combining
147 history = GetTbDecodStats(sinrRx1, history, "CC");
148 auto outputCc = history.at(0);
149 auto eesmOutputCc = DynamicCast<NrEesmErrorModelOutput>(outputCc);
150 double sinrEffCc = eesmOutputCc->m_sinrEff;
151
152 // std::cout << "sinrEff CC Rx1 = " << sinrEffCc << std::endl;
153 NS_TEST_ASSERT_MSG_EQ_TOL(sinrEffCc,
154 m_refEffSinrPerRx.at(2),
155 0.001,
156 "Resulted effective SINR of CC for RX 1 should be equal to the test "
157 "value with tol +-0.001");
158
159 history = GetTbDecodStats(sinrRx2, history, "CC");
160 outputCc = history.at(0);
161 eesmOutputCc = DynamicCast<NrEesmErrorModelOutput>(outputCc);
162 sinrEffCc = eesmOutputCc->m_sinrEff;
163
164 // std::cout << "sinrEff CC Rx2 = " << sinrEffCc << std::endl;
165 NS_TEST_ASSERT_MSG_EQ_TOL(sinrEffCc,
166 m_refEffSinrPerRx.at(3),
167 0.001,
168 "Resulted effective SINR of CC for RX 2 should be equal to the test "
169 "value with tol +-0.001");
170}
171
172void
173TestHarqTestCase::DoRun()
174{
175 switch (m_rxSinrDb.size())
176 {
177 case 2:
178 ValidateHarqForTwoRx();
179 break;
180 default:
181 NS_FATAL_ERROR("Unsupported number of RX given to test HARQ");
182 }
183}
184
185class TestHarq : public TestSuite
186{
187 public:
188 TestHarq()
189 : TestSuite("nr-test-harq", Type::SYSTEM)
190 {
191 // test-1: 2 receptions
192 std::vector<std::vector<double>> rxSinrDb;
193 std::vector<double> sinrDbRx1 = {1.0, 3.5};
194 rxSinrDb.push_back(sinrDbRx1);
195 std::vector<double> sinrDbRx2 = {1.0, 1.5, 2.0, 2.5, 3.0, 3.5};
196 rxSinrDb.push_back(sinrDbRx2);
197 std::vector<double> refEffSinrPerRx;
198 // first the effective SINRs of the two receptions with IR
199 refEffSinrPerRx.push_back(1.67919); // After 1st RX
200 refEffSinrPerRx.push_back(1.67907); // After 2nd RX
201 // the last two are the effective SINRs of the two receptions with CC
202 refEffSinrPerRx.push_back(1.67919); // After 1st RX
203 refEffSinrPerRx.push_back(3.3318); // After 2nd RX
204 uint16_t mcs = 5;
205 uint16_t tbSize = 256;
206 AddTestCase(new TestHarqTestCase(rxSinrDb,
207 refEffSinrPerRx,
208 mcs,
209 tbSize,
210 "HARQ test with 2 receptions"),
211 Duration::QUICK);
212 }
213};
214
215static TestHarq testHarq;
216
217} // namespace ns3
std::vector< Ptr< NrErrorModelOutput > > NrErrorModelHistory
Vector of previous output.
static Ptr< const SpectrumModel > GetSpectrumModel(uint32_t numRbs, double centerFrequency, double subcarrierSpacing)
Creates or obtains from a global map a spectrum model with a given number of RBs, center frequency an...
static TestHarq testHarq
HARQ test.