7#define NS_LOG_APPEND_CONTEXT \
10 std::clog << " [ CellId " << GetCellId() << ", bwpId " << GetBwpId() << "] "; \
15#include "beam-manager.h"
16#include "nr-ch-access-manager.h"
17#include "nr-radio-bearer-tag.h"
18#include "nr-ue-net-device.h"
19#include "nr-ue-power-control.h"
21#include "ns3/boolean.h"
22#include "ns3/double.h"
26#include "ns3/pointer.h"
27#include "ns3/simulator.h"
35const Time NR_DEFAULT_PMI_INTERVAL_WB{MilliSeconds(10)};
36const Time NR_DEFAULT_PMI_INTERVAL_SB{MilliSeconds(2)};
38NS_LOG_COMPONENT_DEFINE(
"NrUePhy");
39NS_OBJECT_ENSURE_REGISTERED(NrUePhy);
43 NS_LOG_FUNCTION(
this);
44 m_wbCqiLast = Simulator::Now();
46 m_powerControl = CreateObject<NrUePowerControl>(
this);
47 m_isConnected =
false;
48 Simulator::Schedule(m_ueMeasurementsFilterPeriod, &NrUePhy::ReportUeMeasurements,
this);
53 NS_LOG_FUNCTION(
this);
59 NS_LOG_FUNCTION(
this);
60 delete m_ueCphySapProvider;
63 m_powerControl->Dispose();
64 m_powerControl =
nullptr;
78 TypeId(
"ns3::NrUePhy")
80 .AddConstructor<NrUePhy>()
81 .AddAttribute(
"TxPower",
82 "Transmission power in dBm",
85 MakeDoubleChecker<double>())
88 "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
89 " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
90 "\"the difference in decibels (dB) between"
91 " the noise output of the actual receiver to the noise output of an "
92 " ideal receiver with the same overall gain and bandwidth when the receivers "
93 " are connected to sources at the standard noise temperature T0.\" "
94 "In this model, we consider T0 = 290K.",
98 MakeDoubleChecker<double>())
100 "PowerAllocationType",
101 "Defines the type of the power allocation. Currently are supported "
102 "two types: \"UniformPowerAllocBw\", which is a uniform power allocation over all "
103 "bandwidth (over all RBs), and \"UniformPowerAllocBw\", which is a uniform "
104 "power allocation over used (active) RBs. By default is set a uniform power "
105 "allocation over used RBs .",
106 EnumValue(NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_USED),
107 MakeEnumAccessor<NrSpectrumValueHelper::PowerAllocationType>(
110 MakeEnumChecker(NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_BW,
111 "UniformPowerAllocBw",
112 NrSpectrumValueHelper::UNIFORM_POWER_ALLOCATION_USED,
113 "UniformPowerAllocUsed"))
114 .AddAttribute(
"SpectrumPhy",
115 "The SpectrumPhy associated to this NrPhy",
119 MakePointerChecker<NrSpectrumPhy>())
120 .AddAttribute(
"LBTThresholdForCtrl",
121 "After a DL/UL transmission, if we have less than this value to send the "
122 "UL CTRL, we consider the channel as granted",
123 TimeValue(MicroSeconds(25)),
124 MakeTimeAccessor(&NrUePhy::m_lbtThresholdForCtrl),
126 .AddAttribute(
"TbDecodeLatency",
127 "Transport block decode latency",
128 TimeValue(MicroSeconds(100)),
131 .AddAttribute(
"EnableUplinkPowerControl",
132 "If true, Uplink Power Control will be enabled.",
134 MakeBooleanAccessor(&NrUePhy::SetEnableUplinkPowerControl),
135 MakeBooleanChecker())
136 .AddAttribute(
"WbPmiUpdateInterval",
137 "Wideband PMI update interval",
138 TimeValue(NR_DEFAULT_PMI_INTERVAL_WB),
139 MakeTimeAccessor(&NrUePhy::m_wbPmiUpdateInterval),
141 .AddAttribute(
"SbPmiUpdateInterval",
142 "Subband PMI update interval",
143 TimeValue(NR_DEFAULT_PMI_INTERVAL_SB),
144 MakeTimeAccessor(&NrUePhy::m_sbPmiUpdateInterval),
146 .AddAttribute(
"AlphaCovMat",
147 "The alpha parameter for the calculation of the interference covariance "
148 "matrix moving average",
151 MakeDoubleChecker<double>(0.0, 1))
154 "CSI-IM duration in the number of OFDM symbols",
157 MakeUintegerChecker<uint8_t>(1, 12))
158 .AddTraceSource(
"DlDataSinr",
159 "DL DATA SINR statistics.",
160 MakeTraceSourceAccessor(&NrUePhy::m_dlDataSinrTrace),
161 "ns3::NrUePhy::DlDataSinrTracedCallback")
162 .AddTraceSource(
"DlCtrlSinr",
163 "Report the SINR computed for DL CTRL",
164 MakeTraceSourceAccessor(&NrUePhy::m_dlCtrlSinrTrace),
165 "ns3::NrUePhy::DlCtrlSinrTracedCallback")
166 .AddAttribute(
"UeMeasurementsFilterPeriod",
167 "Time period for reporting UE measurements, i.e., the"
168 "length of layer-1 filtering.",
169 TimeValue(MilliSeconds(200)),
170 MakeTimeAccessor(&NrUePhy::m_ueMeasurementsFilterPeriod),
172 .AddTraceSource(
"ReportUplinkTbSize",
173 "Report allocated uplink TB size for trace.",
174 MakeTraceSourceAccessor(&NrUePhy::m_reportUlTbSize),
175 "ns3::UlTbSize::TracedCallback")
176 .AddTraceSource(
"ReportDownlinkTbSize",
177 "Report allocated downlink TB size for trace.",
178 MakeTraceSourceAccessor(&NrUePhy::m_reportDlTbSize),
179 "ns3::DlTbSize::TracedCallback")
180 .AddTraceSource(
"ReportRsrp",
182 MakeTraceSourceAccessor(&NrUePhy::m_reportRsrpTrace),
183 "ns3::CurrentRsrp::TracedCallback")
184 .AddTraceSource(
"UePhyRxedCtrlMsgsTrace",
185 "Ue PHY Control Messages Traces.",
186 MakeTraceSourceAccessor(&NrUePhy::m_phyRxedCtrlMsgsTrace),
187 "ns3::NrPhyRxTrace::RxedUePhyCtrlMsgsTracedCallback")
188 .AddTraceSource(
"UePhyTxedCtrlMsgsTrace",
189 "Ue PHY Control Messages Traces.",
190 MakeTraceSourceAccessor(&NrUePhy::m_phyTxedCtrlMsgsTrace),
191 "ns3::NrPhyRxTrace::TxedUePhyCtrlMsgsTracedCallback")
192 .AddTraceSource(
"UePhyRxedDlDciTrace",
193 "Ue PHY DL DCI Traces.",
194 MakeTraceSourceAccessor(&NrUePhy::m_phyUeRxedDlDciTrace),
195 "ns3::NrPhyRxTrace::RxedUePhyDlDciTracedCallback")
196 .AddTraceSource(
"UePhyTxedHarqFeedbackTrace",
197 "Ue PHY DL HARQ Feedback Traces.",
198 MakeTraceSourceAccessor(&NrUePhy::m_phyUeTxedHarqFeedbackTrace),
199 "ns3::NrPhyRxTrace::TxedUePhyHarqFeedbackTracedCallback")
200 .AddTraceSource(
"ReportPowerSpectralDensity",
201 "Power Spectral Density data.",
202 MakeTraceSourceAccessor(&NrUePhy::m_reportPowerSpectralDensity),
203 "ns3::NrUePhy::PowerSpectralDensityTracedCallback")
204 .AddTraceSource(
"CqiFeedbackTrace",
205 "Mimo CQI feedback traces containing RNTI, WB CQI, MCS, and RI ",
206 MakeTraceSourceAccessor(&NrUePhy::m_cqiFeedbackTrace),
207 "ns3::NrUePhy::CqiFeedbackTracedCallback")
208 .AddTraceSource(
"ReportUeMeasurements",
209 "Report UE measurements RSRP (dBm) and RSRQ (dB).",
210 MakeTraceSourceAccessor(&NrUePhy::m_reportUeMeasurements),
211 "ns3::NrUePhy::RsrpRsrqTracedCallback")
212 .AddAttribute(
"EnableRlfDetection",
213 "If true, RLF detection will be enabled.",
215 MakeBooleanAccessor(&NrUePhy::m_enableRlfDetection),
216 MakeBooleanChecker());
221NrUePhy::ChannelAccessGranted([[maybe_unused]]
const Time& time)
223 NS_LOG_FUNCTION(
this);
225 m_channelStatus = GRANTED;
229NrUePhy::ChannelAccessDenied()
231 NS_LOG_FUNCTION(
this);
232 m_channelStatus = NONE;
238 NS_LOG_FUNCTION(
this);
245 NS_LOG_FUNCTION(
this);
246 return (m_ueCphySapProvider);
250NrUePhy::SetEnableUplinkPowerControl(
bool enable)
252 m_enableUplinkPowerControl = enable;
258 m_alphaCovMat = alpha;
264 return m_alphaCovMat;
270 m_csiImDuration = csiImDuration;
276 return m_csiImDuration;
283 m_powerControl->SetTxPower(pow);
301 NS_LOG_FUNCTION(
this);
302 return m_powerControl;
318 m_pmSearch->SetAmc(amc);
328 m_reportPowerSpectralDensity(m_currentSlot,
339NrUePhy::DoSendControlMessage(Ptr<NrControlMessage> msg)
341 NS_LOG_FUNCTION(
this << msg);
346NrUePhy::DoSendControlMessageNow(Ptr<NrControlMessage> msg)
348 NS_LOG_FUNCTION(
this << msg);
353NrUePhy::ProcessDataDci(
const SfnSf& ulSfnSf,
354 const std::shared_ptr<DciInfoElementTdma>& dciInfoElem)
356 NS_LOG_FUNCTION(
this);
358 NS_LOG_DEBUG(
"UE" << m_rnti <<
" UL-DCI received for slot " << ulSfnSf <<
" symStart "
359 <<
static_cast<uint32_t
>(dciInfoElem->m_symStart) <<
" numSym "
360 <<
static_cast<uint32_t
>(dciInfoElem->m_numSym) <<
" tbs "
361 << dciInfoElem->m_tbSize <<
" harqId "
362 <<
static_cast<uint32_t
>(dciInfoElem->m_harqProcess));
364 if (ulSfnSf == m_currentSlot)
366 InsertAllocation(dciInfoElem);
370 InsertFutureAllocation(ulSfnSf, dciInfoElem);
375NrUePhy::SendRachPreamble(uint32_t PreambleId, uint32_t Rnti)
377 NS_LOG_FUNCTION(
this << PreambleId);
379 Ptr<NrRachPreambleMessage> msg = Create<NrRachPreambleMessage>();
381 msg->SetRapId(PreambleId);
386NrUePhy::ProcessSrsDci(
const SfnSf& ulSfnSf,
const std::shared_ptr<DciInfoElementTdma>& dciInfoElem)
388 NS_LOG_FUNCTION(
this);
390 if (ulSfnSf == m_currentSlot)
392 InsertAllocation(dciInfoElem);
396 InsertFutureAllocation(ulSfnSf, dciInfoElem);
403 NS_LOG_FUNCTION(
this);
412 m_ulCtrlSyms = ulCtrlSyms;
418 m_dlCtrlSyms = dlCtrlSyms;
424 m_numRbPerRbg = numRbPerRbg;
430 NS_LOG_FUNCTION(
this);
432 static std::unordered_map<std::string, LteNrTddSlotType> lookupTable = {
439 std::vector<LteNrTddSlotType> vector;
440 std::stringstream ss(pattern);
442 std::vector<std::string> extracted;
444 while (std::getline(ss, token,
'|'))
446 extracted.push_back(token);
449 vector.reserve(extracted.size());
450 for (
const auto& v : extracted)
452 vector.push_back(lookupTable[v]);
458 if (
static_cast<size_t>(ulSlots) ==
m_tddPattern.size())
461 m_csiFeedbackType = 0;
468 return m_numRbPerRbg;
474 m_currentSlot = currentSfnSf;
480 m_lastSlotStart = startTime;
486 return m_lastSlotStart;
496NrUePhy::ComputeAvgSinr(
const SpectrumValue& sinr)
501 Values::const_iterator it;
503 for (it = sinr.ConstValuesBegin(); it != sinr.ConstValuesEnd(); it++)
509 double avrgSinr = (rbNum > 0) ? (sum / rbNum) : DBL_MAX;
515NrUePhy::InsertAllocation(
const std::shared_ptr<DciInfoElementTdma>& dci)
517 NS_LOG_FUNCTION(
this);
519 VarTtiAllocInfo varTtiInfo(dci);
526NrUePhy::InsertFutureAllocation(
const SfnSf& sfnSf,
const std::shared_ptr<DciInfoElementTdma>& dci)
528 NS_LOG_FUNCTION(
this);
530 VarTtiAllocInfo varTtiInfo(dci);
534 ulSlot.m_varTtiAllocInfo.push_back(varTtiInfo);
535 std::stable_sort(ulSlot.m_varTtiAllocInfo.begin(), ulSlot.m_varTtiAllocInfo.end());
539 SlotAllocInfo slotAllocInfo = SlotAllocInfo(sfnSf);
540 slotAllocInfo.m_varTtiAllocInfo.push_back(varTtiInfo);
548 NS_LOG_FUNCTION(
this);
552 auto dciMsg = DynamicCast<NrDlDciMessage>(msg);
553 auto dciInfoElem = dciMsg->GetDciInfoElement();
557 if (dciInfoElem->m_rnti != 0 && dciInfoElem->m_rnti != m_rnti)
562 SfnSf dciSfn = m_currentSlot;
563 uint32_t k0Delay = dciMsg->GetKDelay();
566 NS_LOG_DEBUG(
"UE" << m_rnti <<
" DL-DCI received for slot " << dciSfn <<
" symStart "
567 <<
static_cast<uint32_t
>(dciInfoElem->m_symStart) <<
" numSym "
568 <<
static_cast<uint32_t
>(dciInfoElem->m_numSym) <<
" tbs "
569 << dciInfoElem->m_tbSize <<
" harqId "
570 <<
static_cast<uint32_t
>(dciInfoElem->m_harqProcess));
574 auto it = m_harqIdToK1Map.find(dciInfoElem->m_harqProcess);
575 if (it != m_harqIdToK1Map.end())
577 m_harqIdToK1Map.erase(m_harqIdToK1Map.find(dciInfoElem->m_harqProcess));
580 m_harqIdToK1Map.insert(std::make_pair(dciInfoElem->m_harqProcess, dciMsg->GetK1Delay()));
582 m_phyUeRxedDlDciTrace(m_currentSlot,
586 dciInfoElem->m_harqProcess,
587 dciMsg->GetK1Delay());
589 InsertAllocation(dciInfoElem);
593 if (m_enableUplinkPowerControl)
595 m_powerControl->ReportTpcPusch(dciInfoElem->m_tpc);
596 m_powerControl->ReportTpcPucch(dciInfoElem->m_tpc);
601 auto dciMsg = DynamicCast<NrUlDciMessage>(msg);
602 auto dciInfoElem = dciMsg->GetDciInfoElement();
606 if (dciInfoElem->m_rnti != 0 && dciInfoElem->m_rnti != m_rnti)
611 SfnSf ulSfnSf = m_currentSlot;
612 uint32_t k2Delay = dciMsg->GetKDelay();
613 ulSfnSf.
Add(k2Delay);
617 ProcessDataDci(ulSfnSf, dciInfoElem);
622 ProcessSrsDci(ulSfnSf, dciInfoElem);
628 NS_LOG_DEBUG(
"received MIB");
629 Ptr<NrMibMessage> msg2 = DynamicCast<NrMibMessage>(msg);
635 Ptr<NrSib1Message> msg2 = DynamicCast<NrSib1Message>(msg);
641 Ptr<NrRarMessage> rarMsg = DynamicCast<NrRarMessage>(msg);
647 NS_LOG_INFO(
"Message type not recognized " << msg->GetMessageType());
654NrUePhy::ProcessRar(
const Ptr<NrRarMessage>& rarMsg)
656 NS_LOG_FUNCTION(
this);
659 for (
auto it = rarMsg->RarListBegin(); it != rarMsg->RarListEnd(); ++it)
661 NS_LOG_INFO(
"Received RAR in slot" << m_currentSlot <<
" with RA preamble ID: "
662 << std::to_string(it->rarPayload.raPreambleId));
665 NS_LOG_INFO(
"Received RAR with RA preamble ID:" << +it->rarPayload.raPreambleId
666 <<
" current RA preamble ID is :"
669 SfnSf ulSfnSf = m_currentSlot;
670 uint32_t k2Delay = it->rarPayload.k2Delay;
671 ulSfnSf.
Add(k2Delay);
672 NS_LOG_DEBUG(
"Insert RAR UL DCI allocation for " << ulSfnSf);
673 ProcessDataDci(ulSfnSf, (*it).rarPayload.ulMsg3Dci);
685 NS_LOG_DEBUG(
"Skipping RAR, does not contain preamble ID."
686 <<
"\n My preamble id: " << std::to_string(
m_raPreambleId) <<
" found:");
687 for (
auto it = rarMsg->RarListBegin(); it != rarMsg->RarListEnd(); ++it)
689 NS_LOG_DEBUG(
"rapId: " << std::to_string(it->rapId));
696NrUePhy::TryToPerformLbt()
698 NS_LOG_FUNCTION(
this);
699 uint8_t ulCtrlSymStart = 0;
700 uint8_t ulCtrlNumSym = 0;
707 ulCtrlSymStart = alloc.m_dci->m_symStart;
708 ulCtrlNumSym = alloc.m_dci->m_numSym;
713 if (ulCtrlNumSym != 0)
721 m_lbtThresholdForCtrl;
726 int64_t dciEndsAt = m_lastSlotStart.GetMicroSeconds() +
727 ((alloc.m_dci->m_numSym + alloc.m_dci->m_symStart) * symbolPeriod);
735 if (limit.GetMicroSeconds() < dciEndsAt)
737 NS_LOG_INFO(
"This data DCI ends at "
738 << MicroSeconds(dciEndsAt)
739 <<
" which is inside the LBT shared COT (the limit is " << limit
740 <<
"). No need for LBT");
743 m_channelStatus = GRANTED;
747 NS_LOG_INFO(
"This data DCI starts at "
748 << +alloc.m_dci->m_symStart <<
" for " << +alloc.m_dci->m_numSym
749 <<
" ends at " << MicroSeconds(dciEndsAt)
750 <<
" which is outside the LBT shared COT (the limit is " << limit
754 if (m_channelStatus != GRANTED)
756 Time sched = m_lastSlotStart - Simulator::Now() + (
GetSymbolPeriod() * ulCtrlSymStart) -
758 NS_LOG_DEBUG(
"Scheduling an LBT for sending the UL CTRL at "
759 << Simulator::Now() + sched);
761 m_lbtEvent = Simulator::Schedule(sched, &NrUePhy::RequestAccess,
this);
765 NS_LOG_DEBUG(
"Not scheduling LBT: the UE has a channel status that is GRANTED");
770 NS_LOG_DEBUG(
"Not scheduling LBT; the UE has no UL CTRL symbols available");
775NrUePhy::RequestAccess()
777 NS_LOG_FUNCTION(
this);
778 NS_LOG_DEBUG(
"Request access because we have to transmit UL CTRL");
779 m_cam->RequestAccess();
784NrUePhy::PushCtrlAllocations(
const SfnSf currentSfnSf)
786 NS_LOG_FUNCTION(
this);
790 std::vector<bool> rbgBitmask(
GetRbNum(),
true);
795 NS_LOG_INFO(
"TDD Pattern unknown, insert DL CTRL at the beginning of the slot");
796 VarTtiAllocInfo dlCtrlSlot(std::make_shared<DciInfoElementTdma>(0,
805 uint64_t currentSlotN = currentSfnSf.Normalize() %
m_tddPattern.size();
809 NS_LOG_DEBUG(
"The current TDD pattern indicates that we are in a "
811 <<
" slot, so insert DL CTRL at the beginning of the slot");
812 VarTtiAllocInfo dlCtrlSlot(std::make_shared<DciInfoElementTdma>(0,
821 NS_LOG_DEBUG(
"The current TDD pattern indicates that we are in a "
823 <<
" slot, so insert UL CTRL at the end of the slot");
824 VarTtiAllocInfo ulCtrlSlot(
835NrUePhy::StartSlot(
const SfnSf& s)
837 NS_LOG_FUNCTION(
this);
839 m_lastSlotStart = Simulator::Now();
853 NS_LOG_FUNCTION(
this << s);
854 if (nrAllocationExists)
863 PushCtrlAllocations(m_currentSlot);
867 <<
" composed by the following allocations, total "
871 std::string direction;
883 switch (alloc.m_dci->m_type)
887 NS_LOG_DEBUG(
"Allocation from sym "
888 <<
static_cast<uint32_t
>(alloc.m_dci->m_symStart) <<
" to sym "
889 <<
static_cast<uint32_t
>(alloc.m_dci->m_numSym + alloc.m_dci->m_symStart)
890 <<
" direction " << direction <<
" type " << type);
894 NS_LOG_INFO(
"Allocation from sym "
895 <<
static_cast<uint32_t
>(alloc.m_dci->m_symStart) <<
" to sym "
896 <<
static_cast<uint32_t
>(alloc.m_dci->m_numSym + alloc.m_dci->m_symStart)
897 <<
" direction " << direction <<
" type " << type);
901 NS_LOG_DEBUG(
"Allocation from sym "
902 <<
static_cast<uint32_t
>(alloc.m_dci->m_symStart) <<
" to sym "
903 <<
static_cast<uint32_t
>(alloc.m_dci->m_numSym + alloc.m_dci->m_symStart)
904 <<
" direction " << direction <<
" type " << type);
908 NS_LOG_DEBUG(
"Allocation from sym "
909 <<
static_cast<uint32_t
>(alloc.m_dci->m_symStart) <<
" to sym "
910 <<
static_cast<uint32_t
>(alloc.m_dci->m_numSym + alloc.m_dci->m_symStart)
911 <<
" direction " << direction <<
" type " << type);
914 NS_LOG_ERROR(
"Unknown type DciInfoElementTdma::VarTtiType " << alloc.m_dci->m_type);
923 auto nextVarTtiStart =
GetSymbolPeriod() * allocation.m_dci->m_symStart;
933 for (
const auto& msg : ctrlMsgs)
939 Simulator::Schedule(nextVarTtiStart, &NrUePhy::StartVarTti,
this, allocation.m_dci);
943NrUePhy::DlCtrl(
const std::shared_ptr<DciInfoElementTdma>& dci)
945 NS_LOG_FUNCTION(
this);
949 NS_LOG_DEBUG(
"UE" << m_rnti
950 <<
" RXing DL CTRL frame for"
952 << +dci->m_symStart <<
"-" << +(dci->m_symStart + dci->m_numSym - 1)
953 <<
"\t start " << Simulator::Now() <<
" end "
954 << (Simulator::Now() + varTtiDuration));
956 m_tryToPerformLbt =
true;
958 m_spectrumPhy->AddExpectedDlCtrlEnd(Simulator::Now() + varTtiDuration);
960 return varTtiDuration;
964NrUePhy::UlSrs(
const std::shared_ptr<DciInfoElementTdma>& dci)
966 NS_LOG_FUNCTION(
this);
968 std::vector<int> channelRbs;
969 for (uint32_t i = 0; i <
GetRbNum(); i++)
971 channelRbs.push_back(
static_cast<int>(i));
975 std::list<Ptr<NrControlMessage>> srsMsg;
976 Ptr<NrSrsMessage> srs = Create<NrSrsMessage>();
978 srsMsg.emplace_back(srs);
981 m_phyTxedCtrlMsgsTrace(m_currentSlot,
GetCellId(), dci->m_rnti,
GetBwpId(), *srsMsg.begin());
982 m_spectrumPhy->StartTxUlControlFrames(srsMsg, varTtiDuration - NanoSeconds(1.0));
984 NS_LOG_DEBUG(
"UE" << m_rnti <<
" TXing UL SRS frame for symbols " << +dci->m_symStart <<
"-"
985 << +(dci->m_symStart + dci->m_numSym - 1) <<
"\t start " << Simulator::Now()
986 <<
" end " << (Simulator::Now() + varTtiDuration - NanoSeconds(1.0)));
988 ChannelAccessDenied();
989 return varTtiDuration;
993NrUePhy::UlCtrl(
const std::shared_ptr<DciInfoElementTdma>& dci)
995 NS_LOG_FUNCTION(
this);
1001 NS_LOG_DEBUG(
"UE" << m_rnti <<
" reserved space for UL CTRL frame for symbols "
1002 << +dci->m_symStart <<
"-" << +(dci->m_symStart + dci->m_numSym - 1)
1003 <<
"\t start " << Simulator::Now() <<
" end "
1004 << (Simulator::Now() + varTtiDuration - NanoSeconds(1.0))
1005 <<
" but no data to transmit");
1007 return varTtiDuration;
1009 else if (m_channelStatus != GRANTED)
1011 NS_LOG_INFO(
"UE" << m_rnti <<
" has to transmit CTRL but channel not granted");
1013 return varTtiDuration;
1018 m_phyTxedCtrlMsgsTrace(m_currentSlot,
GetCellId(), dci->m_rnti,
GetBwpId(), msg);
1022 Ptr<NrDlHarqFeedbackMessage> harqMsg = DynamicCast<NrDlHarqFeedbackMessage>(msg);
1023 uint8_t harqId = harqMsg->GetDlHarqFeedback().m_harqProcessId;
1025 auto it = m_harqIdToK1Map.find(harqId);
1026 if (it != m_harqIdToK1Map.end())
1028 m_phyUeTxedHarqFeedbackTrace(m_currentSlot,
1032 static_cast<uint32_t
>(harqId),
1038 std::vector<int> channelRbs;
1039 for (uint32_t i = 0; i <
GetRbNum(); i++)
1041 channelRbs.push_back(
static_cast<int>(i));
1044 if (m_enableUplinkPowerControl)
1046 m_txPower = m_powerControl->GetPucchTxPower(channelRbs.size());
1050 NS_LOG_DEBUG(
"UE" << m_rnti <<
" TXing UL CTRL frame for symbols " << +dci->m_symStart <<
"-"
1051 << +(dci->m_symStart + dci->m_numSym - 1) <<
"\t start " << Simulator::Now()
1052 <<
" end " << (Simulator::Now() + varTtiDuration - NanoSeconds(1.0)));
1054 SendCtrlChannels(varTtiDuration - NanoSeconds(1.0));
1056 ChannelAccessDenied();
1057 return varTtiDuration;
1061NrUePhy::DlData(
const std::shared_ptr<DciInfoElementTdma>& dci)
1063 NS_LOG_FUNCTION(
this);
1065 m_receptionEnabled =
true;
1067 NS_ASSERT(dci->m_rnti == m_rnti);
1080 m_reportDlTbSize(
m_netDevice->GetObject<NrUeNetDevice>()->GetImsi(), dci->m_tbSize);
1081 NS_LOG_INFO(
"UE" << m_rnti <<
" RXing DL DATA frame for symbols " << +dci->m_symStart <<
"-"
1082 << +(dci->m_symStart + dci->m_numSym - 1) <<
" num of rbg assigned: "
1084 <<
". RX will take place for " << varTtiDuration);
1086 return varTtiDuration;
1090NrUePhy::UlData(
const std::shared_ptr<DciInfoElementTdma>& dci)
1092 NS_LOG_FUNCTION(
this);
1093 if (m_enableUplinkPowerControl)
1095 m_txPower = m_powerControl->GetPuschTxPower(
1100 std::list<Ptr<NrControlMessage>> ctrlMsg;
1101 Ptr<PacketBurst> pktBurst =
GetPacketBurst(m_currentSlot, dci->m_symStart, dci->m_rnti);
1102 if (pktBurst && pktBurst->GetNPackets() > 0)
1104 std::list<Ptr<Packet>> pkts = pktBurst->GetPackets();
1105 NrRadioBearerTag bearerTag;
1106 if (!pkts.front()->PeekPacketTag(bearerTag))
1108 NS_FATAL_ERROR(
"No radio bearer tag");
1117 NS_FATAL_ERROR(
"The UE " << dci->m_rnti <<
" has been scheduled without data");
1121 NS_LOG_WARN(
"Not sending MSG3. Probably in RRC IDEAL mode.");
1122 return varTtiDuration;
1125 m_reportUlTbSize(
m_netDevice->GetObject<NrUeNetDevice>()->GetImsi(), dci->m_tbSize);
1127 NS_LOG_DEBUG(
"UE" << m_rnti <<
" TXing UL DATA frame for"
1128 <<
" symbols " << +dci->m_symStart <<
"-"
1129 << +(dci->m_symStart + dci->m_numSym - 1) <<
"\t start " << Simulator::Now()
1130 <<
" end " << (Simulator::Now() + varTtiDuration));
1132 Simulator::Schedule(NanoSeconds(1.0),
1133 &NrUePhy::SendDataChannels,
1138 varTtiDuration - NanoSeconds(2.0));
1139 return varTtiDuration;
1143NrUePhy::StartVarTti(
const std::shared_ptr<DciInfoElementTdma>& dci)
1145 NS_LOG_FUNCTION(
this);
1146 Time varTtiDuration;
1148 m_currTbs = dci->m_tbSize;
1149 m_receptionEnabled =
false;
1153 varTtiDuration = DlCtrl(dci);
1157 varTtiDuration = UlCtrl(dci);
1161 varTtiDuration = UlSrs(dci);
1165 varTtiDuration = DlData(dci);
1170 varTtiDuration = UlData(dci);
1173 Simulator::Schedule(varTtiDuration, &NrUePhy::EndVarTti,
this, dci);
1177NrUePhy::EndVarTti(
const std::shared_ptr<DciInfoElementTdma>& dci)
1179 NS_LOG_FUNCTION(
this);
1180 NS_LOG_DEBUG(
"DCI started at symbol "
1181 <<
static_cast<uint32_t
>(dci->m_symStart) <<
" which lasted for "
1182 <<
static_cast<uint32_t
>(dci->m_numSym) <<
" symbols finished");
1184 if (m_tryToPerformLbt)
1187 m_tryToPerformLbt =
false;
1193 m_currentSlot.
Add(1);
1195 Simulator::Schedule(m_lastSlotStart +
GetSlotPeriod() - Simulator::Now(),
1196 &NrUePhy::StartSlot,
1205 Time nextVarTtiStart =
GetSymbolPeriod() * allocation.m_dci->m_symStart;
1207 Simulator::Schedule(nextVarTtiStart + m_lastSlotStart - Simulator::Now(),
1208 &NrUePhy::StartVarTti,
1213 m_receptionEnabled =
false;
1219 Simulator::ScheduleWithContext(
m_netDevice->GetNode()->GetId(),
1228NrUePhy::SendDataChannels(
const Ptr<PacketBurst>& pb,
1229 const std::list<Ptr<NrControlMessage>>& ctrlMsg,
1230 const std::shared_ptr<DciInfoElementTdma>& dci,
1231 const Time& duration)
1233 if (pb->GetNPackets() > 0)
1236 if (!pb->GetPackets().front()->PeekPacketTag(tag))
1238 NS_FATAL_ERROR(
"No radio bearer tag");
1242 m_spectrumPhy->StartTxDataFrames(pb, ctrlMsg, dci, duration);
1246NrUePhy::SendCtrlChannels(Time duration)
1253NrUePhy::CreateDlCqiFeedbackMessage(
const SpectrumValue& sinr)
1255 NS_LOG_FUNCTION(
this);
1257 Ptr<NrDlCqiMessage> msg = Create<NrDlCqiMessage>();
1261 dlcqi.m_rnti = m_rnti;
1264 std::vector<int> cqi;
1265 dlcqi.m_wbCqi = m_amc->CreateCqiFeedbackSiso(sinr, dlcqi.m_mcs);
1266 msg->SetDlCqi(dlcqi);
1268 m_cqiFeedbackTrace(m_rnti, dlcqi.m_wbCqi, dlcqi.m_mcs, 1);
1275 NS_LOG_FUNCTION(
this);
1277 if (m_ulConfigured && (m_rnti > 0) && m_receptionEnabled)
1281 if (Simulator::Now() > m_wbCqiLast)
1283 Ptr<NrDlCqiMessage> msg = CreateDlCqiFeedbackMessage(sinr);
1287 DoSendControlMessage(msg);
1296 NS_LOG_FUNCTION(
this);
1298 Ptr<NrDlHarqFeedbackMessage> msg = Create<NrDlHarqFeedbackMessage>();
1300 msg->SetDlHarqFeedback(m);
1304 NS_LOG_DEBUG(
"ReceiveNrDlHarqFeedback"
1305 <<
" Harq Process " <<
static_cast<uint32_t
>(k1It->first)
1306 <<
" K1: " << k1It->second <<
" Frame " << m_currentSlot);
1308 Time
event = m_lastSlotStart + (
GetSlotPeriod() * k1It->second);
1309 if (event <= Simulator::Now())
1311 Simulator::ScheduleNow(&NrUePhy::DoSendControlMessageNow,
this, msg);
1315 Simulator::Schedule(event - Simulator::Now(), &NrUePhy::DoSendControlMessageNow,
this, msg);
1322 NS_LOG_FUNCTION(
this);
1323 NS_ASSERT(cam !=
nullptr);
1325 m_cam->SetAccessGrantedCallback(
1326 std::bind(&NrUePhy::ChannelAccessGranted,
this, std::placeholders::_1));
1327 m_cam->SetAccessDeniedCallback(std::bind(&NrUePhy::ChannelAccessDenied,
this));
1333 return m_currentSlot;
1345 NS_LOG_FUNCTION(
this);
1347 m_isConnected =
false;
1351NrUePhy::DoStartCellSearch(uint16_t dlEarfcn)
1353 NS_LOG_FUNCTION(
this << dlEarfcn);
1354 DoSetInitialBandwidth();
1358NrUePhy::DoSynchronizeWithGnb(uint16_t cellId, uint16_t dlEarfcn)
1360 NS_LOG_FUNCTION(
this << cellId << dlEarfcn);
1361 DoSynchronizeWithGnb(cellId);
1365NrUePhy::DoSetPa(
double pa)
1367 NS_LOG_FUNCTION(
this << pa);
1371NrUePhy::DoSetRsrpFilterCoefficient(uint8_t rsrpFilterCoefficient)
1373 NS_LOG_FUNCTION(
this << +rsrpFilterCoefficient);
1377NrUePhy::DoSynchronizeWithGnb(uint16_t cellId)
1379 NS_LOG_FUNCTION(
this << cellId);
1381 DoSetInitialBandwidth();
1387 NS_LOG_FUNCTION(
this);
1389 NS_FATAL_ERROR(
"ERROR");
1395 NS_LOG_FUNCTION(
this);
1396 Simulator::ScheduleWithContext(nodeId,
1398 &NrUePhy::StartEventLoop,
1408 NS_LOG_FUNCTION(
this << rsReceivedPower);
1409 m_rsrp = 10 * log10(Integral(rsReceivedPower)) + 30;
1410 NS_LOG_DEBUG(
"RSRP value updated: " << m_rsrp <<
" dBm");
1412 if (m_enableUplinkPowerControl)
1414 m_powerControl->SetLoggingInfo(
GetCellId(), m_rnti);
1415 m_powerControl->SetRsrp(m_rsrp);
1422 NS_LOG_FUNCTION(
this);
1427 uint32_t subcarrierSpacing;
1428 subcarrierSpacing = 15000 *
static_cast<uint32_t
>(std::pow(2,
GetNumerology()));
1430 Values::const_iterator itPi;
1431 for (itPi = p->ConstValuesBegin(); itPi != p->ConstValuesEnd(); itPi++)
1434 double powerTxW = (*itPi) * subcarrierSpacing;
1440 double rsrp = 10 * log10(1000 * (sum /
static_cast<double>(nRB)));
1442 NS_LOG_DEBUG(
"RSRP value updated: " << rsrp <<
" dBm"
1443 <<
" for Cell Id: " << cellId <<
" RNTI: " << m_rnti);
1446 std::map<uint16_t, UeMeasurementsElement>::iterator itMeasMap =
1447 m_ueMeasurementsMap.find(cellId);
1448 if (itMeasMap == m_ueMeasurementsMap.end())
1451 UeMeasurementsElement newEl;
1452 newEl.rsrpSum = rsrp;
1457 NS_LOG_DEBUG(
"New RSRP entry for Cell Id: " << cellId <<
" RNTI: " << m_rnti
1458 <<
" RSRP: " << newEl.rsrpSum <<
" dBm"
1459 <<
" number of entries: " << +newEl.rsrpNum);
1461 m_ueMeasurementsMap.insert(std::pair<uint16_t, UeMeasurementsElement>(cellId, newEl));
1465 (*itMeasMap).second.rsrpSum += rsrp;
1466 (*itMeasMap).second.rsrpNum++;
1468 NS_LOG_DEBUG(
"Update RSRP entry for Cell Id: "
1469 << cellId <<
" RNTI: " << m_rnti
1470 <<
" RSRP Sum: " << (*itMeasMap).second.rsrpSum <<
" dBm"
1471 <<
" number of entries: " << +((*itMeasMap).second.rsrpNum));
1476NrUePhy::ReportUeMeasurements()
1478 NS_LOG_FUNCTION(
this);
1482 std::map<uint16_t, UeMeasurementsElement>::iterator it;
1483 for (it = m_ueMeasurementsMap.begin(); it != m_ueMeasurementsMap.end(); it++)
1486 double avg_rsrq = 0;
1487 if ((*it).second.rsrpNum != 0)
1489 avg_rsrp = (*it).second.rsrpSum /
static_cast<double>((*it).second.rsrpNum);
1493 NS_LOG_WARN(
" RSRP nSamples is zero!");
1497 NS_LOG_DEBUG(
" Report UE Measurements for CellId "
1498 << (*it).first <<
" Reporting UE " << m_rnti <<
" Av. RSRP " << avg_rsrp
1499 <<
" (nSamples " << +((*it).second.rsrpNum) <<
")"
1506 if (m_isConnected && m_enableRlfDetection)
1508 double avrgSinrForRlf = ComputeAvgSinr(m_ctrlSinrForRlf);
1509 RlfDetection(10 * log10(avrgSinrForRlf));
1512 NrUeCphySapUser::UeMeasurementsElement newEl;
1513 newEl.m_cellId = (*it).first;
1514 newEl.m_rsrp = avg_rsrp;
1515 newEl.m_rsrq = avg_rsrq;
1519 m_reportUeMeasurements(m_rnti,
1530 m_ueMeasurementsMap.clear();
1531 Simulator::Schedule(m_ueMeasurementsFilterPeriod, &NrUePhy::ReportUeMeasurements,
this);
1535NrUePhy::SetCsiFeedbackType(uint8_t csiFeedbackType)
1537 m_csiFeedbackType = csiFeedbackType;
1543 NS_LOG_FUNCTION(
this);
1544 uint32_t rbUsed = 0;
1545 double sinrSum = 0.0;
1547 for (uint32_t i = 0; i < sinr.GetValuesN(); i++)
1549 double currentSinr = sinr.ValuesAt(i);
1550 if (currentSinr != 0)
1553 sinrSum += currentSinr;
1564 NS_LOG_FUNCTION(
this);
1566 uint8_t wbCqi = m_amc->CreateCqiFeedbackSiso(sinr, mcs);
1571NrUePhy::StartEventLoop(uint16_t frame, uint8_t subframe, uint16_t slot)
1573 NS_LOG_FUNCTION(
this);
1577 NS_LOG_INFO(
"Initial bandwidth not set, configuring the default one for Cell ID: "
1581 NS_LOG_INFO(
"No numerology was set, assuming numerology 0 for Cell ID: "
1585 DoSetInitialBandwidth();
1588 NS_LOG_INFO(
"PHY starting. Configuration: "
1590 <<
"\t TxPower: " <<
m_txPower <<
" dBm" << std::endl
1597 <<
"Attached to physical channel: " << std::endl
1602 StartSlot(startSlot);
1606NrUePhy::DoSetInitialBandwidth()
1608 NS_LOG_FUNCTION(
this);
1610 double initialBandwidthHz =
1613 uint16_t initialBandwidthIn100KHz = ceil(initialBandwidthHz / (100 * 1000));
1615 uint16_t initialBandwidthWithOverhead = initialBandwidthIn100KHz / (1 -
GetRbOverhead());
1617 NS_ABORT_MSG_IF(initialBandwidthWithOverhead == 0,
1618 " Initial bandwidth could not be set. Parameters provided are: "
1619 "\n dlBandwidthInRBNum = "
1621 <<
"\n NrSpectrumValueHelper::SUBCARRIERS_PER_RB = "
1625 DoSetDlBandwidth(initialBandwidthWithOverhead);
1629NrUePhy::DoGetCellId()
const
1635NrUePhy::DoGetDlEarfcn()
1639 NS_LOG_FUNCTION(
this);
1640 NS_LOG_WARN(
"DoGetDlEarfcn function is called. This function should be removed in future once "
1641 "NR has its own RRC.");
1646NrUePhy::DoSetDlBandwidth(uint16_t dlBandwidth)
1648 NS_LOG_FUNCTION(
this << +dlBandwidth);
1652 NS_LOG_DEBUG(
"PHY reconfiguring. Result: "
1654 <<
"\t TxPower: " <<
m_txPower <<
" dBm" << std::endl
1661 <<
"Attached to physical channel: " << std::endl
1668NrUePhy::DoConfigureUplink(uint16_t ulEarfcn, uint8_t ulBandwidth)
1670 NS_LOG_FUNCTION(
this << ulEarfcn << +ulBandwidth);
1672 m_ulConfigured =
true;
1676NrUePhy::DoConfigureReferenceSignalPower(int8_t referenceSignalPower)
1678 NS_LOG_FUNCTION(
this << referenceSignalPower);
1679 m_powerControl->ConfigureReferenceSignalPower(referenceSignalPower);
1683NrUePhy::DoSetRnti(uint16_t rnti)
1685 NS_LOG_FUNCTION(
this << rnti);
1691NrUePhy::DoSetTransmissionMode(uint8_t txMode)
1693 NS_LOG_FUNCTION(
this << +txMode);
1697NrUePhy::DoSetSrsConfigurationIndex(uint16_t srcCi)
1699 NS_LOG_FUNCTION(
this << srcCi);
1709NrUePhy::DoNotifyConnectionSuccessful()
1718 m_isConnected =
true;
1720 InitializeRlfParams();
1725NrUePhy::DoResetPhyAfterRlf()
1727 NS_LOG_FUNCTION(
this);
1733NrUePhy::DoResetRlfParams()
1735 NS_LOG_FUNCTION(
this);
1736 InitializeRlfParams();
1740NrUePhy::DoStartInSyncDetection()
1742 NS_LOG_FUNCTION(
this);
1744 m_downlinkInSync =
false;
1748NrUePhy::InitializeRlfParams()
1750 NS_LOG_FUNCTION(
this);
1751 m_numOfSubframes = 0;
1754 m_downlinkInSync =
true;
1758NrUePhy::RlfDetection(
double sinrDb)
1760 NS_LOG_FUNCTION(
this << sinrDb);
1761 m_sinrDbFrame += sinrDb;
1763 NS_LOG_LOGIC(
"No of Subframes: " << m_numOfSubframes
1764 <<
" UE synchronized: " << m_downlinkInSync);
1767 if (m_downlinkInSync && m_numOfSubframes == 10)
1773 if ((m_sinrDbFrame / m_numOfSubframes) < m_qOut)
1776 NS_LOG_LOGIC(
"No of Frames which cannot be decoded: " << m_numOfFrames);
1785 NS_LOG_INFO(
"Resetting frame counter at phy. Current value = " << m_numOfFrames);
1790 m_numOfSubframes = 0;
1798 if (m_downlinkInSync && (m_numOfFrames * 10) == m_numOfQoutEvalSf)
1800 NS_LOG_LOGIC(
"At " << Simulator::Now().As(Time::MS)
1801 <<
" ms UE PHY sending out of sync indication to UE RRC layer");
1807 if (!m_downlinkInSync && m_numOfSubframes == 10)
1814 if ((m_sinrDbFrame / m_numOfSubframes) > m_qIn)
1817 NS_LOG_LOGIC(
"No of Frames successfully decoded: " << m_numOfFrames);
1830 m_numOfSubframes = 0;
1837 if (!m_downlinkInSync && (m_numOfFrames * 10) == m_numOfQinEvalSf)
1839 NS_LOG_LOGIC(
"At " << Simulator::Now().As(Time::MS)
1840 <<
" ms UE PHY sending in sync indication to UE RRC layer");
1847NrUePhy::DoSetImsi(uint64_t imsi)
1849 NS_LOG_FUNCTION(
this);
1857 NS_LOG_FUNCTION(
this);
1859 if (!m_ulConfigured || (m_rnti == 0))
1866 auto cqi = m_pmSearch->CreateCqiFeedbackMimo(rxSignal, pmiUpdateParams);
1870 .m_cqiType = cqi.m_cqiType,
1871 .m_wbCqi = cqi.m_wbCqi,
1872 .m_wbPmi = cqi.m_wbPmi,
1873 .m_sbCqis = cqi.m_sbCqis,
1874 .m_sbPmis = cqi.m_sbPmis,
1876 .m_optPrecMat = cqi.m_optPrecMat,
1879 m_cqiFeedbackTrace(m_rnti, cqi.m_wbCqi, cqi.m_mcs, cqi.m_rank);
1881 auto msg = Create<NrDlCqiMessage>();
1883 msg->SetDlCqi(dlcqi);
1885 DoSendControlMessage(msg);
1891 return m_csiFeedbackType;
1897 NS_LOG_FUNCTION(
this);
1898 NS_ASSERT(csiRsMimoSignal.size() == 1);
1900 m_lastCsiRsMimoSignalTime = Simulator::Now();
1906 NS_LOG_FUNCTION(
this);
1907 NS_ASSERT(m_csiRsMimoSignal.
m_chanMat.GetSize() != 0);
1913 if (m_avgIntCovMat.GetSize() != 0)
1915 csiFeedbackSignal.
m_covMat = m_avgIntCovMat;
1923 NS_LOG_FUNCTION(
this);
1926 auto csiFeedbackSignal =
NrMimoSignal(csiImSignalChunks);
1930 if (m_alphaCovMat != 1)
1932 csiFeedbackSignal.m_covMat = m_csiRsMimoSignal.
m_covMat;
1934 csiFeedbackSignal.m_chanMat = m_csiRsMimoSignal.
m_chanMat;
1941 NS_LOG_FUNCTION(
this);
1943 auto csiFeedbackSignal =
NrMimoSignal(pdschMimoChunks);
1946 if (m_alphaCovMat != 1)
1948 csiFeedbackSignal.m_covMat = m_avgIntCovMat;
1951 if (m_csiFeedbackType & CQI_CSI_RS)
1953 NS_ASSERT_MSG(m_csiRsMimoSignal.
m_chanMat.GetSize(),
1954 "CSI-RS based channel matrix not available");
1955 csiFeedbackSignal.m_chanMat = m_csiRsMimoSignal.
m_chanMat;
1968 NS_LOG_FUNCTION(
this);
1977 auto intfNormChanMat =
1980 ComplexMatrixArray precMat = ComplexMatrixArray(
1981 csiFeedbackSignal.
m_chanMat.GetNumCols(),
1982 csiFeedbackSignal.
m_chanMat.GetNumRows(),
1983 csiFeedbackSignal.
m_chanMat.GetNumPages(),
1984 std::valarray<std::complex<double>>(std::complex<double>(1.0, 0.0),
1985 csiFeedbackSignal.
m_chanMat.GetSize()));
1988 NrSinrMatrix sinrMatrix = intfNormChanMat.ComputeSinrForPrecoding(precMat);
1996 NS_LOG_FUNCTION(
this);
1997 if (avgIntCovMat->GetSize() == 0)
1999 *avgIntCovMat = ComplexMatrixArray(newCovMat.GetNumRows(),
2000 newCovMat.GetNumCols(),
2001 newCovMat.GetNumPages());
2004 *avgIntCovMat = newCovMat * std::complex<double>{m_alphaCovMat, 0.0} +
2005 *avgIntCovMat * std::complex<double>{1 - m_alphaCovMat, 0.0};
2017 auto now = Simulator::Now();
2018 if (now > m_wbPmiLastUpdate + m_wbPmiUpdateInterval)
2020 pmiUpdate.updateWb =
true;
2021 m_wbPmiLastUpdate = now;
2023 if (now > m_sbPmiLastUpdate + m_sbPmiUpdateInterval)
2025 pmiUpdate.updateSb =
true;
2026 m_sbPmiLastUpdate = now;
2034 m_pmSearch = pmSearch;
2036 m_pmSearch->SetAmc(m_amc);
@ UL_DCI
The resources allocation map from the BS to the attached UEs (UL)
@ DL_HARQ
DL HARQ feedback.
@ MIB
Master Information Block.
@ RAR
Random Access Response.
@ SIB1
System Information Block Type 1.
@ DL_DCI
The resources allocation map from the BS to the attached UEs (DL)
virtual NrIntfNormChanMat CalcIntfNormChannel(const ComplexMatrixArray &chanMat) const
Calculate the interference-normalized channel matrix for SISO and MIMO. See NrIntfNormChanMat for det...
The base class for gNb and UE physical layer.
Time GetSymbolPeriod() const
Get SymbolPeriod.
Ptr< NrSpectrumPhy > m_spectrumPhy
Pointer to the (owned) spectrum phy.
SlotAllocInfo RetrieveSlotAllocInfo()
Get the head for the slot allocation info, and delete it from the internal list.
uint16_t GetCellId() const
uint16_t GetNumerology() const
Get the configured numerology.
Ptr< NrSpectrumPhy > GetSpectrumPhy() const
Retrieve the SpectrumPhy pointer.
void EncodeCtrlMsg(const Ptr< NrControlMessage > &msg)
Take the control messages, and put it in a list that will be sent at the first occasion.
void SetNumerology(uint16_t numerology)
Set GNB or UE numerology.
virtual void SetTbDecodeLatency(const Time &us)
Configures TB decode latency.
std::list< Ptr< NrControlMessage > > m_ctrlMsgs
CTRL messages to be sent.
void PushBackSlotAllocInfo(const SlotAllocInfo &slotAllocInfo)
Store the slot allocation info.
Ptr< PacketBurst > GetPacketBurst(SfnSf sf, uint8_t sym, uint16_t rnti)
Retrieve the PacketBurst at the slot/symbol specified.
void SetPowerAllocationType(enum NrSpectrumValueHelper::PowerAllocationType powerAllocationType)
Set power allocation type. There are currently supported two types: one that distributes uniformly en...
static std::string GetPattern(const std::vector< LteNrTddSlotType > &pattern)
Get a string representation of a pattern.
Time GetSlotPeriod() const
Get the slot period.
virtual std::list< Ptr< NrControlMessage > > PopCurrentSlotCtrlMsgs()
Extract and return the message list that is at the beginning of the queue.
SlotAllocInfo m_currSlotAllocInfo
Current slot allocation.
enum NrSpectrumValueHelper::PowerAllocationType GetPowerAllocationType() const
Get the power allocation type.
void EnqueueCtrlMsgNow(const Ptr< NrControlMessage > &msg)
Enqueue a CTRL message without considering L1L2CtrlLatency.
uint32_t GetChannelBandwidth() const
Retrieve the channel bandwidth, in Hz.
virtual Time GetTbDecodeLatency() const
Returns Transport Block decode latency.
SlotAllocInfo & PeekSlotAllocInfo(const SfnSf &sfnsf)
Peek the SlotAllocInfo at the SfnSf specified.
double GetCentralFrequency() const
Retrieve the frequency (in Hz) of this PHY's channel.
double m_noiseFigure
Noise figure (attribute)
uint32_t m_raPreambleId
Preamble ID.
double GetNoiseFigure() const
Get the NoiseFigure value.
void SetNoiseFigure(double d)
Set the NoiseFigure value.
double m_txPower
Transmission power (attribute)
void InitializeMessageList()
Initialize the message list.
Ptr< SpectrumValue > GetTxPowerSpectralDensity(const std::vector< int > &rbIndexVector)
void SetChannelBandwidth(uint16_t bandwidth)
Function to set the channel bandwidth, used also by child classes, i.e., see functions DoSetDlBanwidt...
uint16_t GetBwpId() const
Ptr< NrNetDevice > m_netDevice
Pointer to the owner netDevice.
bool SlotAllocInfoExists(const SfnSf &sfnsf) const
Check if the SlotAllocationInfo for that slot exists.
uint32_t GetSubcarrierSpacing() const
Retrieve the subcarrier spacing in Hz. Subcarrier spacing is updated when the numerology is being upd...
uint32_t GetSymbolsPerSlot() const
Get the number of symbols in a slot.
std::vector< LteNrTddSlotType > m_tddPattern
Pattern.
double GetRbOverhead() const
Get the bandwidth overhead used when calculating the usable RB number.
uint32_t GetRbNum() const
Get the number of Resource block configured.
std::vector< int > FromRBGBitmaskToRBAssignment(const std::vector< bool > rbgBitmask) const
Transform a MAC-made vector of RBG to a PHY-ready vector of SINR indices.
void EnqueueCtrlMessage(const Ptr< NrControlMessage > &m)
Enqueue a ctrl message, keeping in consideration L1L2CtrlDelay.
void DoDispose() override
DoDispose method inherited from Object.
void DoSetCellId(uint16_t cellId)
Set the cell ID.
Tag used to define the RNTI and LC id for each MAC packet transmitted.
NrSinrMatrix stores the MIMO SINR matrix, with dimension rank x nRbs.
SpectrumValue GetVectorizedSpecVal() const
Linearize a 2D matrix into a vector, and convert that vector to a SpectrumValue Matches layer-to-code...
static const uint8_t SUBCARRIERS_PER_RB
subcarriers per resource block
virtual void ReportUeMeasurements(UeMeasurementsParameters params)=0
Send a report of RSRP and RSRQ values perceived from PSS by the PHY entity (after applying layer-1 fi...
virtual void ResetSyncIndicationCounter()=0
Reset the sync indication counter.
virtual void RecvSystemInformationBlockType1(uint16_t cellId, NrRrcSap::SystemInformationBlockType1 sib1)=0
Relay an SIB1 message from the PHY entity to the RRC layer.
virtual void RecvMasterInformationBlock(uint16_t cellId, NrRrcSap::MasterInformationBlock mib)=0
Relay an MIB message from the PHY entity to the RRC layer.
virtual void NotifyOutOfSync()=0
Send an out of sync indication to UE RRC.
virtual void NotifyInSync()=0
Send an in sync indication to UE RRC.
void SetUplinkPowerControl(Ptr< NrUePowerControl > pc)
Allow configuration of uplink power control algorithm. E.g. necessary in FDD, when measurements are r...
void SetPhySapUser(NrUePhySapUser *ptr)
Install the PHY sap user (AKA the UE MAC)
void ScheduleStartEventLoop(uint32_t nodeId, uint16_t frame, uint8_t subframe, uint16_t slot) override
Start the ue Event Loop.
void ReceivePss(uint16_t cellId, const Ptr< SpectrumValue > &p)
Receive PSS and calculate RSRQ in dBm.
void CalcAvgIntCovMat(NrCovMat *avgIntCovMat, const NrCovMat &newCovMat) const
Calculates the moving average of the interference covariance matrix.
uint8_t GetCsiImDuration() const
void EnqueueDlHarqFeedback(const DlHarqInfo &m)
Get the HARQ feedback (on the transmission) from NrSpectrumPhy and send it through ideal PUCCH to gNB...
void SetTxPower(double pow)
Set the transmission power for the UE.
void SetSubChannelsForTransmission(const std::vector< int > &mask, uint32_t numSym)
Set the Tx power spectral density based on the RB index vector.
NrUePhy()
NrUePhy default constructor.
void SetNumRbPerRbg(uint32_t numRbPerRbg)
Function that sets the number of RBs per RBG. This function will be soon deprecated,...
BeamId GetBeamId(uint16_t rnti) const override
Get the beam id for the specified user.
NrUePhySapUser * GetPhySapUser() const
Get pointer to PhySapUser.
~NrUePhy() override
~NrUePhy
Ptr< NrPmSearch > GetPmSearch() const
Get the precoding matrix search engine.
void GenerateCsiRsCqi()
Function that will be called in the case that CSI-RS is received, but CSI-IM is disabled and there is...
void CsiRsReceived(const std::vector< MimoSignalChunk > &csiRsSignal)
A callback function that is called from NrMimoChunkProcessor when CSI-RS is being received....
NrPmSearch::PmiUpdate CheckUpdatePmi()
Check if updates to wideband and/or subband PMI are necessary. This function is used to limit the fre...
void SetPmSearch(Ptr< NrPmSearch > pmSearch)
Set the precoding matrix search engine.
uint32_t GetNumRbPerRbg() const override
NrUeCphySapProvider * GetUeCphySapProvider() __attribute__((warn_unused_result))
Retrieve the pointer for the C PHY SAP provider (AKA the PHY interface towards the RRC)
Time GetLastSlotStart() const
Get Time of last slot start.
uint8_t ComputeCqi(const SpectrumValue &sinr)
Compute the CQI based on the SINR.
void SetAlphaCovMat(double alpha)
Set alpha parameter for the calculation of the CSI interference covariance matrix moving average.
void SetDlAmc(const Ptr< const NrAmc > &amc)
Set the AMC pointer from the GNB.
double GetTxPower() const override
Retrieve the TX power of the UE.
void SetCsiImDuration(uint8_t csiImDuration)
Sets CSI-IM duration in the number of OFDM symbols, if enabled.
void SetDlCtrlSyms(uint8_t dlCtrlSyms)
Set the number of DL CTRL symbols.
uint8_t GetCsiFeedbackType() const
double GetRsrp() const
Returns the latest measured RSRP value Called by NrUePowerControl.
void DoDispose() override
DoDispose method inherited from Object.
Ptr< NrUePowerControl > GetUplinkPowerControl() const
Get NR uplink power control entity.
void GenerateDlCqiReportMimo(const NrMimoSignal &cqiMimoFeedbackSignal, NrPmSearch::PmiUpdate pmiUpdateParams)
Generate DL CQI, PMI, and RI (channel quality precoding matrix and rank indicators)
void SetCurrentSfnSf(const SfnSf ¤tSfnSf)
Set current SfnSf.
void GenerateDlCqiReport(const SpectrumValue &sinr)
Generate a DL CQI report.
void SetCam(const Ptr< NrChAccessManager > &cam)
Set the channel access manager interface for this instance of the PHY.
void SetPattern(const std::string &pattern)
Set the UE pattern.
void SetUlCtrlSyms(uint8_t ulCtrlSyms)
Set the number of UL CTRL symbols.
uint16_t GetRnti() const __attribute__((warn_unused_result))
Get the current RNTI of the user.
void RegisterToGnb(uint16_t bwpId)
Register the UE to a certain Gnb.
void FinishSlotProcessing(const SfnSf &s, bool nrAllocationExists)
Finish the StartSlot processing.
const SfnSf & GetCurrentSfnSf() const override
Get the current SfnSf.
void SetUeCphySapUser(NrUeCphySapUser *s)
Install ue C PHY SAP user (AKA the PHY interface towards the RRC)
void PhyCtrlMessagesReceived(const Ptr< NrControlMessage > &msg)
Receive a list of CTRL messages.
double GetAlphaCovMat() const
void TriggerDlCqiGeneration(const NrMimoSignal &csiFeedbackSignal, NrPmSearch::PmiUpdate pmiUpdateParams)
Function is called in different possible scenarios to generate CQI information. For example,...
void PdschMimoReceived(const std::vector< MimoSignalChunk > &pdschMimoChunks)
Function is called when PDSCH is received by the UE. It contains the channel and interference informa...
void SetLastSlotStart(Time startTime)
Set last slot start.
void ReportDlCtrlSinr(const SpectrumValue &sinr)
Called when DlCtrlSinr is fired.
void PhyDataPacketReceived(const Ptr< Packet > &p)
Receive a PHY data packet.
void ReportRsReceivedPower(const SpectrumValue &power)
Called when rsReceivedPower is fired.
void CsiImEnded(const std::vector< MimoSignalChunk > &csiImSignalChunks)
Function is called when CSI-IM finishes, and this function triggers the update of the interference co...
static TypeId GetTypeId()
Get the object TypeId.
SAP interface between the UE PHY and the UE MAC.
virtual void ReceiveControlMessage(Ptr< NrControlMessage > msg)=0
Receive SendNrControlMessage (PDCCH map, CQI feedbacks) using the ideal control channel.
virtual void ReceivePhyPdu(Ptr< Packet > p)=0
Notify the MAC of the reception of a new PHY-PDU.
virtual void SlotIndication(SfnSf s)=0
Trigger the indication of a new slot for the MAC.
void Add(uint32_t slotN)
Add to this SfnSf a number of slot indicated by the first parameter.
@ F
DL CTRL + DL DATA + UL DATA + UL CTRL.
@ S
DL CTRL + DL DATA + UL CTRL.
@ CTRL
Used for DL/UL CTRL.
@ DATA
Used for DL/UL DATA.
@ SRS
Used for SRS (it would be like DCI format 2_3)
enum ns3::DlCqiInfo::DlCqiType WB
The type of the CQI.
A struct that contains info for the DL HARQ.
uint8_t m_harqProcessId
ProcessId.
Helper struct for processing and storing received signals for use in CSI feedback.
NrCovMat m_covMat
Interference and noise covariance matrix; nRxPorts * nRxPorts * nRbs.
ComplexMatrixArray m_chanMat
Channel Matrix; nRxPorts * nTxPorts * nRbs.
Parameters that define if PMI should be updated or if previous PMI values are used.
UeMeasurementsParameters structure.
std::vector< UeMeasurementsElement > m_ueMeasurementsList
UE measurement list.
uint8_t m_componentCarrierId
component carrier ID
The SlotAllocInfo struct.
SfnSf m_sfnSf
SfnSf of this allocation.
std::deque< VarTtiAllocInfo > m_varTtiAllocInfo
queue of allocations