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/pointer.h"
18#include "ns3/uniform-planar-array.h"
19#include <ns3/boolean.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);
196 NS_LOG_FUNCTION(
this);
202 NS_LOG_FUNCTION(
this);
203 m_slotAllocInfo.clear();
204 m_controlMessageQueue.clear();
220 NS_LOG_FUNCTION(
this);
230 NS_LOG_FUNCTION(
this);
237 NS_LOG_FUNCTION(
this);
238 NS_ABORT_IF(m_centralFrequency >= 0.0);
239 m_centralFrequency = f;
245 NS_LOG_FUNCTION(
this);
247 NS_LOG_DEBUG(
"SetChannelBandwidth called with channel bandwidth value: "
248 << channelBandwidth * 100 * 1000
250 "and the previous value of channel bandwidth was: "
253 if (m_channelBandwidth != channelBandwidth)
255 m_channelBandwidth = channelBandwidth;
264 NS_LOG_FUNCTION(
this);
265 m_numerology = numerology;
266 m_slotsPerSubframe =
static_cast<uint16_t
>(std::pow(2, numerology));
267 m_slotPeriod = Seconds(0.001 / m_slotsPerSubframe);
268 m_subcarrierSpacing = 15000 *
static_cast<uint32_t
>(std::pow(2, numerology));
269 m_symbolPeriod = (m_slotPeriod / m_symbolsPerSlot);
272 if (m_channelBandwidth != 0)
276 NS_LOG_INFO(
" Numerology configured:"
277 <<
GetNumerology() <<
" slots per subframe: " << m_slotsPerSubframe
280 <<
" number of RBs: " <<
GetRbNum());
284 NS_LOG_DEBUG(
"Numerology is set, but the channel bandwidth not yet, so the number of RBs "
285 "cannot be updated now.");
298 NS_LOG_FUNCTION(
this);
299 m_symbolsPerSlot = symbolsPerSlot;
300 m_symbolPeriod = (m_slotPeriod / m_symbolsPerSlot);
318 return m_symbolsPerSlot;
324 NS_ABORT_IF(m_slotPeriod.IsNegative());
331 NS_LOG_FUNCTION(
this);
338 NS_LOG_FUNCTION(
this);
344 NS_LOG_FUNCTION(
this);
351 it =
m_packetBurstMap.insert(std::make_pair(key, CreateObject<PacketBurst>())).first;
353 it->second->AddPacket(p);
354 NS_LOG_INFO(
"Adding a packet for the Packet Burst of " << sfn <<
" at sym " << +symStart
361 NS_LOG_FUNCTION(
this);
367 NS_LOG_FUNCTION(
this);
369 Ptr<PacketBurst> pburst;
376 NS_LOG_WARN(
"Packet burst not found for " << sfn <<
" at sym " << +sym);
402 m_powerAllocationType);
408 NS_LOG_FUNCTION(
this);
409 NS_ABORT_IF(m_centralFrequency < 0.0);
410 return m_centralFrequency;
416 static std::unordered_map<LteNrTddSlotType, std::string, std::hash<int>> lookupTable = {
422 std::stringstream ss;
424 for (
const auto& v : pattern)
426 ss << lookupTable[v] <<
"|";
435 m_powerAllocationType = powerAllocationType;
438enum NrSpectrumValueHelper::PowerAllocationType
441 return m_powerAllocationType;
447 NS_LOG_FUNCTION(
this);
449 m_controlMessageQueue.at(m_controlMessageQueue.size() - 1).push_back(m);
455 NS_LOG_FUNCTION(
this);
457 m_controlMessageQueue.at(0).push_back(msg);
463 for (
const auto& msg : listOfMsgs)
465 m_controlMessageQueue.at(0).push_back(msg);
472 NS_LOG_FUNCTION(
this);
491 for (
const auto& v : pattern)
504 for (
const auto& v : pattern)
524 return m_channelBandwidth * 1000 * 100;
530 return m_subcarrierSpacing;
536 NS_LOG_FUNCTION(
this);
537 NS_ABORT_MSG_IF(m_channelBandwidth == 0,
"Channel bandwidth not set");
544 "Bandwidth and numerology not correctly set. Bandwidth after reduction of overhead is :"
545 << realBw <<
", while RB width is: " << rbWidth);
547 m_rbNum =
static_cast<uint32_t
>(realBw / rbWidth);
550 NS_LOG_INFO(
"Updated RbNum to " <<
GetRbNum());
566 NS_LOG_WARN(
"Working without channel (i.e., under test)");
568 NS_LOG_DEBUG(
"Noise Power Spectral Density updated");
577 for (
const auto& v : pattern)
595 return !(anUl ^ aDl);
601 NS_LOG_FUNCTION(
this);
602 m_controlMessageQueue.clear();
606 m_controlMessageQueue.emplace_back();
610std::list<Ptr<NrControlMessage>>
613 NS_LOG_FUNCTION(
this);
614 if (m_controlMessageQueue.empty())
616 std::list<Ptr<NrControlMessage>> emptylist;
620 if (!m_controlMessageQueue.at(0).empty())
622 std::list<Ptr<NrControlMessage>> ret = m_controlMessageQueue.front();
623 m_controlMessageQueue.erase(m_controlMessageQueue.begin());
624 std::list<Ptr<NrControlMessage>> newlist;
625 m_controlMessageQueue.push_back(newlist);
630 m_controlMessageQueue.erase(m_controlMessageQueue.begin());
631 std::list<Ptr<NrControlMessage>> newlist;
632 m_controlMessageQueue.push_back(newlist);
633 std::list<Ptr<NrControlMessage>> emptylist;
641 NS_LOG_FUNCTION(
this);
678 NS_LOG_FUNCTION(
this);
685 NS_LOG_FUNCTION(
this);
687 NS_LOG_DEBUG(
"setting info for slot " << slotAllocInfo.
m_sfnSf);
690 bool updated =
false;
691 for (
auto& alloc : m_slotAllocInfo)
693 if (alloc.m_sfnSf == slotAllocInfo.
m_sfnSf)
695 NS_LOG_DEBUG(
"Merging inside existing allocation");
696 alloc.Merge(slotAllocInfo);
703 m_slotAllocInfo.push_back(slotAllocInfo);
704 m_slotAllocInfo.sort();
705 NS_LOG_DEBUG(
"Pushing allocation at the end of the list");
708 std::stringstream output;
710 for (
const auto& alloc : m_slotAllocInfo)
714 NS_LOG_DEBUG(output.str());
720 NS_LOG_FUNCTION(
this);
722 m_slotAllocInfo.push_front(slotAllocInfo);
723 SfnSf currentSfn = newSfnSf;
724 std::unordered_map<uint64_t, Ptr<PacketBurst>>
726 std::unordered_map<uint64_t, uint64_t> sfnMap;
731 for (
auto it = m_slotAllocInfo.begin(); it != m_slotAllocInfo.end(); ++it)
733 auto slotSfn = it->m_sfnSf;
734 for (
const auto& alloc : it->m_varTtiAllocInfo)
738 Ptr<PacketBurst> pburst =
739 GetPacketBurst(slotSfn, alloc.m_dci->m_symStart, alloc.m_dci->m_rnti);
740 if (pburst && pburst->GetNPackets() > 0)
743 alloc.m_dci->m_rnti);
744 auto oldKey = it->m_sfnSf.GetEncodingWithSymStartRnti(alloc.m_dci->m_symStart,
745 alloc.m_dci->m_rnti);
746 newBursts.insert({newKey, pburst});
747 sfnMap.insert({newKey, oldKey});
751 NS_LOG_INFO(
"No packet burst found for " << slotSfn);
756 NS_LOG_INFO(
"Set slot allocation for " << it->m_sfnSf <<
" to " << currentSfn);
757 it->m_sfnSf = currentSfn;
761 for (
const auto& burstPair : newBursts)
768 NS_LOG_INFO(
"PacketBurst with " << burstPair.second->GetNPackets() <<
"packets for SFN "
769 << old <<
" now moved to SFN " << latest);
776 NS_LOG_FUNCTION(
this);
778 for (
const auto& alloc : m_slotAllocInfo)
780 if (alloc.m_sfnSf == retVal)
791 NS_LOG_FUNCTION(
this);
793 m_slotAllocInfo.erase(m_slotAllocInfo.begin());
800 NS_LOG_FUNCTION(
" slot " << sfnsf);
803 for (
auto allocIt = m_slotAllocInfo.begin(); allocIt != m_slotAllocInfo.end(); ++allocIt)
805 if (allocIt->m_sfnSf == sfnsf)
808 m_slotAllocInfo.erase(allocIt);
813 NS_FATAL_ERROR(
"Didn't found the slot");
820 NS_LOG_FUNCTION(
this);
822 for (
auto& alloc : m_slotAllocInfo)
824 if (alloc.m_sfnSf == sfnsf)
830 NS_FATAL_ERROR(
"Didn't found the slot");
836 NS_LOG_FUNCTION(
this);
837 return m_slotAllocInfo.size();
843 NS_LOG_FUNCTION(
this);
844 return m_controlMessageQueue.empty() || m_controlMessageQueue.at(0).empty();
847Ptr<const SpectrumModel>
850 NS_LOG_FUNCTION(
this);
852 NS_ABORT_MSG_IF(m_channelBandwidth == 0,
"Channel bandwidth not set.");
861 NS_LOG_FUNCTION(
this);
862 return m_symbolPeriod;
885 m_tbDecodeLatencyUs = us;
891 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.