diff --git a/src/lte/examples/lena-first-sim.cc b/src/lte/examples/lena-first-sim.cc index 27c381115..a0149bb6d 100644 --- a/src/lte/examples/lena-first-sim.cc +++ b/src/lte/examples/lena-first-sim.cc @@ -23,29 +23,11 @@ #include "ns3/network-module.h" #include "ns3/mobility-module.h" #include "ns3/lte-module.h" -#include "ns3/config-store.h" - +//#include "ns3/gtk-config-store.h" using namespace ns3; int main (int argc, char *argv[]) { - - - - - CommandLine cmd; - cmd.Parse (argc, argv); - - // to save a template default attribute file run it like this: - // ./waf --command-template="%s --ns3::ConfigStore::Filename=input-defaults.txt --ns3::ConfigStore::Mode=Save --ns3::ConfigStore::FileFormat=RawText" --run src/lte/examples/lena-first-sim - // - // to load a previously created default attribute file - // ./waf --command-template="%s --ns3::ConfigStore::Filename=input-defaults.txt --ns3::ConfigStore::Mode=Load --ns3::ConfigStore::FileFormat=RawText" --run src/lte/examples/lena-first-sim - // note that the latter will override any of the defaults set via command-line arguments - // - ConfigStore inputConfig; - inputConfig.ConfigureDefaults (); - LenaHelper lena; lena.EnableLogComponents (); @@ -84,6 +66,9 @@ int main (int argc, char *argv[]) Simulator::Run (); + //GtkConfigStore config; + //config.ConfigureAttributes (); + Simulator::Destroy (); return 0; } diff --git a/src/lte/model/lte-amc.h b/src/lte/model/lte-amc.h index 01a4453c9..3c01fdcdb 100644 --- a/src/lte/model/lte-amc.h +++ b/src/lte/model/lte-amc.h @@ -83,7 +83,6 @@ public: */ static std::vector CreateCqiFeedbacks (const SpectrumValue& sinr); -private: /** * \brief Get a proper CQI for the spectrale efficiency value. * In order to assure a fewer block error rate, the AMC chooses the lower CQI value diff --git a/src/lte/model/lte-common.cc b/src/lte/model/lte-common.cc index 6199186ac..0e830a7f2 100644 --- a/src/lte/model/lte-common.cc +++ b/src/lte/model/lte-common.cc @@ -16,10 +16,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Manuel Requena + * Author: Marco Miozzo */ #include "lte-common.h" +#include +NS_LOG_COMPONENT_DEFINE ("LteFfConverter"); namespace ns3 { @@ -47,5 +50,31 @@ operator < (const lteFlowId_t& a, const lteFlowId_t& b) } +uint16_t +LteFfConverter::double2fpS11dot3(double val) +{ + // convert from double to fixed point notation Sxxxxxxxxxxx.xxx + int16_t valFp = (int16_t)(val * pow (2, 3)); + return (valFp); +} + +double +LteFfConverter::fpS11dot3toDouble(uint16_t val) +{ + // convert from fixed point notation Sxxxxxxxxxxx.xxx to double + double valD = ((int16_t)val) / pow (2, 3); + return (valD); +} + +double +LteFfConverter::getMinFpS11dot3Value () +{ + return (-4096); // -4096 = 0x8000 = 1000 0000 0000 0000 b +} + +//static double g_lowestFpS11dot3Value = -4096; // 0x8001 (1000 0000 0000 0000) + + + }; // namespace ns3 diff --git a/src/lte/model/lte-common.h b/src/lte/model/lte-common.h index 18149f54f..ab675d5bd 100644 --- a/src/lte/model/lte-common.h +++ b/src/lte/model/lte-common.h @@ -16,11 +16,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Manuel Requena + * Author: Marco Miozzo */ #ifndef LTE_COMMON_H #define LTE_COMMON_H #include "ns3/uinteger.h" +#include namespace ns3 { @@ -38,6 +40,19 @@ public: friend bool operator < (const lteFlowId_t &a, const lteFlowId_t &b); }; +class LteFfConverter +{ + +public: + static uint16_t double2fpS11dot3 (double val); + static double fpS11dot3toDouble (uint16_t val); + static double getMinFpS11dot3Value (); + + //static const double MIN_FP_S11DOT3_VALUE = -4096; + + +}; + }; // namespace ns3 diff --git a/src/lte/model/lte-enb-phy.cc b/src/lte/model/lte-enb-phy.cc index 801732a39..587fee350 100644 --- a/src/lte/model/lte-enb-phy.cc +++ b/src/lte/model/lte-enb-phy.cc @@ -33,6 +33,7 @@ #include "ideal-control-messages.h" #include "lte-enb-net-device.h" #include "lte-enb-mac.h" +#include NS_LOG_COMPONENT_DEFINE ("LteEnbPhy"); @@ -419,8 +420,11 @@ LteEnbPhy::CreateUlCqiReport (const SpectrumValue& sinr) int i = 0; for (it = sinr.ConstValuesBegin (); it != sinr.ConstValuesEnd (); it++) { - ulcqi.m_sinr.push_back ((*it)); - //NS_LOG_DEBUG(this << " RB " << i << " SINR " << (*it)); + double sinrdb = 10*log10 ((*it)); + // convert from double to fixed point notation Sxxxxxxxxxxx.xxx + int16_t sinrFp = LteFfConverter::double2fpS11dot3 (sinrdb); + ulcqi.m_sinr.push_back (sinrFp); + //NS_LOG_DEBUG(this << " RB " << i << " SINR FP " << sinrFp << " orig " << sinrdb); i++; } return (ulcqi); diff --git a/src/lte/model/pf-ff-mac-scheduler.cc b/src/lte/model/pf-ff-mac-scheduler.cc index 113547105..dab2fe161 100644 --- a/src/lte/model/pf-ff-mac-scheduler.cc +++ b/src/lte/model/pf-ff-mac-scheduler.cc @@ -698,8 +698,36 @@ PfFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched uldci.m_rbStart = rbAllocated; uldci.m_rbLen = rbPerFlow; rbAllocated += rbPerFlow; - uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD - uldci.m_tbSize = (LteAmc::GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD + std::map >::iterator itCqi = m_ueCqi.find ((*it).first); + if (itCqi == m_ueCqi.end ()) + { + // no cqi info about this UE + uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD + //NS_LOG_DEBUG (this << " UE does not have ULCQI " << (*it).first ); + } + else + { + // take the lowest CQI value (worst RB) + double minSinr = (*itCqi).second.at(uldci.m_rbStart); + for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++) + { + //NS_LOG_DEBUG (this << " UE " << (*it).first << " has CQI " << (*itCqi).second.at(i)); + if ((*itCqi).second.at(i) < minSinr) + { + minSinr = (*itCqi).second.at(i); + } + } + + // translate SINR -> cqi: WILD ACK: same as DL + double s = log2 ( 1 + ( + pow (10, minSinr / 10 ) / + ( (-log (5.0 * 0.00005 )) / 1.5) )); + int cqi = LteAmc::GetCqiFromSpectralEfficiency (s); + uldci.m_mcs = LteAmc::GetMcsFromCqi (cqi); + //NS_LOG_DEBUG (this << " UE " << (*it).first << " minsinr " << minSinr << " -> mcs " << (uint16_t)uldci.m_mcs); + + } + uldci.m_tbSize = (LteAmc::GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); uldci.m_ndi = 1; uldci.m_cceIndex = 0; uldci.m_aggrLevel = 1; @@ -784,7 +812,7 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched uint16_t sfnSf = ((0xFF & frameNo) << 4) | (0xF & subframeNo); // retrieve the allocation for this subframe std::map >::iterator itMap; - std::map >::iterator itCqi; + std::map >::iterator itCqi; itMap = m_allocationMaps.find (sfnSf); if (itMap == m_allocationMaps.end()) { @@ -793,33 +821,38 @@ PfFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::Sched } for (uint32_t i = 0; i < (*itMap).second.size (); i++) { - //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINR " << params.m_ulCqi.m_sinr.at (i)); - // fixed point notation Sxxxxxxxxxxx.xxx + // convert from fixed point notation Sxxxxxxxxxxx.xxx to double + double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i)); + //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr); itCqi = m_ueCqi.find ((*itMap).second.at (i)); if (itCqi == m_ueCqi.end ()) { // create a new entry - std::vector newCqi; + std::vector newCqi; for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++) { if (i==j) { - newCqi.push_back (params.m_ulCqi.m_sinr.at (i)); + newCqi.push_back (sinr); } else { - newCqi.push_back (0); // TBD : put the lower possible value + // initialize with minumum values according to the fixed point notation + newCqi.push_back (LteFfConverter::getMinFpS11dot3Value ()); } } + m_ueCqi.insert (std::pair > ((*itMap).second.at (i), newCqi)); } else { // update the value - (*itCqi).second.at (i) = params.m_ulCqi.m_sinr.at (i); + (*itCqi).second.at (i) = sinr; } } + // remove obsolete info on allocation + m_allocationMaps.erase (m_allocationMaps.begin (), ++itMap); return; } diff --git a/src/lte/model/pf-ff-mac-scheduler.h b/src/lte/model/pf-ff-mac-scheduler.h index 4bd021651..8cbe9ef83 100644 --- a/src/lte/model/pf-ff-mac-scheduler.h +++ b/src/lte/model/pf-ff-mac-scheduler.h @@ -160,7 +160,7 @@ private: /* * Map of UEs' UL-CQI per RBG */ - std::map > m_ueCqi; + std::map > m_ueCqi; /* * Map of UE's buffer status reports received diff --git a/src/lte/model/rr-ff-mac-scheduler.cc b/src/lte/model/rr-ff-mac-scheduler.cc index e4d64456e..987c0f18e 100644 --- a/src/lte/model/rr-ff-mac-scheduler.cc +++ b/src/lte/model/rr-ff-mac-scheduler.cc @@ -207,7 +207,8 @@ RrSchedulerMemberSchedSapProvider::SchedUlCqiInfoReq (const struct SchedUlCqiInf RrFfMacScheduler::RrFfMacScheduler () : m_cschedSapUser (0), - m_schedSapUser (0) + m_schedSapUser (0), + m_schedTtiDelay (2) // WILD ACK: based on a m_macChTtiDelay = 1 { m_cschedSapProvider = new RrSchedulerMemberCschedSapProvider (this); m_schedSapProvider = new RrSchedulerMemberSchedSapProvider (this); @@ -544,7 +545,7 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched int rbAllocated = 0; FfMacSchedSapUser::SchedUlConfigIndParameters ret; - + std::vector rbgAllocationMap; for (it = m_ceBsrRxed.begin (); it != m_ceBsrRxed.end (); it++) { if (rbAllocated + rbPerFlow > m_cschedCellConfig.m_ulBandwidth) @@ -552,12 +553,45 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched // limit to physical resources last resource assignment rbPerFlow = m_cschedCellConfig.m_ulBandwidth - rbAllocated; } + // store info on allocation for managing ul-cqi interpretation + for (int i = 0; i < rbPerFlow; i++) + { + rbgAllocationMap.push_back ((*it).first); + } UlDciListElement_s uldci; uldci.m_rnti = (*it).first; uldci.m_rbStart = rbAllocated; uldci.m_rbLen = rbPerFlow; rbAllocated += rbPerFlow; - uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD + std::map >::iterator itCqi = m_ueCqi.find ((*it).first); + if (itCqi == m_ueCqi.end ()) + { + // no cqi info about this UE + uldci.m_mcs = 0; // MCS 0 -> UL-AMC TBD + //NS_LOG_DEBUG (this << " UE does not have ULCQI " << (*it).first ); + } + else + { + // take the lowest CQI value (worst RB) + double minSinr = (*itCqi).second.at(uldci.m_rbStart); + for (uint16_t i = uldci.m_rbStart; i < uldci.m_rbStart + uldci.m_rbLen; i++) + { + //NS_LOG_DEBUG (this << " UE " << (*it).first << " has CQI " << (*itCqi).second.at(i)); + if ((*itCqi).second.at(i) < minSinr) + { + minSinr = (*itCqi).second.at(i); + } + } + + // translate SINR -> cqi: WILD ACK: same as DL + double s = log2 ( 1 + ( + pow (10, minSinr / 10 ) / + ( (-log (5.0 * 0.00005 )) / 1.5) )); + int cqi = LteAmc::GetCqiFromSpectralEfficiency (s); + uldci.m_mcs = LteAmc::GetMcsFromCqi (cqi); + //NS_LOG_DEBUG (this << " UE " << (*it).first << " minsinr " << minSinr << " -> mcs " << (uint16_t)uldci.m_mcs); + + } uldci.m_tbSize = (LteAmc::GetTbSizeFromMcs (uldci.m_mcs, rbPerFlow) / 8); // MCS 0 -> UL-AMC TBD uldci.m_ndi = 1; uldci.m_cceIndex = 0; @@ -573,6 +607,7 @@ RrFfMacScheduler::DoSchedUlTriggerReq (const struct FfMacSchedSapProvider::Sched uldci.m_pdcchPowerOffset = 0; // not used ret.m_dciList.push_back (uldci); } + m_allocationMaps.insert (std::pair > (params.m_sfnSf, rbgAllocationMap)); m_schedSapUser->SchedUlConfigInd (ret); return; } @@ -628,7 +663,62 @@ void RrFfMacScheduler::DoSchedUlCqiInfoReq (const struct FfMacSchedSapProvider::SchedUlCqiInfoReqParameters& params) { NS_LOG_FUNCTION (this); - // TODO: Implementation of the API + //NS_LOG_DEBUG (this << " RX UL CQI at " << params.m_sfnSf); + // correlate info on UL-CQIs with previous scheduling -> calculate m_sfnSf of transmission + uint32_t frameNo = (0xFF & params.m_sfnSf) >> 4; + uint32_t subframeNo = (0xF & params.m_sfnSf); + //NS_LOG_DEBUG (this << " sfn " << frameNo << " sbfn " << subframeNo); + if (subframeNo - m_schedTtiDelay < 0) + { + frameNo--; + } + subframeNo = (subframeNo - m_schedTtiDelay) % 10; + //NS_LOG_DEBUG (this << " Actual sfn " << frameNo << " sbfn " << subframeNo); + uint16_t sfnSf = ((0xFF & frameNo) << 4) | (0xF & subframeNo); + // retrieve the allocation for this subframe + std::map >::iterator itMap; + std::map >::iterator itCqi; + itMap = m_allocationMaps.find (sfnSf); + if (itMap == m_allocationMaps.end()) + { + NS_LOG_DEBUG (this << " Does not find info on allocation"); + return; + } + for (uint32_t i = 0; i < (*itMap).second.size (); i++) + { + // convert from fixed point notation Sxxxxxxxxxxx.xxx to double + double sinr = LteFfConverter::fpS11dot3toDouble (params.m_ulCqi.m_sinr.at (i)); + //NS_LOG_DEBUG (this << " UE " << (*itMap).second.at (i) << " SINRfp " << params.m_ulCqi.m_sinr.at (i) << " sinrdb " << sinr); + itCqi = m_ueCqi.find ((*itMap).second.at (i)); + if (itCqi == m_ueCqi.end ()) + { + // create a new entry + std::vector newCqi; + for (uint32_t j = 0; j < m_cschedCellConfig.m_ulBandwidth; j++) + { + if (i==j) + { + newCqi.push_back (sinr); + } + else + { + // initialize with minumum values according to the fixed point notation + newCqi.push_back (LteFfConverter::getMinFpS11dot3Value ()); + } + + } + m_ueCqi.insert (std::pair > ((*itMap).second.at (i), newCqi)); + } + else + { + // update the value + (*itCqi).second.at (i) = sinr; + } + + } + // remove obsolete info on allocation + m_allocationMaps.erase (m_allocationMaps.begin (), ++itMap); + return; } diff --git a/src/lte/model/rr-ff-mac-scheduler.h b/src/lte/model/rr-ff-mac-scheduler.h index 3938d083c..855ea2bd4 100644 --- a/src/lte/model/rr-ff-mac-scheduler.h +++ b/src/lte/model/rr-ff-mac-scheduler.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace ns3 { @@ -127,7 +128,19 @@ private: /* * Map of UE's DL CQI P01 received */ - std::map m_p10CqiRxed; + std::map m_p10CqiRxed; + + /* + * Map of previous allocated UE per RBG + * (used to retrieve info from UL-CQI) + */ + std::map > m_allocationMaps; + + /* + * Map of UEs' UL-CQI per RBG + */ + std::map > m_ueCqi; + /* @@ -144,6 +157,8 @@ private: // Internal parameters FfMacCschedSapProvider::CschedCellConfigReqParameters m_cschedCellConfig; + + uint8_t m_schedTtiDelay; // delay between scheduling and reception (based on m_macChTtiDelay) };