created tti_point type and unit test. Added also the tti_point to the scheduler harqs, and rrc procedure

master
Francisco Paisana 5 years ago committed by Francisco Paisana
parent e824cbd251
commit 5330249625

@ -0,0 +1,122 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef SRSLTE_TTI_POINT_H
#define SRSLTE_TTI_POINT_H
#include "logmap.h"
#include <cstdint>
#include <limits>
namespace srslte {
struct tti_point {
constexpr tti_point() = default;
explicit tti_point(uint32_t tti_val_) : tti_val(tti_val_ % 10240)
{
if (tti_val_ > std::numeric_limits<uint32_t>::max() / 2) {
// there was a overflow at tti initialization
uint32_t diff = std::numeric_limits<uint32_t>::max() - tti_val_;
if (diff < 10240) {
tti_val = 10240 - diff - 1;
} else {
srslte::logmap::get("COMMON")->error("Invalid TTI point assigned\n");
}
}
}
void reset() { tti_val = std::numeric_limits<uint32_t>::max(); }
uint32_t sf_idx() const { return tti_val % 10; }
uint32_t sfn() const { return tti_val / 10; }
// comparison operators
bool operator==(const tti_point& other) const { return tti_val == other.tti_val; }
bool operator!=(const tti_point& other) const { return tti_val != other.tti_val; }
bool operator<(const tti_point& other) const
{
bool lower_val = tti_val < other.tti_val;
bool wrap_flag = (lower_val ? other.tti_val - tti_val : tti_val - other.tti_val) > 10240 / 2;
return (lower_val != wrap_flag);
}
bool operator<=(const tti_point& other) const { return *this == other or *this < other; }
bool operator>(const tti_point& other) const { return not(*this <= other); }
bool operator>=(const tti_point& other) const { return not(*this < other); }
// add/subtract
int operator-(const tti_point& other) const
{
int diff = static_cast<int>(tti_val) - static_cast<int>(other.tti_val);
if (diff > 10240 / 2) {
return diff - 10240;
}
if (diff < -10240 / 2) {
return diff + 10240;
}
return diff;
}
tti_point& operator+=(uint32_t jump)
{
tti_val = (tti_val + jump) % 10240;
return *this;
}
tti_point& operator-=(uint32_t jump)
{
tti_val -= jump - ((tti_val < jump) ? 10240 : 0);
return *this;
}
tti_point& operator++() { return this->operator+=(1); }
tti_point operator++(int)
{
tti_point ret{tti_val};
this-> operator+=(1);
return ret;
}
bool is_valid() const { return tti_val < 10240; }
explicit operator uint32_t() const { return tti_val; }
uint32_t to_uint() const { return tti_val; }
bool is_in_interval(tti_point l, tti_point u) const { return (*this >= l and *this <= u); }
private:
uint32_t tti_val = std::numeric_limits<uint32_t>::max();
};
inline tti_point operator+(tti_point tti, uint32_t jump)
{
return tti_point{(uint32_t)tti + jump};
}
inline tti_point operator+(uint32_t jump, tti_point tti)
{
return tti_point{(uint32_t)tti + jump};
}
inline tti_point operator-(tti_point tti, uint32_t jump)
{
return tti_point{(uint32_t)tti + 10240 - jump};
}
inline tti_point max(tti_point tti1, tti_point tti2)
{
return tti1 > tti2 ? tti1 : tti2;
}
inline tti_point min(tti_point tti1, tti_point tti2)
{
return tti1 < tti2 ? tti1 : tti2;
}
} // namespace srslte
#endif // SRSLTE_TTI_POINT_H

@ -91,3 +91,7 @@ add_test(network_utils_test network_utils_test)
add_executable(test_common_test test_common_test.cc)
target_link_libraries(test_common_test srslte_common)
add_test(test_common_test test_common_test)
add_executable(tti_point_test tti_point_test.cc)
target_link_libraries(tti_point_test srslte_common)
add_test(tti_point_test tti_point_test)

