5#define NS_LOG_APPEND_CONTEXT \
8 std::clog << " [ CellId " << GetCellId() << ", bwpId " << GetBwpId() << "] "; \
13#include "beam-manager.h"
14#include "nr-net-device.h"
15#include "nr-spectrum-phy.h"
17#include "ns3/boolean.h"
18#include "ns3/pointer.h"
19#include "ns3/uniform-planar-array.h"
26NS_LOG_COMPONENT_DEFINE(
"NrPhy");
28NS_OBJECT_ENSURE_REGISTERED(NrPhy);
31class NrMemberPhySapProvider :
public NrPhySapProvider
34 NrMemberPhySapProvider(NrPhy* phy);
36 void SendMacPdu(
const Ptr<Packet>& p,
39 uint16_t rnti)
override;
41 void SendControlMessage(Ptr<NrControlMessage> msg)
override;
43 void SendRachPreamble(uint8_t PreambleId, uint8_t Rnti)
override;
45 void SetSlotAllocInfo(
const SlotAllocInfo& slotAllocInfo)
override;
47 BeamId GetBeamId(uint8_t rnti)
const override;
49 Ptr<const SpectrumModel> GetSpectrumModel()
override;
51 void NotifyConnectionSuccessful()
override;
53 uint16_t GetBwpId()
const override;
55 uint16_t GetCellId()
const override;
57 uint32_t GetSymbolsPerSlot()
const override;
59 Time GetSlotPeriod()
const override;
61 uint32_t GetRbNum()
const override;
67NrMemberPhySapProvider::NrMemberPhySapProvider(NrPhy* phy)
74NrMemberPhySapProvider::SendMacPdu(
const Ptr<Packet>& p,
79 m_phy->SetMacPdu(p, sfn, symStart, rnti);
83NrMemberPhySapProvider::SendControlMessage(Ptr<NrControlMessage> msg)
85 m_phy->EnqueueCtrlMessage(msg);
89NrMemberPhySapProvider::SendRachPreamble(uint8_t PreambleId, uint8_t Rnti)
91 m_phy->SendRachPreamble(PreambleId, Rnti);
95NrMemberPhySapProvider::SetSlotAllocInfo(
const SlotAllocInfo& slotAllocInfo)
97 m_phy->PushBackSlotAllocInfo(slotAllocInfo);
101NrMemberPhySapProvider::GetBeamId(uint8_t rnti)
const
103 return m_phy->GetBeamId(rnti);
106Ptr<const SpectrumModel>
107NrMemberPhySapProvider::GetSpectrumModel()
109 return m_phy->GetSpectrumModel();
113NrMemberPhySapProvider::NotifyConnectionSuccessful()
115 m_phy->NotifyConnectionSuccessful();
119NrMemberPhySapProvider::GetBwpId()
const
121 return m_phy->GetBwpId();
125NrMemberPhySapProvider::GetCellId()
const
127 return m_phy->GetCellId();
131NrMemberPhySapProvider::GetSymbolsPerSlot()
const
133 return m_phy->GetSymbolsPerSlot();
137NrMemberPhySapProvider::GetSlotPeriod()
const
139 return m_phy->GetSlotPeriod();
143NrMemberPhySapProvider::GetRbNum()
const
145 return m_phy->GetRbNum();
153 static TypeId tid = TypeId(
"ns3::NrPhy")
155 .AddAttribute(
"NrSpectrumPhy",
156 "NrSpectrumPhy instance",
158 MakePointerAccessor(&NrPhy::m_spectrumPhy),
159 MakePointerChecker<NrSpectrumPhy>());
165NrPhy::FromRBGBitmaskToRBAssignment(
const std::vector<bool> rbgBitmask)
const
167 std::vector<int> ret;
169 for (uint32_t i = 0; i < rbgBitmask.size(); ++i)
171 if (rbgBitmask.at(i) == 1)
173 for (uint32_t k = 0; k < GetNumRbPerRbg(); ++k)
175 ret.push_back((i * GetNumRbPerRbg()) + k);
180 NS_ASSERT(
static_cast<uint32_t
>(std::count(rbgBitmask.begin(), rbgBitmask.end(), 1) *
181 GetNumRbPerRbg()) == ret.size());
186 : m_currSlotAllocInfo(
SfnSf(0, 0, 0, 0)),
187 m_tbDecodeLatencyUs(100.0)
189 NS_LOG_FUNCTION(
this);
195 NS_LOG_FUNCTION(
this);
201 NS_LOG_FUNCTION(
this);
202 m_slotAllocInfo.clear();
203 m_controlMessageQueue.clear();
219 NS_LOG_FUNCTION(
this);
229 NS_LOG_FUNCTION(
this);
236 NS_LOG_FUNCTION(
this);
237 NS_ABORT_IF(m_centralFrequency >= 0.0);
238 m_centralFrequency = f;
244 NS_LOG_FUNCTION(
this);
246 NS_LOG_DEBUG(
"SetChannelBandwidth called with channel bandwidth value: "
247 << channelBandwidth * 100 * 1000
249 "and the previous value of channel bandwidth was: "
252 if (m_channelBandwidth != channelBandwidth)
254 m_channelBandwidth = channelBandwidth;
263 NS_LOG_FUNCTION(
this);
264 m_numerology = numerology;
265 m_slotsPerSubframe =
static_cast<uint16_t
>(std::pow(2, numerology));
266 m_slotPeriod = Seconds(0.001 / m_slotsPerSubframe);
267 m_subcarrierSpacing = 15000 *
static_cast<uint32_t
>(std::pow(2, numerology));
268 m_symbolPeriod = (m_slotPeriod / m_symbolsPerSlot);
271 if (m_channelBandwidth != 0)
275 NS_LOG_INFO(
" Numerology configured:"
276 <<
GetNumerology() <<
" slots per subframe: " << m_slotsPerSubframe
279 <<
" number of RBs: " <<
GetRbNum());
283 NS_LOG_DEBUG(
"Numerology is set, but the channel bandwidth not yet, so the number of RBs "
284 "cannot be updated now.");
297 NS_LOG_FUNCTION(
this);
298 m_symbolsPerSlot = symbolsPerSlot;
299 m_symbolPeriod = (m_slotPeriod / m_symbolsPerSlot);
317 return m_symbolsPerSlot;
323 NS_ABORT_IF(m_slotPeriod.IsNegative());
330 NS_LOG_FUNCTION(
this);
337 NS_LOG_FUNCTION(
this);
343 NS_LOG_FUNCTION(
this);
350 it =
m_packetBurstMap.insert(std::make_pair(key, CreateObject<PacketBurst>())).first;
352 it->second->AddPacket(p);
353 NS_LOG_INFO(
"Adding a packet for the Packet Burst of " << sfn <<
" at sym " << +symStart
360 NS_LOG_FUNCTION(
this);
366 NS_LOG_FUNCTION(
this);
368 Ptr<PacketBurst> pburst;
375 NS_LOG_WARN(
"Packet burst not found for " << sfn <<
" at sym " << +sym);
401 m_powerAllocationType);
407 NS_LOG_FUNCTION(
this);
408 NS_ABORT_IF(m_centralFrequency < 0.0);
409 return m_centralFrequency;
415 static std::unordered_map<LteNrTddSlotType, std::string, std::hash<int>> lookupTable = {
421 std::stringstream ss;
423 for (
const auto& v : pattern)
425 ss << lookupTable[v] <<
"|";
434 m_powerAllocationType = powerAllocationType;
437enum NrSpectrumValueHelper::PowerAllocationType
440 return m_powerAllocationType;
446 NS_LOG_FUNCTION(
this);
448 m_controlMessageQueue.at(m_controlMessageQueue.size() - 1).push_back(m);
454 NS_LOG_FUNCTION(
this);
456 m_controlMessageQueue.at(0).push_back(msg);
462 for (
const auto& msg : listOfMsgs)
464 m_controlMessageQueue.at(0).push_back(msg);
471 NS_LOG_FUNCTION(
this);
490 for (
const auto& v : pattern)
503 for (
const auto& v : pattern)
523 return m_channelBandwidth * 1000 * 100;
529 return m_subcarrierSpacing;
535 NS_LOG_FUNCTION(
this);
536 NS_ABORT_MSG_IF(m_channelBandwidth == 0,
"Channel bandwidth not set");
543 "Bandwidth and numerology not correctly set. Bandwidth after reduction of overhead is :"
544 << realBw <<
", while RB width is: " << rbWidth);
546 m_rbNum =
static_cast<uint32_t
>(realBw / rbWidth);
549 NS_LOG_INFO(
"Updated RbNum to " <<
GetRbNum());
565 NS_LOG_WARN(
"Working without channel (i.e., under test)");
567 NS_LOG_DEBUG(
"Noise Power Spectral Density updated");
576 for (
const auto& v : pattern)
594 return !(anUl ^ aDl);
600 NS_LOG_FUNCTION(
this);
601 m_controlMessageQueue.clear();
605 m_controlMessageQueue.emplace_back();
609std::list<Ptr<NrControlMessage>>
612 NS_LOG_FUNCTION(
this);
613 if (m_controlMessageQueue.empty())
615 std::list<Ptr<NrControlMessage>> emptylist;
619 if (!m_controlMessageQueue.at(0).empty())
621 std::list<Ptr<NrControlMessage>> ret = m_controlMessageQueue.front();
622 m_controlMessageQueue.erase(m_controlMessageQueue.begin());
623 std::list<Ptr<NrControlMessage>> newlist;
624 m_controlMessageQueue.push_back(newlist);
629 m_controlMessageQueue.erase(m_controlMessageQueue.begin());
630 std::list<Ptr<NrControlMessage>> newlist;
631 m_controlMessageQueue.push_back(newlist);
632 std::list<Ptr<NrControlMessage>> emptylist;
640 NS_LOG_FUNCTION(
this);
677 NS_LOG_FUNCTION(
this);
684 NS_LOG_FUNCTION(
this);
686 NS_LOG_DEBUG(
"setting info for slot " << slotAllocInfo.
m_sfnSf);
689 bool updated =
false;
690 for (
auto& alloc : m_slotAllocInfo)
692 if (alloc.m_sfnSf == slotAllocInfo.
m_sfnSf)
694 NS_LOG_DEBUG(
"Merging inside existing allocation");
695 alloc.Merge(slotAllocInfo);
702 m_slotAllocInfo.push_back(slotAllocInfo);
703 m_slotAllocInfo.sort();
704 NS_LOG_DEBUG(
"Pushing allocation at the end of the list");
707 std::stringstream output;
709 for (
const auto& alloc : m_slotAllocInfo)
713 NS_LOG_DEBUG(output.str());
719 NS_LOG_FUNCTION(
this);
721 m_slotAllocInfo.push_front(slotAllocInfo);
722 SfnSf currentSfn = newSfnSf;
723 std::unordered_map<uint64_t, Ptr<PacketBurst>>
725 std::unordered_map<uint64_t, uint64_t> sfnMap;
730 for (
auto it = m_slotAllocInfo.begin(); it != m_slotAllocInfo.end(); ++it)
732 auto slotSfn = it->m_sfnSf;
733 for (
const auto& alloc : it->m_varTtiAllocInfo)
737 Ptr<PacketBurst> pburst =
738 GetPacketBurst(slotSfn, alloc.m_dci->m_symStart, alloc.m_dci->m_rnti);
739 if (pburst && pburst->GetNPackets() > 0)
742 alloc.m_dci->m_rnti);
743 auto oldKey = it->m_sfnSf.GetEncodingWithSymStartRnti(alloc.m_dci->m_symStart,
744 alloc.m_dci->m_rnti);
745 newBursts.insert({newKey, pburst});
746 sfnMap.insert({newKey, oldKey});
750 NS_LOG_INFO(
"No packet burst found for " << slotSfn);
755 NS_LOG_INFO(
"Set slot allocation for " << it->m_sfnSf <<
" to " << currentSfn);
756 it->m_sfnSf = currentSfn;
760 for (
const auto& burstPair : newBursts)
767 NS_LOG_INFO(
"PacketBurst with " << burstPair.second->GetNPackets() <<
"packets for SFN "
768 << old <<
" now moved to SFN " << latest);
775 NS_LOG_FUNCTION(
this);
777 for (
const auto& alloc : m_slotAllocInfo)
779 if (alloc.m_sfnSf == retVal)
790 NS_LOG_FUNCTION(
this);
792 m_slotAllocInfo.erase(m_slotAllocInfo.begin());
799 NS_LOG_FUNCTION(
" slot " << sfnsf);
802 for (
auto allocIt = m_slotAllocInfo.begin(); allocIt != m_slotAllocInfo.end(); ++allocIt)
804 if (allocIt->m_sfnSf == sfnsf)
807 m_slotAllocInfo.erase(allocIt);
812 NS_FATAL_ERROR(
"Didn't found the slot");
819 NS_LOG_FUNCTION(
this);
821 for (
auto& alloc : m_slotAllocInfo)
823 if (alloc.m_sfnSf == sfnsf)
829 NS_FATAL_ERROR(
"Didn't found the slot");
835 NS_LOG_FUNCTION(
this);
836 return m_slotAllocInfo.size();
842 NS_LOG_FUNCTION(
this);
843 return m_controlMessageQueue.empty() || m_controlMessageQueue.at(0).empty();
846Ptr<const SpectrumModel>
849 NS_LOG_FUNCTION(
this);
851 NS_ABORT_MSG_IF(m_channelBandwidth == 0,
"Channel bandwidth not set.");
860 NS_LOG_FUNCTION(
this);
861 return m_symbolPeriod;
884 m_tbDecodeLatencyUs = us;
890 return m_tbDecodeLatencyUs;
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 DoInitialize() override
DoInitialize method inherited from Object.
void SetRbOverhead(double oh)
Set the bandwidth overhead for calculating the usable RB number.
void PushBackSlotAllocInfo(const SlotAllocInfo &slotAllocInfo)
Store the slot allocation info.
void NotifyConnectionSuccessful()
Notify PHY about the successful RRC connection establishment.
void InstallCentralFrequency(double f)
Install the PHY over a particular central frequency.
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.
void InstallSpectrumPhy(const Ptr< NrSpectrumPhy > &spectrumPhy)
Set the SpectrumPhy associated with this PHY.
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.
virtual void SendRachPreamble(uint32_t PreambleId, uint32_t Rnti)
Send the RachPreamble.
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.
void SetMacPdu(const Ptr< Packet > &p, const SfnSf &sfn, uint8_t symStart, uint16_t rnti)
Store a MAC PDU.
double m_noiseFigure
Noise figure (attribute)
void SetSymbolsPerSlot(uint16_t symbolsPerSlot)
Set the number of symbol per slot.
void SetDevice(Ptr< NrNetDevice > d)
Set the owner device.
Ptr< const SpectrumModel > GetSpectrumModel()
Get the spectrum model of the PHY.
size_t SlotAllocInfoSize() const
Retrieve the size of the SlotAllocInfo list.
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.
void DoUpdateRbNum()
Update the number of RB. Usually called after bandwidth changes.
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
void PushFrontSlotAllocInfo(const SfnSf &newSfnSf, const SlotAllocInfo &slotAllocInfo)
Store the slot allocation info at the front.
Ptr< NrNetDevice > m_netDevice
Pointer to the owner netDevice.
uint32_t GetL1L2CtrlLatency() const
bool HasDlSlot() const
Go through the current pattern and see if at least one slot is DL, F or S.
bool SlotAllocInfoExists(const SfnSf &sfnsf) const
Check if the SlotAllocationInfo for that slot exists.
std::unordered_map< uint64_t, Ptr< PacketBurst > > m_packetBurstMap
Map between SfnSf and PacketBurst.
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.
Ptr< SpectrumValue > GetNoisePowerSpectralDensity()
Create Noise Power Spectral density.
bool IsCtrlMsgListEmpty() const
Check if there are no control messages queued for this slot.
NrPhySapProvider * m_phySapProvider
Pointer to the MAC.
double GetRbOverhead() const
Get the bandwidth overhead used when calculating the usable RB number.
bool HasUlSlot() const
Go through the current pattern and see if at least one slot is UL, F or S.
void SetBwpId(uint16_t bwpId)
Set the bwp id. Called by helper.
uint32_t GetRbNum() const
Get the number of Resource block configured.
void EnqueueCtrlMessage(const Ptr< NrControlMessage > &m)
Enqueue a ctrl message, keeping in consideration L1L2CtrlDelay.
static bool IsTdd(const std::vector< LteNrTddSlotType > &pattern)
Check if a pattern is TDD.
NrPhySapProvider * GetPhySapProvider()
Retrieve a pointer to an instance of NrPhySapProvider.
void DoDispose() override
DoDispose method inherited from Object.
void DoSetCellId(uint16_t cellId)
Set the cell ID.
SAP interface between the MAC and the PHY.
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 Ptr< SpectrumValue > CreateNoisePowerSpectralDensity(double noiseFigure, const Ptr< const SpectrumModel > &spectrumModel)
Create a SpectrumValue that models the power spectral density of AWGN.
static Ptr< SpectrumValue > CreateTxPowerSpectralDensity(double powerTx, const std::vector< int > &rbIndexVector, const Ptr< const SpectrumModel > &txSm, enum PowerAllocationType allocationType)
Create SpectrumValue that will represent transmit power spectral density, and assuming that all RBs a...
static const uint8_t SUBCARRIERS_PER_RB
subcarriers per resource block
static SfnSf Decode(uint64_t sfn)
Decode the parameter and return a SfnSf.
uint8_t GetNumerology() const
GetNumerology.
void Add(uint32_t slotN)
Add to this SfnSf a number of slot indicated by the first parameter.
uint64_t GetEncodingWithSymStartRnti(uint8_t symStart, uint16_t rnti) const
Get an encoding of frame & slot number, plus starting OFDM symbol and RNTI.
@ F
DL CTRL + DL DATA + UL DATA + UL CTRL.
@ S
DL CTRL + DL DATA + UL CTRL.
@ DATA
Used for DL/UL DATA.
The SlotAllocInfo struct.
SfnSf m_sfnSf
SfnSf of this allocation.