5#define NS_LOG_APPEND_CONTEXT \
8 std::clog << " [ CellId " << GetCellId() << ", bwpId " << GetBwpId() << "] "; \
10#include "nr-mac-scheduler-harq-rr.h"
12#include "nr-fh-control.h"
21NS_LOG_COMPONENT_DEFINE(
"NrMacSchedulerHarqRr");
48 m_getFhControlMethod = fn;
53 const std::function<
bool(uint16_t bwpId, uint32_t mcs, uint32_t nRegs, uint8_t dlRank)>& fn)
55 m_getDoesAllocationFit = fn;
77 const std::unordered_map<uint16_t, std::shared_ptr<NrMacSchedulerUeInfo>>& ueMap,
78 std::vector<DlHarqInfo>* dlHarqToRetransmit,
79 const std::vector<DlHarqInfo>& dlHarqFeedback,
82 NS_LOG_FUNCTION(
this);
83 NS_ASSERT(startingPoint->
m_rbg == 0);
85 uint8_t symPerBeam = symAvail / activeDlHarq.size();
87 NS_LOG_INFO(
"We have " << activeDlHarq.size() <<
" beams with data to RETX, each beam has "
88 <<
static_cast<uint32_t
>(symPerBeam) <<
" symb");
90 for (
const auto& beam : activeDlHarq)
92 std::vector<uint16_t> allocatedUe;
93 NS_LOG_INFO(
" Try to assign HARQ resource for Beam sector: "
94 <<
static_cast<uint32_t
>(beam.first.GetSector())
95 <<
" Beam theta: " <<
static_cast<uint32_t
>(beam.first.GetElevation())
96 <<
" # HARQ to Retx=" << beam.second.size());
98 for (
auto it : beam.second)
102 "Process " <<
static_cast<uint32_t
>(it->first)
103 <<
" is not in RECEIVED_FEEDBACK status");
110 uint32_t rbgAssigned =
111 std::count(dciInfoReTx->m_rbgBitmask.begin(), dciInfoReTx->m_rbgBitmask.end(), 1) *
112 dciInfoReTx->m_numSym;
115 NS_LOG_INFO(
"Evaluating space to retransmit HARQ PID="
116 <<
static_cast<uint32_t
>(dciInfoReTx->m_harqProcess) <<
" for UE="
117 <<
static_cast<uint32_t
>(dciInfoReTx->m_rnti) <<
" SYM assigned previously="
118 <<
static_cast<uint32_t
>(dciInfoReTx->m_numSym)
119 <<
" RBG assigned previously=" <<
static_cast<uint32_t
>(rbgAssigned)
120 <<
" SYM avail for this beam=" <<
static_cast<uint32_t
>(symPerBeam)
121 <<
" RBG avail for this beam=" << rbgAvail);
123 if (std::find(allocatedUe.begin(), allocatedUe.end(), dciInfoReTx->m_rnti) !=
126 NS_LOG_INFO(
"UE " << dciInfoReTx->m_rnti
127 <<
" already has an HARQ allocated, buffer this HARQ process"
128 <<
static_cast<uint32_t
>(dciInfoReTx->m_harqProcess));
132 dciInfoReTx->m_harqProcess);
135 else if (rbgAvail < rbgAssigned)
137 NS_LOG_INFO(
"No resource for this retx, we have to buffer it");
141 dciInfoReTx->m_harqProcess);
151 dciInfoReTx->m_rank) == 0)
153 NS_LOG_INFO(
"No FH resources for this retx, we have to buffer it");
157 dciInfoReTx->m_harqProcess);
162 allocatedUe.push_back(dciInfoReTx->m_rnti);
165 auto dci = std::make_shared<DciInfoElementTdma>(dciInfoReTx->m_rnti,
166 dciInfoReTx->m_format,
167 startingPoint->
m_sym,
171 dciInfoReTx->m_precMats,
172 dciInfoReTx->m_tbSize,
174 dciInfoReTx->m_rv + 1,
176 dciInfoReTx->m_bwpIndex,
179 dci->m_rbgBitmask = harqProcess.
m_dciElement->m_rbgBitmask;
180 dci->m_harqProcess = dciInfoReTx->m_harqProcess;
185 if (rbgAssigned % dciInfoReTx->m_numSym == 0)
187 rbgAssigned = rbgAssigned / dciInfoReTx->m_numSym;
191 rbgAssigned = rbgAssigned / dciInfoReTx->m_numSym;
195 NS_ABORT_IF(
static_cast<unsigned long>(rbgAssigned) > dciInfoReTx->m_rbgBitmask.size());
197 for (
unsigned int i = 0; i < dciInfoReTx->m_rbgBitmask.size(); ++i)
199 if (startingPoint->
m_rbg <= i && i < startingPoint->m_rbg + rbgAssigned)
201 dciInfoReTx->m_rbgBitmask.at(i) =
true;
205 dciInfoReTx->m_rbgBitmask.at(i) =
false;
209 startingPoint->
m_rbg += rbgAssigned;
213 "UE" << dciInfoReTx->m_rnti <<
" gets DL symbols "
214 <<
static_cast<uint32_t
>(dciInfoReTx->m_symStart) <<
"-"
215 <<
static_cast<uint32_t
>(dciInfoReTx->m_symStart + dciInfoReTx->m_numSym - 1)
216 <<
" tbs " << dciInfoReTx->m_tbSize <<
" harqId "
217 <<
static_cast<uint32_t
>(dciInfoReTx->m_harqProcess) <<
" rv "
218 <<
static_cast<uint32_t
>(dciInfoReTx->m_rv)
219 <<
" RBG start: " <<
static_cast<uint32_t
>(startingPoint->
m_rbg - rbgAssigned)
220 <<
" RBG end: " <<
static_cast<uint32_t
>(startingPoint->
m_rbg) <<
" RETX");
223 slotInfo.m_rlcPduInfo.push_back(rlcPdu);
227 ueMap.find(dciInfoReTx->m_rnti)->second->m_dlMRBRetx =
228 dciInfoReTx->m_numSym * rbgAssigned;
231 if (!allocatedUe.empty())
233 startingPoint->
m_sym += symPerBeam;
234 startingPoint->
m_rbg = 0;
235 usedSym += symPerBeam;
237 symAvail -= symPerBeam;
240 NS_ASSERT(startingPoint->
m_rbg == 0);
265 const std::unordered_map<uint16_t, std::shared_ptr<NrMacSchedulerUeInfo>>& ueMap,
266 std::vector<UlHarqInfo>* ulHarqToRetransmit,
267 const std::vector<UlHarqInfo>& ulHarqFeedback,
270 NS_LOG_FUNCTION(
this);
272 NS_ASSERT(startingPoint->
m_rbg == 0);
274 NS_LOG_INFO(
"Scheduling UL HARQ starting from sym "
275 << +startingPoint->
m_sym <<
" and RBG " << startingPoint->
m_rbg
276 <<
". Available symbols: " << symAvail
277 <<
" number of feedback: " << ulHarqFeedback.size());
279 for (uint16_t i = 0; i < ulHarqFeedback.size() && symAvail > 0; i++)
283 uint16_t rnti = harqInfo.
m_rnti;
288 HarqProcess& harqProcess = ueMap.find(rnti)->second->m_ulHarq.Find(harqId)->second;
295 NS_LOG_INFO(
"Feedback is for UE " << rnti <<
" process " << +harqId
296 <<
" sym: " << +dciInfoReTx->m_numSym);
298 if (symAvail >= dciInfoReTx->m_numSym)
300 symAvail -= dciInfoReTx->m_numSym;
301 symUsed += dciInfoReTx->m_numSym;
306 std::make_shared<DciInfoElementTdma>(dciInfoReTx->m_rnti,
307 dciInfoReTx->m_format,
308 startingPoint->
m_sym - dciInfoReTx->m_numSym,
309 dciInfoReTx->m_numSym,
312 dciInfoReTx->m_precMats,
313 dciInfoReTx->m_tbSize,
315 dciInfoReTx->m_rv + 1,
317 dciInfoReTx->m_bwpIndex,
319 dci->m_rbgBitmask = harqProcess.
m_dciElement->m_rbgBitmask;
320 dci->m_harqProcess = harqId;
324 startingPoint->
m_sym -= dciInfoReTx->m_numSym;
328 "UE" << dciInfoReTx->m_rnti <<
" gets UL symbols "
329 <<
static_cast<uint32_t
>(dciInfoReTx->m_symStart) <<
"-"
330 <<
static_cast<uint32_t
>(dciInfoReTx->m_symStart + dciInfoReTx->m_numSym - 1)
331 <<
" tbs " << dciInfoReTx->m_tbSize <<
" harqId "
332 <<
static_cast<uint32_t
>(dciInfoReTx->m_harqProcess) <<
" rv "
333 <<
static_cast<uint32_t
>(dciInfoReTx->m_rv) <<
" RETX");
337 ueMap.find(rnti)->second->m_ulMRBRetx = dciInfoReTx->m_numSym *
GetBandwidthInRbg();
341 ulHarqToRetransmit->push_back(ulHarqFeedback.at(i));
345 NS_ASSERT(startingPoint->
m_rbg == 0);
357 NS_LOG_FUNCTION(
this);
362 bool operator()(
const NrMacSchedulerNs3::HarqVectorIterator& a,
363 const NrMacSchedulerNs3::HarqVectorIterator& b)
const
365 return a->second.m_dciElement->m_numSym > b->second.m_dciElement->m_numSym;
369 for (
auto& it : *activeDlHarq)
371 std::stable_sort(it.second.begin(), it.second.end(), CompareNumSym);
388 NS_LOG_FUNCTION(
this);
400 std::vector<DlHarqInfo>* dlHarqToRetransmit,
402 uint8_t harqProcess)
const
404 NS_LOG_FUNCTION(
this);
407 for (
const auto& feedback : dlHarqFeedback)
409 if (feedback.m_rnti == rnti && feedback.m_harqProcessId == harqProcess)
411 dlHarqToRetransmit->push_back(feedback);
428 return m_getCellId();
434 return m_getBwInRbg();
440 return m_getFhControlMethod();
447 uint8_t dlRank)
const
449 return m_getDoesAllocationFit(bwpId, mcs, nRegs, dlRank);
@ Postponing
Postpone sending data (MAC Layer)
@ OptimizeRBs
Optimize RBs allocated.
@ OptimizeMcs
Optimize MCS.
virtual uint8_t ScheduleUlHarq(NrMacSchedulerNs3::PointInFTPlane *startingPoint, uint8_t symAvail, const std::unordered_map< uint16_t, std::shared_ptr< NrMacSchedulerUeInfo > > &ueMap, std::vector< UlHarqInfo > *ulHarqToRetransmit, const std::vector< UlHarqInfo > &ulHarqFeedback, SlotAllocInfo *slotAlloc) const
Schedule the UL HARQ.
uint16_t GetBwpId() const
Get the bwp id of this MAC.
uint16_t GetCellId() const
Get the cell id of this MAC.
void InstallGetBwpIdFn(const std::function< uint16_t()> &fn)
Install a function to retrieve the bwp id.
void InstallDoesFhAllocationFitFn(const std::function< bool(uint16_t bwpId, uint32_t mcs, uint32_t nRegs, uint8_t dlRank)> &fn)
Install a function to retrieve whether the allocation fits when FH Control is enabled.
virtual void SortDlHarq(NrMacSchedulerNs3::ActiveHarqMap *activeDlHarq) const
Sort Dl Harq retx based on their symbol requirement.
uint16_t GetBandwidthInRbg() const
Get the bandwidth in RBG.
NrMacSchedulerHarqRr()
NrMacSchedulerHarqRr constructor.
void BufferHARQFeedback(const std::vector< DlHarqInfo > &dlHarqFeedback, std::vector< DlHarqInfo > *dlHarqToRetransmit, uint16_t rnti, uint8_t harqProcess) const
Find the specified HARQ process and buffer it into a vector.
void InstallGetCellIdFn(const std::function< uint16_t()> &fn)
Install a function to retrieve the cell id.
bool GetDoesFhAllocationFit(uint16_t bwpId, uint32_t mcs, uint32_t nRegs, uint8_t dlRank) const
Get from sched if the allocation fits when FH Control is enabled.
void InstallGetFhControlMethodFn(const std::function< uint8_t()> &fn)
Install a function to retrieve the FH Control Method (when enabled)
uint8_t GetFromSchedFhControlMethod() const
Get the FH Control method.
virtual void SortUlHarq(NrMacSchedulerNs3::ActiveHarqMap *activeUlHarq) const
(In theory) sort UL HARQ retx
void InstallGetBwInRBG(const std::function< uint16_t()> &fn)
Install a function to retrieve the bandwidth in RBG.
virtual uint8_t ScheduleDlHarq(NrMacSchedulerNs3::PointInFTPlane *startingPoint, uint8_t symAvail, const NrMacSchedulerNs3::ActiveHarqMap &activeDlHarq, const std::unordered_map< uint16_t, std::shared_ptr< NrMacSchedulerUeInfo > > &ueMap, std::vector< DlHarqInfo > *dlHarqToRetransmit, const std::vector< DlHarqInfo > &dlHarqFeedback, SlotAllocInfo *slotAlloc) const
Schedule DL HARQ in RR fashion.
std::unordered_map< BeamId, HarqVectorIteratorList, BeamIdHash > ActiveHarqMap
Map between a beamID and the HARQ of that beam.
@ DATA
Used for DL/UL DATA.
uint8_t m_harqProcessId
ProcessId.
Status m_status
Status of the process.
std::vector< RlcPduInfo > m_rlcPduInfo
vector of RLC PDU
uint8_t m_timer
Timer of the process (in slot)
@ RECEIVED_FEEDBACK
Received feedback (NACK)
@ WAITING_FEEDBACK
Data transmitted, waiting the feedback.
std::shared_ptr< DciInfoElementTdma > m_dciElement
DCI element.
Point in the Frequency/Time plane.
uint32_t m_rbg
Represent the starting RBG.
uint8_t m_sym
Represent the starting symbol.
The SlotAllocInfo struct.
uint32_t m_numSymAlloc
Number of allocated symbols.
std::deque< VarTtiAllocInfo > m_varTtiAllocInfo
queue of allocations
A struct that contains info for the UL HARQ.
bool IsReceivedOk() const override