@ -0,0 +1,82 @@
/*
* Copyright 2013-2019 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/common/test_common.h"
#include "srslte/common/tti_point.h"
using srslte::tti_point;
int test_tti_type()
{
// TEST: constructors
tti_point tti1;
TESTASSERT(not tti1.is_valid());
tti1 = tti_point{5};
TESTASSERT(tti1.is_valid());
// TEST: operators
TESTASSERT(tti1 != tti_point{2});
TESTASSERT(tti1 == tti_point{5});
TESTASSERT(tti1 <= tti_point{5});
TESTASSERT(tti1 >= tti_point{5});
TESTASSERT(tti1 < tti_point{6});
TESTASSERT(tti1 > tti_point{4});
TESTASSERT(tti1 - tti_point{2} == 3);
TESTASSERT(tti1++ == tti_point{5});
TESTASSERT(tti1 == tti_point{6});
TESTASSERT(++tti1 == tti_point{7});
// TEST: wrap arounds
TESTASSERT(tti_point{10239} - tti_point{1} == -2);
TESTASSERT(tti_point{10239} < tti_point{1});
TESTASSERT(tti_point{10238} - tti_point{10239} == -1);
TESTASSERT(tti_point{10238} < tti_point{10239});
TESTASSERT(tti_point{10239} - tti_point{10238} == 1);
TESTASSERT(tti_point{10239} > tti_point{10238});
TESTASSERT(tti_point{1} - tti_point{10239} == 2);
TESTASSERT(tti_point{1} > tti_point{10239});
tti1 = tti_point{10239};
TESTASSERT(tti1++ == tti_point{10239});
TESTASSERT(tti1 == tti_point{0});
// TEST: tti skips
tti1 = tti_point{10239};
tti1 += 10;
TESTASSERT(tti1 == tti_point{9});
tti1 -= 11;
TESTASSERT(tti1 == tti_point{10238});
tti1 -= 10237;
TESTASSERT(tti1 == (tti_point)1);
// TEST: wrap initializations
TESTASSERT(tti_point{1u - 2u} == tti_point{10239});
TESTASSERT(tti_point{1u - 100u} == tti_point{10141});
TESTASSERT(tti_point{10239u + 3u} == tti_point{2});
return SRSLTE_SUCCESS;
}
int main()
{
TESTASSERT(test_tti_type() == SRSLTE_SUCCESS);
return 0;
}

@ -24,6 +24,7 @@
#include "srslte/common/bounded_bitset.h"
#include "srslte/common/log.h"
#include "srslte/common/tti_point.h"
#include "srslte/interfaces/sched_interface.h"
#include <map>
@ -41,13 +42,13 @@ public:
uint32_t nof_tx(uint32_t tb_idx) const;
uint32_t nof_retx(uint32_t tb_idx) const;
uint32_t get_tti() const;
srslte::tti_point get_tti() const;
bool get_ndi(uint32_t tb_idx) const;
uint32_t max_nof_retx() const;
protected:
void new_tx_common(uint32_t tb_idx, uint32_t tti, int mcs, int tbs);
void new_retx_common(uint32_t tb_idx, uint32_t tti, int* mcs, int* tbs);
void new_tx_common(uint32_t tb_idx, srslte::tti_point tti, int mcs, int tbs);
void new_retx_common(uint32_t tb_idx, srslte::tti_point tti, int* mcs, int* tbs);
bool has_pending_retx_common(uint32_t tb_idx) const;
void set_ack_common(uint32_t tb_idx, bool ack);
void reset_pending_data_common();
@ -61,7 +62,7 @@ protected:
uint32_t max_retx = 5;
uint32_t n_rtx[SRSLTE_MAX_TB];
uint32_t tx_cnt[SRSLTE_MAX_TB];
int tti;
srslte::tti_point tti;
int last_mcs[SRSLTE_MAX_TB];
int last_tbs[SRSLTE_MAX_TB];

@ -30,6 +30,8 @@
#define Info(fmt, ...) log_h->info(fmt, ##__VA_ARGS__)
#define Debug(fmt, ...) log_h->debug(fmt, ##__VA_ARGS__)
using srslte::tti_point;
namespace srsenb {
/******************************************************
@ -55,7 +57,7 @@ void harq_proc::reset(uint32_t tb_idx)
ack_state[tb_idx] = NULL_ACK;
active[tb_idx] = false;
n_rtx[tb_idx] = 0;
tti = 0;
tti = tti_point{0};
last_mcs[tb_idx] = -1;
last_tbs[tb_idx] = -1;
tx_cnt[tb_idx] = 0;
@ -86,9 +88,9 @@ bool harq_proc::has_pending_retx_common(uint32_t tb_idx) const
return !is_empty(tb_idx) && ack_state[tb_idx] == NACK;
}
uint32_t harq_proc::get_tti() const
tti_point harq_proc::get_tti() const
{
return (uint32_t)tti;
return tti;
}
void harq_proc::set_ack_common(uint32_t tb_idx, bool ack_)
@ -96,15 +98,18 @@ void harq_proc::set_ack_common(uint32_t tb_idx, bool ack_)
ack_state[tb_idx] = ack_ ? ACK : NACK;
log_h->debug("ACK=%d received pid=%d, tb_idx=%d, n_rtx=%d, max_retx=%d\n", ack_, id, tb_idx, n_rtx[tb_idx], max_retx);
if (!ack_ && (n_rtx[tb_idx] + 1 >= max_retx)) {
Warning(
"SCHED: discarding TB %d pid=%d, tti=%d, maximum number of retx exceeded (%d)\n", tb_idx, id, tti, max_retx);
Warning("SCHED: discarding TB %d pid=%d, tti=%d, maximum number of retx exceeded (%d)\n",
tb_idx,
id,
tti.to_uint(),
max_retx);
active[tb_idx] = false;
} else if (ack_) {
active[tb_idx] = false;
}
}
void harq_proc::new_tx_common(uint32_t tb_idx, uint32_t tti_, int mcs, int tbs)
void harq_proc::new_tx_common(uint32_t tb_idx, tti_point tti_, int mcs, int tbs)
{
reset(tb_idx);
ndi[tb_idx] = !ndi[tb_idx];
@ -116,7 +121,7 @@ void harq_proc::new_tx_common(uint32_t tb_idx, uint32_t tti_, int mcs, int tbs)
active[tb_idx] = true;
}
void harq_proc::new_retx_common(uint32_t tb_idx, uint32_t tti_, int* mcs, int* tbs)
void harq_proc::new_retx_common(uint32_t tb_idx, tti_point tti_, int* mcs, int* tbs)
{
ack_state[tb_idx] = NACK;
tti = tti_;
@ -172,7 +177,7 @@ void dl_harq_proc::new_tx(const rbgmask_t& new_mask, uint32_t tb_idx, uint32_t t
{
n_cce = n_cce_;
rbgmask = new_mask;
new_tx_common(tb_idx, tti, mcs, tbs);
new_tx_common(tb_idx, tti_point{tti}, mcs, tbs);
}
void dl_harq_proc::new_retx(const rbgmask_t& new_mask,
@ -184,7 +189,7 @@ void dl_harq_proc::new_retx(const rbgmask_t& new_mask,
{
n_cce = n_cce_;
rbgmask = new_mask;
new_retx_common(tb_idx, tti_, mcs, tbs);
new_retx_common(tb_idx, tti_point{tti_}, mcs, tbs);
}
void dl_harq_proc::set_ack(uint32_t tb_idx, bool ack)
@ -204,8 +209,7 @@ rbgmask_t dl_harq_proc::get_rbgmask() const
bool dl_harq_proc::has_pending_retx(uint32_t tb_idx, uint32_t tti_tx_dl) const
{
uint32_t tti_diff = srslte_tti_interval(tti_tx_dl, tti);
return (tti_diff < (10240 / 2)) and (tti_diff >= FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS) and
return (tti_point{tti_tx_dl} >= tti + FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS) and
has_pending_retx_common(tb_idx);
}
@ -243,7 +247,7 @@ void ul_harq_proc::new_tx(uint32_t tti_, int mcs, int tbs, ul_harq_proc::ul_allo
max_retx = (uint32_t)max_retx_;
is_adaptive = false;
allocation = alloc;
new_tx_common(0, tti_, mcs, tbs);
new_tx_common(0, tti_point{tti_}, mcs, tbs);
pending_data = tbs;
pending_ack = NULL_ACK;
}
@ -252,7 +256,7 @@ void ul_harq_proc::new_retx(uint32_t tb_idx, uint32_t tti_, int* mcs, int* tbs,
{
is_adaptive = alloc.L != allocation.L or alloc.RB_start != allocation.RB_start;
allocation = alloc;
new_retx_common(tb_idx, tti_, mcs, tbs);
new_retx_common(tb_idx, tti_point{tti_}, mcs, tbs);
}
void ul_harq_proc::set_ack(uint32_t tb_idx, bool ack_)
@ -349,7 +353,7 @@ dl_harq_proc* harq_entity::get_pending_dl_harq(uint32_t tti_tx_dl)
std::pair<uint32_t, int> harq_entity::set_ack_info(uint32_t tti_rx, uint32_t tb_idx, bool ack)
{
for (auto& h : dl_harqs) {
if (TTI_ADD(h.get_tti(), FDD_HARQ_DELAY_DL_MS) == tti_rx) {
if (h.get_tti() + FDD_HARQ_DELAY_DL_MS == tti_point{tti_rx}) {
h.set_ack(tb_idx, ack);
return {h.get_id(), h.get_tbs(tb_idx)};
}
@ -364,11 +368,11 @@ ul_harq_proc* harq_entity::get_ul_harq(uint32_t tti_tx_ul)
void harq_entity::reset_pending_data(uint32_t tti_rx)
{
uint32_t tti_tx_ul = TTI_ADD(tti_rx, (FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS));
uint32_t tti_tx_dl = TTI_ADD(tti_rx, FDD_HARQ_DELAY_UL_MS);
tti_point tti_tx_ul = tti_point{tti_rx} + FDD_HARQ_DELAY_UL_MS + FDD_HARQ_DELAY_DL_MS;
tti_point tti_tx_dl = tti_point{tti_rx} + FDD_HARQ_DELAY_UL_MS;
// Reset ACK state of UL Harq
get_ul_harq(tti_tx_ul)->reset_pending_data();
get_ul_harq(tti_tx_ul.to_uint())->reset_pending_data();
// Reset any DL harq which has 0 retxs
for (auto& h : dl_harqs) {
@ -378,10 +382,11 @@ void harq_entity::reset_pending_data(uint32_t tti_rx)
// delete old DL harq procs
for (auto& h : dl_harqs) {
if (not h.is_empty()) {
uint32_t tti_diff = srslte_tti_interval(tti_tx_dl, h.get_tti());
if (tti_diff > 100 and tti_diff < 10240 / 2) {
srslte::logmap::get("MAC")->info(
"SCHED: pid=%d is old. tti_pid=%d, now is %d, resetting\n", h.get_id(), h.get_tti(), tti_tx_dl);
if (tti_tx_dl > h.get_tti() + 100) {
srslte::logmap::get("MAC")->info("SCHED: pid=%d is old. tti_pid=%d, now is %d, resetting\n",
h.get_id(),
h.get_tti().to_uint(),
tti_tx_dl.to_uint());
for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
h.reset(tb);
}
@ -397,11 +402,12 @@ void harq_entity::reset_pending_data(uint32_t tti_rx)
*/
dl_harq_proc* harq_entity::get_oldest_dl_harq(uint32_t tti_tx_dl)
{
tti_point t_tx_dl{tti_tx_dl};
int oldest_idx = -1;
uint32_t oldest_tti = 0;
for (const dl_harq_proc& h : dl_harqs) {
if (h.has_pending_retx(0, tti_tx_dl) or h.has_pending_retx(1, tti_tx_dl)) {
uint32_t x = srslte_tti_interval(tti_tx_dl, h.get_tti());
uint32_t x = t_tx_dl - h.get_tti();
if (x > oldest_tti) {
oldest_idx = h.get_id();
oldest_tti = x;

@ -41,6 +41,8 @@
#include "scheduler_test_utils.h"
#include "srslte/common/test_common.h"
using srslte::tti_point;
/********************************************************
* Random Tester for Scheduler.
* Current Checks:
@ -285,7 +287,7 @@ int sched_tester::test_harqs()
uint16_t rnti = data.dci.rnti;
const srsenb::dl_harq_proc& h = ue_db[rnti].get_dl_harq(h_id, CARRIER_IDX);
CONDERROR(h.is_empty(), "Cannot schedule an empty harq proc\n");
CONDERROR(h.get_tti() != tti_info.tti_params.tti_tx_dl,
CONDERROR(h.get_tti() != tti_point{tti_info.tti_params.tti_tx_dl},
"The scheduled DL harq pid=%d does not a valid tti=%u\n",
h_id,
tti_info.tti_params.tti_tx_dl);
@ -309,7 +311,7 @@ int sched_tester::test_harqs()
const auto& ue_data = tti_data.ue_data[rnti];
const srsenb::ul_harq_proc* h = ue_db[rnti].get_ul_harq(tti_info.tti_params.tti_tx_ul, CARRIER_IDX);
CONDERROR(h == nullptr or h->is_empty(), "scheduled UL harq does not exist or is empty\n");
CONDERROR(h->get_tti() != tti_info.tti_params.tti_tx_ul,
CONDERROR(h->get_tti() != tti_point{tti_info.tti_params.tti_tx_ul},
"The scheduled UL harq does not a valid tti=%u\n",
tti_info.tti_params.tti_tx_ul);
CONDERROR(h->has_pending_ack(), "At the end of the TTI, there shouldnt be any pending ACKs\n");
@ -361,8 +363,7 @@ int sched_tester::test_harqs()
for (auto& user : ue_db) {
for (int i = 0; i < srsenb::sched_ue_carrier::SCHED_MAX_HARQ_PROC; i++) {
if (not user.second.get_dl_harq(i, CARRIER_IDX).is_empty(0)) {
if (srslte_tti_interval(tti_info.tti_params.tti_tx_dl, user.second.get_dl_harq(i, CARRIER_IDX).get_tti()) >
49) {
if (tti_point{tti_info.tti_params.tti_tx_dl} > user.second.get_dl_harq(i, CARRIER_IDX).get_tti() + 49) {
TESTERROR(
"The pid=%d for rnti=0x%x got old.\n", user.second.get_dl_harq(i, CARRIER_IDX).get_id(), user.first);
}

@ -20,6 +20,7 @@
*/
#include "srsue/hdr/stack/rrc/rrc_procedures.h"
#include "srslte/common/tti_point.h"
#include <inttypes.h> // for printing uint64_t
#define Error(fmt, ...) rrc_ptr->rrc_log->error("Proc \"%s\" - " fmt, name(), ##__VA_ARGS__)
@ -30,6 +31,7 @@
namespace srsue {
using srslte::proc_outcome_t;
using srslte::tti_point;
/**************************************
* Cell Search Procedure
@ -303,24 +305,28 @@ void rrc::si_acquire_proc::start_si_acquire()
const uint32_t nof_sib_harq_retxs = 5;
// Instruct MAC to decode SIB (non-blocking)
uint32_t tti = rrc_ptr->mac->get_current_tti();
auto ret = compute_si_window(tti, sib_index, sched_index, period, rrc_ptr->serving_cell->sib1ptr());
uint32_t si_win_start = ret.first, si_win_len = ret.second;
rrc_ptr->mac->bcch_start_rx(si_win_start, si_win_len);
tti_point tti{rrc_ptr->mac->get_current_tti()};
auto ret = compute_si_window(tti.to_uint(), sib_index, sched_index, period, rrc_ptr->serving_cell->sib1ptr());
tti_point si_win_start = tti_point{ret.first};
if (si_win_start < tti) {
Error("The SI Window start was incorrectly calculated. si_win_start=%d, tti=%d\n",
si_win_start.to_uint(),
tti.to_uint());
return;
}
uint32_t si_win_len = ret.second;
rrc_ptr->mac->bcch_start_rx(si_win_start.to_uint(), si_win_len);
// start window retry timer
uint32_t retry_period = (sib_index == 0) ? sib1_periodicity : period * nof_sib_harq_retxs;
uint32_t tics_until_si_win_start = srslte_tti_interval(si_win_start, tti);
if (tics_until_si_win_start > 10240 / 2) {
Error("The SI Window start was incorrectly calculated. si_win_start=%d, tti=%d\n", si_win_start, tti);
}
int tics_until_si_win_start = si_win_start - tti;
uint32_t tics_until_si_retry = retry_period + tics_until_si_win_start;
si_acq_retry_timer.set(tics_until_si_retry);
si_acq_retry_timer.run();
Info("Instructed MAC to search for SIB%d, win_start=%d, win_len=%d, period=%d, sched_index=%d\n",
sib_index + 1,
si_win_start,
si_win_start.to_uint(),
si_win_len,
period,
sched_index);

Loading…
Cancel
Save