mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-15 13:40:29 +00:00
Compare commits
5 Commits
pre-commit
...
oran_fh_mu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44532e7139 | ||
|
|
399544f8fb | ||
|
|
d3836862f5 | ||
|
|
77c0263841 | ||
|
|
8f815255c5 |
@@ -173,7 +173,7 @@ index eccc4ae..a97fdc6 100644
|
||||
CPP_FLAGS_FULL := $(CPP_FLAGS) $(CPP_COMP) $(INC) $(DEF)
|
||||
CPP_FLAGS_FULL_SNC := $(CPP_FLAGS) $(CPP_COMP_SNC) $(INC) $(DEF)
|
||||
diff --git a/fhi_lib/lib/api/xran_fh_o_du.h b/fhi_lib/lib/api/xran_fh_o_du.h
|
||||
index bacf597..1dd6d66 100644
|
||||
index bacf597..1cd8764 100644
|
||||
--- a/fhi_lib/lib/api/xran_fh_o_du.h
|
||||
+++ b/fhi_lib/lib/api/xran_fh_o_du.h
|
||||
@@ -141,7 +141,7 @@ extern "C" {
|
||||
@@ -193,6 +193,15 @@ index bacf597..1dd6d66 100644
|
||||
int32_t bbdev_mode; /**< DPDK for BBDev */
|
||||
uint32_t dpdkIoVaMode; /**< IOVA Mode */
|
||||
uint32_t dpdkMemorySize; /**< DPDK max memory allocation */
|
||||
@@ -555,7 +556,7 @@ struct xran_prb_map {
|
||||
uint16_t tti_id; /**< xRAN slot id [0 - (max tti-1)] */
|
||||
uint8_t start_sym_id; /**< start symbol Id [0-13] */
|
||||
uint32_t nPrbElm; /**< total number of PRB elements for given map [0- (XRAN_MAX_SECTIONS_PER_SLOT-1)] */
|
||||
- struct xran_prb_elm prbMap[1];
|
||||
+ struct xran_prb_elm prbMap[XRAN_MIN_SECTIONS_PER_SLOT];
|
||||
};
|
||||
|
||||
/* PRACH config required for XRAN based FH */
|
||||
@@ -1193,6 +1194,31 @@ int32_t xran_reg_physide_cb_by_dev_id(void *pHandle, xran_fh_tti_callback_fn Cb,
|
||||
*/
|
||||
int32_t xran_get_slot_idx (uint32_t PortId, uint32_t *nFrameIdx, uint32_t *nSubframeIdx, uint32_t *nSlotIdx, uint64_t *nSecond);
|
||||
@@ -688,7 +697,7 @@ index 4498b33..8a2984f 100644
|
||||
/* convert byte order */
|
||||
tmp = (uint64_t *)ext3_f;
|
||||
diff --git a/fhi_lib/lib/src/xran_cp_proc.c b/fhi_lib/lib/src/xran_cp_proc.c
|
||||
index 789c6fd..a768efb 100644
|
||||
index 789c6fd..a3929e1 100644
|
||||
--- a/fhi_lib/lib/src/xran_cp_proc.c
|
||||
+++ b/fhi_lib/lib/src/xran_cp_proc.c
|
||||
@@ -35,7 +35,10 @@
|
||||
@@ -702,6 +711,19 @@ index 789c6fd..a768efb 100644
|
||||
|
||||
#include <rte_common.h>
|
||||
#include <rte_eal.h>
|
||||
@@ -304,6 +307,12 @@ xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int
|
||||
return (-1);
|
||||
}
|
||||
|
||||
+ if(prbMap->nPrbElm == 0)
|
||||
+ {
|
||||
+ print_dbg("No section to process\n");
|
||||
+ return (-1);
|
||||
+ }
|
||||
+
|
||||
if(0== prbElmProcInfo->numSymsRemaining)
|
||||
{ /* new slot */
|
||||
prbElmProcInfo->numSymsRemaining = p_x_ctx->numSymsForDlCP;
|
||||
diff --git a/fhi_lib/lib/src/xran_delay_measurement.c b/fhi_lib/lib/src/xran_delay_measurement.c
|
||||
index 4c943c8..7db51a8 100644
|
||||
--- a/fhi_lib/lib/src/xran_delay_measurement.c
|
||||
|
||||
@@ -177,6 +177,15 @@ uint64_t reverse_bits(uint64_t in, int n_bits)
|
||||
return rev_bits;
|
||||
}
|
||||
|
||||
uint8_t get_first_set_bit_idx(const uint32_t a)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
while (!IS_BIT_SET(a, i) && (i < 32)) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
#define NUM_BW_ENTRIES 15
|
||||
|
||||
static const int tables_5_3_2[5][NUM_BW_ENTRIES] = {
|
||||
@@ -731,14 +740,10 @@ int get_dmrs_port(int nl, uint16_t dmrs_ports)
|
||||
if (dmrs_ports == 0)
|
||||
return 0; // dci 1_0
|
||||
int p = -1;
|
||||
int found = -1;
|
||||
for (int i = 0; i < 12; i++) { // loop over dmrs ports
|
||||
if((dmrs_ports >> i) & 0x01) { // check if current bit is 1
|
||||
found++;
|
||||
if (found == nl) { // found antenna port number corresponding to current layer
|
||||
p = i;
|
||||
break;
|
||||
}
|
||||
p = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AssertFatal(p > -1, "No dmrs port corresponding to layer %d found\n", nl);
|
||||
|
||||
@@ -260,6 +260,7 @@ static __attribute__((always_inline)) inline int count_bits64_with_mask(uint64_t
|
||||
|
||||
uint64_t reverse_bits(uint64_t in, int n_bits);
|
||||
void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out);
|
||||
uint8_t get_first_set_bit_idx(const uint32_t a);
|
||||
|
||||
uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn);
|
||||
uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw);
|
||||
|
||||
@@ -33,7 +33,8 @@ extern "C" {
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
|
||||
|
||||
#define IS_BIT_SET(a,b) ((a >> b) & 1)
|
||||
#define SET_BIT(a,b) (a | (1 << b))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -58,6 +58,7 @@ extern "C"
|
||||
|
||||
#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n"
|
||||
#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n"
|
||||
#define CONFIG_HLP_MU_MIMO "Enable MU-MIMO in phy-test mode\n"
|
||||
#define CONFIG_HLP_DORA "test gNB and UE with RA procedures\n"
|
||||
#define CONFIG_HLP_SA "run gNB in standalone mode\n"
|
||||
#define CONFIG_HLP_SL_MODE "sets the NR sidelink mode (0: not in sidelink mode, 1: in-coverage/gNB, 2: out-of-coverage/no gNB)\n"
|
||||
@@ -123,6 +124,7 @@ extern "C"
|
||||
#define TP_CONFIG softmodem_params.threadPoolConfig
|
||||
#define CONTINUOUS_TX softmodem_params.continuous_tx
|
||||
#define PHY_TEST softmodem_params.phy_test
|
||||
#define MU_MIMO softmodem_params.mu_mimo
|
||||
#define DO_RA softmodem_params.do_ra
|
||||
#define SL_MODE softmodem_params.sl_mode
|
||||
#define CHAIN_OFFSET softmodem_params.chain_offset
|
||||
@@ -152,6 +154,7 @@ extern int usrp_tx_thread;
|
||||
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, .strptr=&RF_CONFIG_FILE, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{"thread-pool", CONFIG_HLP_TPOOL, 0, .strptr=&TP_CONFIG, .defstrval="-1,-1,-1,-1,-1,-1,-1,-1", TYPE_STRING, 0}, \
|
||||
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, .iptr=&PHY_TEST, .defintval=0, TYPE_INT, 0}, \
|
||||
{"mu-mimo", CONFIG_HLP_MU_MIMO, PARAMFLAG_BOOL, .iptr=&MU_MIMO, .defintval=0, TYPE_INT, 0}, \
|
||||
{"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, .iptr=&DO_RA, .defintval=0, TYPE_INT, 0}, \
|
||||
{"sl-mode", CONFIG_HLP_SL_MODE, 0, .u8ptr=&SL_MODE, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{"clock-source", CONFIG_HLP_CLK, 0, .uptr=&CLOCK_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
@@ -218,6 +221,7 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s3a = { config_checkstr_assign_integer, \
|
||||
{"MONOLITHIC", "PNF", "VNF", "AERIAL","UE_STUB_PNF","UE_STUB_OFFNET","STANDALONE_PNF"}, \
|
||||
{NFAPI_MONOLITHIC, NFAPI_MODE_PNF, NFAPI_MODE_VNF, NFAPI_MODE_AERIAL,NFAPI_UE_STUB_PNF,NFAPI_UE_STUB_OFFNET,NFAPI_MODE_STANDALONE_PNF}, \
|
||||
@@ -318,6 +322,7 @@ typedef struct {
|
||||
char *rf_config_file;
|
||||
char *threadPoolConfig;
|
||||
int phy_test;
|
||||
int mu_mimo;
|
||||
int do_ra;
|
||||
uint8_t sl_mode;
|
||||
int emulate_rf;
|
||||
|
||||
@@ -80,14 +80,18 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
uint32_t cset_nsymb = pdcch_pdu_rel15->DurationSymbols;
|
||||
int dci_idx = 0;
|
||||
// multi-beam number (for concurrent beams)
|
||||
int bitmap = SL_to_bitmap(cset_start_symb, pdcch_pdu_rel15->DurationSymbols);
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
bitmap);
|
||||
rb_offset,
|
||||
n_rb,
|
||||
cset_start_symb,
|
||||
cset_nsymb,
|
||||
1,
|
||||
0);
|
||||
|
||||
LOG_D(NR_PHY_DCI, "pdcch: Coreset rb_offset %d, nb_rb %d BWP Start %d\n", rb_offset, n_rb, pdcch_pdu_rel15->BWPStart);
|
||||
LOG_D(NR_PHY_DCI,
|
||||
|
||||
@@ -460,12 +460,14 @@ static inline void do_txdataF(c16_t **txdataF,
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15,
|
||||
int ant,
|
||||
int start_sc,
|
||||
int txdataF_offset_per_symbol)
|
||||
int txdataF_offset_per_symbol,
|
||||
int nl)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
int rb = 0;
|
||||
uint16_t subCarrier = start_sc;
|
||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||
const int dmrs_port = get_dmrs_port(ant, rel15->dmrsPorts);
|
||||
while (rb < rel15->rbSize) {
|
||||
// get pmi info
|
||||
const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0;
|
||||
@@ -477,29 +479,25 @@ static inline void do_txdataF(c16_t **txdataF,
|
||||
const int re_cnt = NR_NB_SC_PER_RB * rb_step;
|
||||
|
||||
if (pmi == 0) { // unitary Precoding
|
||||
if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC
|
||||
if (ant < rel15->nrOfLayers)
|
||||
// For no precoding, use only as many number of antennas as layers
|
||||
// and prevents overwriting txdataF with 0
|
||||
if (ant == dmrs_port) {
|
||||
if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC
|
||||
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
|
||||
&txdataF_precoding[ant][subCarrier],
|
||||
&txdataF_precoding[nl][subCarrier],
|
||||
re_cnt * sizeof(**txdataF));
|
||||
else
|
||||
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF));
|
||||
} else { // RB does cross DC
|
||||
const int neg_length = symbol_sz - subCarrier;
|
||||
const int pos_length = re_cnt - neg_length;
|
||||
if (ant < rel15->nrOfLayers) {
|
||||
} else { // RB does cross DC
|
||||
const int neg_length = symbol_sz - subCarrier;
|
||||
const int pos_length = re_cnt - neg_length;
|
||||
memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier],
|
||||
&txdataF_precoding[ant][subCarrier],
|
||||
&txdataF_precoding[nl][subCarrier],
|
||||
neg_length * sizeof(**txdataF));
|
||||
memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant], pos_length * sizeof(**txdataF));
|
||||
} else {
|
||||
memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF));
|
||||
memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF));
|
||||
memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[nl], pos_length * sizeof(**txdataF));
|
||||
}
|
||||
subCarrier += re_cnt;
|
||||
if (subCarrier >= symbol_sz) {
|
||||
subCarrier -= symbol_sz;
|
||||
}
|
||||
}
|
||||
subCarrier += re_cnt;
|
||||
if (subCarrier >= symbol_sz) {
|
||||
subCarrier -= symbol_sz;
|
||||
}
|
||||
} else { // non-unitary Precoding
|
||||
AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n");
|
||||
@@ -679,14 +677,18 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
start_meas(&gNB->dlsch_precoding_stats);
|
||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||
// beam number in multi-beam scenario (concurrent beams)
|
||||
int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
bitmap);
|
||||
rel15->rbStart,
|
||||
rel15->rbSize,
|
||||
rel15->StartSymbolIndex,
|
||||
rel15->NrOfSymbols,
|
||||
rel15->nrOfLayers,
|
||||
get_first_set_bit_idx(rel15->dmrsPorts));
|
||||
|
||||
c16_t **txdataF = gNB->common_vars.txdataF[beam_nb];
|
||||
|
||||
@@ -760,7 +762,15 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
|
||||
for (int ant = 0; ant < frame_parms->nb_antennas_tx; ant++) {
|
||||
const size_t txdataF_offset_per_symbol = l_symbol * symbol_sz + txdataF_offset;
|
||||
do_txdataF(txdataF, symbol_sz, txdataF_precoding, gNB, rel15, ant, start_sc, txdataF_offset_per_symbol);
|
||||
do_txdataF(txdataF,
|
||||
symbol_sz,
|
||||
txdataF_precoding,
|
||||
gNB,
|
||||
rel15,
|
||||
ant,
|
||||
start_sc,
|
||||
txdataF_offset_per_symbol,
|
||||
ant % rel15->nrOfLayers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,14 +84,19 @@ int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *pr
|
||||
for (int i = 0; i < prach_pdu->beamforming.dig_bf_interface; i++) {
|
||||
int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[i].beam_idx;
|
||||
int start_symb = prach_pdu->prach_start_symbol + i * n_symb;
|
||||
int bitmap = SL_to_bitmap(start_symb, n_symb);
|
||||
prach->beam_nb[i] = beam_index_allocation(gNB->enable_analog_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
Slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
// tmp: no dbf for prach
|
||||
0,
|
||||
273,
|
||||
start_symb,
|
||||
n_symb,
|
||||
1,
|
||||
0);
|
||||
}
|
||||
}
|
||||
LOG_D(NR_PHY,"Copying prach pdu %d bytes to index %d\n", (int)sizeof(*prach_pdu), prach_id);
|
||||
|
||||
@@ -75,14 +75,18 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t
|
||||
ulsch->beam_nb = 0;
|
||||
if (gNB->common_vars.beam_id) {
|
||||
int fapi_beam_idx = ulsch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
|
||||
int bitmap = SL_to_bitmap(ulsch_pdu->start_symbol_index, ulsch_pdu->nr_of_symbols);
|
||||
ulsch->beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
ulsch_pdu->rb_start,
|
||||
ulsch_pdu->rb_size,
|
||||
ulsch_pdu->start_symbol_index,
|
||||
ulsch_pdu->nr_of_symbols,
|
||||
ulsch_pdu->nrOfLayers,
|
||||
get_first_set_bit_idx(ulsch_pdu->dmrs_ports));
|
||||
}
|
||||
ulsch->frame = frame;
|
||||
ulsch->slot = slot;
|
||||
|
||||
@@ -69,14 +69,18 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t
|
||||
pucch->beam_nb = 0;
|
||||
if (gNB->common_vars.beam_id) {
|
||||
int fapi_beam_idx = pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
|
||||
int bitmap = SL_to_bitmap(pucch_pdu->start_symbol_index, pucch_pdu->nr_of_symbols);
|
||||
pucch->beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
pucch_pdu->prb_start,
|
||||
pucch_pdu->prb_size,
|
||||
pucch_pdu->start_symbol_index,
|
||||
pucch_pdu->nr_of_symbols,
|
||||
1,
|
||||
0);
|
||||
}
|
||||
memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t));
|
||||
LOG_D(PHY,
|
||||
|
||||
@@ -57,7 +57,6 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu
|
||||
srs->active = true;
|
||||
srs->beam_nb = 0;
|
||||
if (gNB->common_vars.beam_id) {
|
||||
int bitmap = SL_to_bitmap(srs_pdu->time_start_position, 1 << srs_pdu->num_symbols);
|
||||
int fapi_beam_idx = srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
|
||||
srs->beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
fapi_beam_idx,
|
||||
@@ -65,7 +64,12 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
srs_pdu->bwp_start,
|
||||
srs_pdu->bwp_size,
|
||||
srs_pdu->time_start_position,
|
||||
1 << srs_pdu->num_symbols,
|
||||
1,
|
||||
0);
|
||||
}
|
||||
memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t));
|
||||
break;
|
||||
|
||||
@@ -91,6 +91,22 @@ typedef enum {
|
||||
synch_to_mobipass_standalone // special case for mobipass in standalone mode
|
||||
} node_timing_t;
|
||||
|
||||
struct oai_ofh_section_def {
|
||||
uint16_t start_symbol;
|
||||
uint16_t num_symbols;
|
||||
uint16_t start_prb;
|
||||
uint16_t num_prb;
|
||||
uint16_t re_offset;
|
||||
uint16_t beam_id;
|
||||
uint16_t num_ports;
|
||||
uint16_t start_port;
|
||||
};
|
||||
|
||||
#define NR_MAX_OFH_SECTIONS 6
|
||||
struct oai_ofh_section {
|
||||
uint16_t num_sections;
|
||||
struct oai_ofh_section_def sec[NR_MAX_OFH_SECTIONS];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/// \brief Holds the transmit data in the frequency domain (1 frame).
|
||||
@@ -133,9 +149,10 @@ typedef struct {
|
||||
/// - first index: concurrent beam
|
||||
/// - second index: beam_id [0.. symbols_per_frame[
|
||||
int **beam_id;
|
||||
/// \brief Holds tx data section details relevant for xran interface
|
||||
struct oai_ofh_section tx_sections;
|
||||
} RU_COMMON;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/// \brief Received frequency-domain signal after extraction.
|
||||
/// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
|
||||
|
||||
@@ -291,6 +291,7 @@ typedef struct {
|
||||
bool analog_bf;
|
||||
int32_t *debugBuff;
|
||||
int32_t debugBuff_sample_offset;
|
||||
struct oai_ofh_section tx_sections;
|
||||
} NR_gNB_COMMON;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -94,7 +94,7 @@ void nr_schedule_dl_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_request_t *DL_req
|
||||
|
||||
for (int i = 0; i < number_dl_pdu; i++) {
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i];
|
||||
LOG_D(NR_PHY, "NFAPI: dl_pdu %d : type %d\n", i, dl_tti_pdu->PDUType);
|
||||
LOG_D(NR_PHY, "frame %d, slot %d, NFAPI: dl_pdu %d : type %d\n", frame, slot, i, dl_tti_pdu->PDUType);
|
||||
switch (dl_tti_pdu->PDUType) {
|
||||
case NFAPI_NR_DL_TTI_SSB_PDU_TYPE:
|
||||
handle_nr_nfapi_ssb_pdu(msgTx, frame, slot, dl_tti_pdu);
|
||||
|
||||
@@ -196,6 +196,9 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx)
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&ru->common.tx_sections, &gNB->common_vars.tx_sections, sizeof(ru->common.tx_sections));
|
||||
memset(&gNB->common_vars.tx_sections, 0, sizeof(gNB->common_vars.tx_sections));
|
||||
|
||||
// If there is no digital beamforming we just need to copy the data to RU
|
||||
if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) {
|
||||
for (int b = 0; b < ru->num_beams_period; b++) {
|
||||
|
||||
@@ -53,38 +53,76 @@ int beam_index_allocation(bool das,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
int bitmap_symbols)
|
||||
int start_rb,
|
||||
int num_rb,
|
||||
int start_symb,
|
||||
int num_symb,
|
||||
int num_ports,
|
||||
int start_port)
|
||||
{
|
||||
if (!common_vars->beam_id)
|
||||
return 0;
|
||||
if (das)
|
||||
return fapi_beam_index;
|
||||
|
||||
int ru_beam_idx = analog_bf->analog_beam_list[fapi_beam_index].value;
|
||||
int idx = -1;
|
||||
for (int j = 0; j < common_vars->num_beams_period; j++) {
|
||||
// L2 analog beam implementation is slot based, so we need to verify occupancy for the whole slot
|
||||
for (int i = 0; i < symbols_per_slot; i++) {
|
||||
int current_beam = common_vars->beam_id[j][slot * symbols_per_slot + i];
|
||||
if (current_beam == -1 || current_beam == ru_beam_idx)
|
||||
idx = j;
|
||||
else {
|
||||
idx = -1;
|
||||
break;
|
||||
/* According to SCF nfapi spec, MSB of beam-Id indicates if beamforming is
|
||||
applied at L1 or if it should be passed down to RU */
|
||||
const bool is_lophy_bf = IS_BIT_SET(fapi_beam_index, 15);
|
||||
if (!is_lophy_bf) {
|
||||
/* Only analog BF for now because of L2 implementation. This could also be digital BF
|
||||
in which case L1 has to apply the pre-defined beam weights before OFDM modulation or
|
||||
sending freq domain data to RU. */
|
||||
AssertFatal(common_vars->beam_id, "L1 should do beamforming but no weights preconfigured: slot %d, beam id %d\n", slot, fapi_beam_index);
|
||||
int ru_beam_idx = analog_bf->analog_beam_list[fapi_beam_index].value;
|
||||
int idx = -1;
|
||||
for (int j = 0; j < common_vars->num_beams_period; j++) {
|
||||
// L2 analog beam implementation is slot based, so we need to verify occupancy for the whole slot
|
||||
for (int i = 0; i < symbols_per_slot; i++) {
|
||||
int current_beam = common_vars->beam_id[j][slot * symbols_per_slot + i];
|
||||
if (current_beam <= 0 || current_beam == ru_beam_idx)
|
||||
idx = j;
|
||||
else {
|
||||
idx = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx != -1)
|
||||
break;
|
||||
}
|
||||
if (idx != -1)
|
||||
break;
|
||||
}
|
||||
AssertFatal(idx >= 0, "Couldn't allocate beam ID %d\n", ru_beam_idx);
|
||||
for (int j = 0; j < symbols_per_slot; j++) {
|
||||
if (((bitmap_symbols >> j) & 0x01))
|
||||
AssertFatal(idx >= 0, "Couldn't allocate beam ID %d\n", ru_beam_idx);
|
||||
for (int j = start_symb; j < start_symb + num_symb; j++) {
|
||||
common_vars->beam_id[idx][slot * symbols_per_slot + j] = ru_beam_idx;
|
||||
}
|
||||
LOG_D(PHY, "Allocating beam_id[%d] %d in slot %d\n", idx, ru_beam_idx, slot);
|
||||
} else {
|
||||
// Digital or analog BF we don't care because L1 has to pass the beam index down to O-RU
|
||||
int ru_beam_idx = (fapi_beam_index & 0x7fff);
|
||||
update_ofh_section_info(&common_vars->tx_sections, ru_beam_idx, start_rb, num_rb, start_symb, num_symb, start_port, num_ports);
|
||||
// in this case the beam number is not relevant for L1 as mulitple beams are handled in multiple sections
|
||||
idx = 0;
|
||||
}
|
||||
LOG_D(PHY, "Allocating beam_id[%d] %d in slot %d\n", idx, ru_beam_idx, slot);
|
||||
return idx;
|
||||
}
|
||||
|
||||
void update_ofh_section_info(struct oai_ofh_section *tx_s,
|
||||
int beam_id,
|
||||
int start_rb,
|
||||
int num_rb,
|
||||
int start_symb,
|
||||
int num_symb,
|
||||
int start_port,
|
||||
int num_ports)
|
||||
{
|
||||
struct oai_ofh_section_def *sec = tx_s->sec + tx_s->num_sections;
|
||||
sec->beam_id = beam_id;
|
||||
sec->start_prb = start_rb;
|
||||
sec->num_prb = num_rb;
|
||||
sec->start_symbol = start_symb;
|
||||
sec->num_symbols = num_symb;
|
||||
sec->start_port = start_port;
|
||||
sec->num_ports = num_ports;
|
||||
tx_s->num_sections++;
|
||||
}
|
||||
|
||||
void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_dl_tti_ssb_pdu ssb_pdu)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
@@ -140,14 +178,18 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n
|
||||
c16_t ***txdataF = gNB->common_vars.txdataF;
|
||||
int txdataF_offset = slot * fp->samples_per_slot_wCP;
|
||||
// beam number in a scenario with multiple concurrent beams
|
||||
int bitmap = SL_to_bitmap(ssb_start_symbol, 4); // 4 ssb symbols
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
bitmap);
|
||||
fp->ssb_start_subcarrier / NR_NB_SC_PER_RB,
|
||||
20 + (fp->ssb_start_subcarrier % NR_NB_SC_PER_RB != 0),
|
||||
ssb_start_symbol,
|
||||
4,
|
||||
1,
|
||||
0);
|
||||
|
||||
nr_generate_pss(&txdataF[beam_nb][0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp);
|
||||
nr_generate_sss(&txdataF[beam_nb][0][txdataF_offset], gNB->TX_AMP, ssb_start_symbol, cfg, fp);
|
||||
@@ -173,14 +215,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n
|
||||
}
|
||||
#endif
|
||||
|
||||
nr_generate_pbch(gNB,
|
||||
&ssb_pdu,
|
||||
&txdataF[beam_nb][0][txdataF_offset],
|
||||
ssb_start_symbol,
|
||||
n_hf,
|
||||
frame,
|
||||
cfg,
|
||||
fp);
|
||||
nr_generate_pbch(gNB, &ssb_pdu, &txdataF[beam_nb][0][txdataF_offset], ssb_start_symbol, n_hf, frame, cfg, fp);
|
||||
}
|
||||
|
||||
// clearing beam information to be provided to RU for all slots (DL and UL)
|
||||
@@ -280,17 +315,22 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
csi_params->symb_l0,
|
||||
csi_params->symb_l1);
|
||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &csi_params->precodingAndBeamforming;
|
||||
int csi_bitmap = 0;
|
||||
int lprime_num = mapping_parms.lprime + 1;
|
||||
for (int j = 0; j < mapping_parms.size; j++)
|
||||
csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j];
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
csi_bitmap);
|
||||
int beam_nb = 0;
|
||||
for (int j = 0; j < mapping_parms.size; j++) {
|
||||
beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
csi_params->start_rb,
|
||||
csi_params->nr_of_rbs,
|
||||
mapping_parms.loverline[j],
|
||||
lprime_num,
|
||||
1,
|
||||
0);
|
||||
}
|
||||
|
||||
nr_generate_csi_rs(&gNB->frame_parms,
|
||||
&mapping_parms,
|
||||
|
||||
@@ -53,5 +53,18 @@ int beam_index_allocation(bool das,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
int bitmap_symbols);
|
||||
int start_rb,
|
||||
int num_rb,
|
||||
int start_symb,
|
||||
int num_symb,
|
||||
int num_ports,
|
||||
int start_port);
|
||||
void update_ofh_section_info(struct oai_ofh_section *tx_s,
|
||||
int beam_id,
|
||||
int start_rb,
|
||||
int num_rb,
|
||||
int start_symb,
|
||||
int num_symb,
|
||||
int start_port,
|
||||
int num_port);
|
||||
#endif
|
||||
|
||||
@@ -5144,3 +5144,27 @@ int get_j_for_k2(int mu)
|
||||
AssertFatal(mu >= 0 && mu < sizeofArray(j_table), "Invalid numerology %d\n", mu);
|
||||
return j_table[mu];
|
||||
}
|
||||
|
||||
// TODO: Only supports dmrs-Type 1 and one codeword
|
||||
uint16_t get_dmrs_ports_from_dci(const uint8_t table_idx)
|
||||
{
|
||||
DevAssert(table_idx < 11);
|
||||
// TODO: This table already in mac_tables.c need to move it here
|
||||
const uint8_t table_7_3_2_3_3_1[12][5] = {
|
||||
{1,1,0,0,0},
|
||||
{1,0,1,0,0},
|
||||
{1,1,1,0,0},
|
||||
{2,1,0,0,0},
|
||||
{2,0,1,0,0},
|
||||
{2,0,0,1,0},
|
||||
{2,0,0,0,1},
|
||||
{2,1,1,0,0},
|
||||
{2,0,0,1,1},
|
||||
{2,1,1,1,0},
|
||||
{2,1,1,1,1},
|
||||
{2,1,0,1,0}
|
||||
};
|
||||
|
||||
const uint8_t *t = table_7_3_2_3_3_1[table_idx];
|
||||
return (t[1] | t[2] << 1 | t[3] << 2 | t[4] << 3);
|
||||
}
|
||||
|
||||
@@ -303,4 +303,6 @@ int get_delta_for_k2(int mu);
|
||||
|
||||
int get_j_for_k2(int mu);
|
||||
|
||||
uint16_t get_dmrs_ports_from_dci(const uint8_t table_idx);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -784,7 +784,7 @@ static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int s
|
||||
for (int i = 0; i < beam_info->beams_per_period; i++) {
|
||||
beam_info->beam_allocation[i] = malloc16(beam_info->beam_allocation_size * sizeof(int));
|
||||
for (int j = 0; j < beam_info->beam_allocation_size; j++)
|
||||
beam_info->beam_allocation[i][j] = -1;
|
||||
beam_info->beam_allocation[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ static void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slo
|
||||
// resetting previous period allocation
|
||||
LOG_D(NR_MAC, "%d.%d Clear beam information for index %d\n", frame, slot, idx_to_clear);
|
||||
for (int i = 0; i < beam_info->beams_per_period; i++)
|
||||
beam_info->beam_allocation[i][idx_to_clear] = -1;
|
||||
beam_info->beam_allocation[i][idx_to_clear] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,6 +180,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
|
||||
int beam_index = get_fapi_beamforming_index(gNB, i_ssb);
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_per_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
|
||||
beam_index = get_allocated_beam(&gNB->beam_info, frameP, slotP, slots_per_frame, beam.idx);
|
||||
const int prb_offset = offset_pointa >> scs;
|
||||
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, beam_index, ssbSubcarrierOffset, offset_pointa, mib_pdu);
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id, beam.idx);
|
||||
@@ -212,6 +213,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
|
||||
int beam_index = get_fapi_beamforming_index(gNB, i_ssb);
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_per_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
|
||||
beam_index = get_allocated_beam(&gNB->beam_info, frameP, slotP, slots_per_frame, beam.idx);
|
||||
const int prb_offset = offset_pointa >> scs;
|
||||
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, beam_index, ssbSubcarrierOffset, offset_pointa, mib_pdu);
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id, beam.idx);
|
||||
@@ -244,6 +246,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
|
||||
int beam_index = get_fapi_beamforming_index(gNB, i_ssb);
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, slots_per_frame);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb);
|
||||
beam_index = get_allocated_beam(&gNB->beam_info, frameP, slotP, slots_per_frame, beam.idx);
|
||||
const int prb_offset = offset_pointa >> (scs-2); // reference 60kHz
|
||||
schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, beam_index, ssbSubcarrierOffset, offset_pointa, mib_pdu);
|
||||
fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset >> (scs - 2), ssb_start_symbol, CC_id, beam.idx);
|
||||
|
||||
@@ -966,7 +966,7 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu
|
||||
pdsch_pdu->SCID = dmrs_parms->n_scid;
|
||||
pdsch_pdu->dlDmrsScramblingId = dmrs_parms->scrambling_id;
|
||||
pdsch_pdu->numDmrsCdmGrpsNoData = dmrs_parms->numDmrsCdmGrpsNoData;
|
||||
pdsch_pdu->dmrsPorts = (1 << sched_pdsch->nrOfLayers) - 1; // FIXME with a better implementation
|
||||
pdsch_pdu->dmrsPorts = get_dmrs_ports_from_dci(dmrs_parms->dmrs_ports_id);
|
||||
// Pdsch Allocation in frequency domain
|
||||
pdsch_pdu->resourceAlloc = 1;
|
||||
pdsch_pdu->rbStart = sched_pdsch->rbStart;
|
||||
|
||||
@@ -54,6 +54,20 @@ uint32_t target_dl_Nl = 1;
|
||||
uint32_t target_dl_bw = 50;
|
||||
uint64_t dlsch_slot_bitmap = (1<<1);
|
||||
|
||||
static uint8_t get_next_mu_mimo_beam(const int layer, const int num_ssb, const BIT_STRING_t *ssbBitmap)
|
||||
{
|
||||
int sum = 0;
|
||||
for (int i = 0; i < num_ssb; i++) {
|
||||
if (IS_BIT_SET(ssbBitmap->buf[0], (7 - i))) {
|
||||
if (layer == sum)
|
||||
return i;
|
||||
sum++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* schedules whole bandwidth for first user, all the time */
|
||||
void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot)
|
||||
{
|
||||
@@ -62,146 +76,187 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot)
|
||||
int slot_period = slot % mac->frame_structure.numb_slots_period;
|
||||
if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot_period))
|
||||
return;
|
||||
NR_UE_info_t *UE = mac->UE_info.connected_ue_list[0];
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
|
||||
const int CC_id = 0;
|
||||
|
||||
/* return if all DL HARQ processes wait for feedback */
|
||||
if (sched_ctrl->retrans_dl_harq.head == -1 && sched_ctrl->available_dl_harq.head == -1) {
|
||||
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UE has no free DL HARQ process, skipping\n", UE->rnti, frame, slot);
|
||||
return;
|
||||
}
|
||||
bool is_mu_mimo = get_softmodem_params()->mu_mimo;
|
||||
AssertFatal((is_mu_mimo && (target_dl_Nl > 1)) || (!is_mu_mimo), "No of layers has to be more than 1 for MU-MIMO\n");
|
||||
uint8_t num_layers_per_ue = (is_mu_mimo) ? 1 : target_dl_Nl; // Limit MU-MIMO layer to 1 per UE
|
||||
// Tmp hack to scheduler MU-MIMO
|
||||
uint8_t layer_indicator = 0;
|
||||
|
||||
const int tda = get_dl_tda(mac, slot);
|
||||
NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp,
|
||||
sched_ctrl->search_space->searchSpaceType->present,
|
||||
tda,
|
||||
scc->dmrs_TypeA_Position,
|
||||
1,
|
||||
TYPE_C_RNTI_,
|
||||
sched_ctrl->coreset->controlResourceSetId,
|
||||
false);
|
||||
if(!tda_info.valid_tda)
|
||||
return;
|
||||
UE_iterator (mac->UE_info.connected_ue_list, UE) {
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
|
||||
const int CC_id = 0;
|
||||
|
||||
sched_ctrl->sched_pdsch.tda_info = tda_info;
|
||||
sched_ctrl->sched_pdsch.time_domain_allocation = tda;
|
||||
|
||||
/* find largest unallocated chunk */
|
||||
const int bwpSize = dl_bwp->BWPSize;
|
||||
const int BWPStart = dl_bwp->BWPStart;
|
||||
|
||||
// TODO implement beam procedures for phy-test mode
|
||||
int beam = 0;
|
||||
|
||||
int rbStart = 0;
|
||||
int rbSize = 0;
|
||||
if (target_dl_bw>bwpSize)
|
||||
target_dl_bw = bwpSize;
|
||||
uint16_t *vrb_map = mac->common_channels[CC_id].vrb_map[beam];
|
||||
/* loop ensures that we allocate exactly target_dl_bw, or return */
|
||||
while (true) {
|
||||
/* advance to first free RB */
|
||||
while (rbStart < bwpSize &&
|
||||
(vrb_map[rbStart + BWPStart]&SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)))
|
||||
rbStart++;
|
||||
rbSize = 1;
|
||||
/* iterate until we are at target_dl_bw or no available RBs */
|
||||
while (rbStart + rbSize < bwpSize &&
|
||||
!(vrb_map[rbStart + rbSize + BWPStart]&SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) &&
|
||||
rbSize < target_dl_bw)
|
||||
rbSize++;
|
||||
/* found target_dl_bw? */
|
||||
if (rbSize == target_dl_bw)
|
||||
break;
|
||||
/* at end and below target_dl_bw? */
|
||||
if (rbStart + rbSize >= bwpSize)
|
||||
return;
|
||||
rbStart += rbSize;
|
||||
}
|
||||
|
||||
sched_ctrl->num_total_bytes = 0;
|
||||
DevAssert(seq_arr_size(&sched_ctrl->lc_config) == 1);
|
||||
const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, 0);
|
||||
const int lcid = c->lcid;
|
||||
const uint16_t rnti = UE->rnti;
|
||||
/* update sched_ctrl->num_total_bytes so that postprocessor schedules data,
|
||||
* if available */
|
||||
sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid);
|
||||
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
||||
|
||||
int CCEIndex = get_cce_index(mac,
|
||||
CC_id, slot, UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
beam,
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
false,
|
||||
0);
|
||||
AssertFatal(CCEIndex >= 0, "Could not find CCE for UE %04x\n", UE->rnti);
|
||||
|
||||
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
|
||||
if (sched_pdsch->dl_harq_pid == -1)
|
||||
sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head;
|
||||
|
||||
int alloc = -1;
|
||||
if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) {
|
||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, UE->current_UL_BWP.pucch_Config, CCEIndex);
|
||||
alloc = nr_acknack_scheduling(mac, UE, frame, slot, 0, r_pucch, 0);
|
||||
if (alloc < 0) {
|
||||
LOG_D(NR_MAC, "Could not find PUCCH for UE %04x@%d.%d\n", rnti, frame, slot);
|
||||
/* return if all DL HARQ processes wait for feedback */
|
||||
if (sched_ctrl->retrans_dl_harq.head == -1 && sched_ctrl->available_dl_harq.head == -1) {
|
||||
LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UE has no free DL HARQ process, skipping\n", UE->rnti, frame, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
const int tda = get_dl_tda(mac, slot);
|
||||
NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp,
|
||||
sched_ctrl->search_space->searchSpaceType->present,
|
||||
tda,
|
||||
scc->dmrs_TypeA_Position,
|
||||
1,
|
||||
TYPE_C_RNTI_,
|
||||
sched_ctrl->coreset->controlResourceSetId,
|
||||
false);
|
||||
if (!tda_info.valid_tda)
|
||||
return;
|
||||
|
||||
sched_ctrl->sched_pdsch.tda_info = tda_info;
|
||||
sched_ctrl->sched_pdsch.time_domain_allocation = tda;
|
||||
|
||||
/* find largest unallocated chunk */
|
||||
const int bwpSize = dl_bwp->BWPSize;
|
||||
const int BWPStart = dl_bwp->BWPStart;
|
||||
|
||||
// TODO implement beam procedures for phy-test mode
|
||||
int num_ssb = 0;
|
||||
const BIT_STRING_t *ssbBitmap = NULL;
|
||||
switch (scc->ssb_PositionsInBurst->present) {
|
||||
case 1:
|
||||
num_ssb = 4;
|
||||
ssbBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
num_ssb = 8;
|
||||
ssbBitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(0, "SSB burst len in burst not supported\n");
|
||||
}
|
||||
int ssb_idx_beam = 0;
|
||||
for (int i_ssb = 0; i_ssb < num_ssb; i_ssb++) {
|
||||
if (IS_BIT_SET(ssbBitmap->buf[0], (7 - i_ssb))) {
|
||||
NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing;
|
||||
const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
|
||||
uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb);
|
||||
// select beam for PDSCH in current slot based on SSB beam
|
||||
if ((ssb_start_symbol / 14) == (slot % mac->frame_structure.numb_slots_period)) {
|
||||
ssb_idx_beam = i_ssb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If MU-MIMO, set first UE's beam to be the first beam idx available
|
||||
const int start_beam_idx = (is_mu_mimo) ? get_next_mu_mimo_beam(layer_indicator, num_ssb, ssbBitmap) : ssb_idx_beam;
|
||||
int beam_idx = get_fapi_beamforming_index(mac, start_beam_idx);
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&mac->beam_info, frame, slot, beam_idx, mac->frame_structure.numb_slots_frame);
|
||||
AssertFatal(beam.idx > -1, "Can't allocate beam %d in phytest scheduler\n", beam_idx);
|
||||
UE->UE_beam_index = get_allocated_beam(&mac->beam_info, frame, slot, mac->frame_structure.numb_slots_frame, beam.idx);
|
||||
|
||||
int rbStart = 0;
|
||||
int rbSize = 0;
|
||||
if (target_dl_bw > bwpSize)
|
||||
target_dl_bw = bwpSize;
|
||||
uint16_t *vrb_map = mac->common_channels[CC_id].vrb_map[beam.idx];
|
||||
/* loop ensures that we allocate exactly target_dl_bw, or return */
|
||||
while (true) {
|
||||
/* advance to first free RB */
|
||||
while (rbStart < bwpSize && (vrb_map[rbStart + BWPStart] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)))
|
||||
rbStart++;
|
||||
rbSize = 1;
|
||||
/* iterate until we are at target_dl_bw or no available RBs */
|
||||
while (rbStart + rbSize < bwpSize
|
||||
&& !(vrb_map[rbStart + rbSize + BWPStart] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols))
|
||||
&& rbSize < target_dl_bw)
|
||||
rbSize++;
|
||||
/* found target_dl_bw? */
|
||||
if (rbSize == target_dl_bw)
|
||||
break;
|
||||
/* at end and below target_dl_bw? */
|
||||
if (rbStart + rbSize >= bwpSize)
|
||||
return;
|
||||
rbStart += rbSize;
|
||||
}
|
||||
|
||||
sched_ctrl->num_total_bytes = 0;
|
||||
DevAssert(seq_arr_size(&sched_ctrl->lc_config) == 1);
|
||||
const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, 0);
|
||||
const int lcid = c->lcid;
|
||||
const uint16_t rnti = UE->rnti;
|
||||
/* update sched_ctrl->num_total_bytes so that postprocessor schedules data,
|
||||
* if available */
|
||||
sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid);
|
||||
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
|
||||
|
||||
int CCEIndex = get_cce_index(mac,
|
||||
CC_id,
|
||||
slot,
|
||||
UE->rnti,
|
||||
&sched_ctrl->aggregation_level,
|
||||
beam.idx,
|
||||
sched_ctrl->search_space,
|
||||
sched_ctrl->coreset,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
false,
|
||||
0);
|
||||
AssertFatal(CCEIndex >= 0, "Could not find CCE for UE %04x\n", UE->rnti);
|
||||
|
||||
NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
|
||||
if (sched_pdsch->dl_harq_pid == -1)
|
||||
sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head;
|
||||
|
||||
int alloc = -1;
|
||||
if (!get_FeedbackDisabled(UE->sc_info.downlinkHARQ_FeedbackDisabled_r17, sched_pdsch->dl_harq_pid)) {
|
||||
int r_pucch = nr_get_pucch_resource(sched_ctrl->coreset, UE->current_UL_BWP.pucch_Config, CCEIndex);
|
||||
alloc = nr_acknack_scheduling(mac, UE, frame, slot, 0, r_pucch, 0);
|
||||
if (alloc < 0) {
|
||||
LOG_D(NR_MAC, "Could not find PUCCH for UE %04x@%d.%d\n", rnti, frame, slot);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sched_ctrl->cce_index = CCEIndex;
|
||||
|
||||
fill_pdcch_vrb_map(mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, beam.idx);
|
||||
|
||||
// AssertFatal(alloc,
|
||||
// "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n",
|
||||
// rnti, frame, slot);
|
||||
|
||||
sched_pdsch->pucch_allocation = alloc;
|
||||
sched_pdsch->rbStart = rbStart;
|
||||
sched_pdsch->rbSize = rbSize;
|
||||
sched_pdsch->bwp_info = get_pdsch_bwp_start_size(mac, UE);
|
||||
sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc, dl_bwp, &tda_info, num_layers_per_ue);
|
||||
// Assign the right antenna port
|
||||
if (is_mu_mimo) {
|
||||
DevAssert((sched_pdsch->dmrs_parms.dmrs_ports_id == 0) || (sched_pdsch->dmrs_parms.dmrs_ports_id == 3));
|
||||
sched_pdsch->dmrs_parms.dmrs_ports_id += layer_indicator++;
|
||||
}
|
||||
|
||||
sched_pdsch->mcs = target_dl_mcs;
|
||||
sched_pdsch->nrOfLayers = num_layers_per_ue;
|
||||
sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
|
||||
sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
|
||||
sched_ctrl->dl_bler_stats.mcs = target_dl_mcs; /* for logging output */
|
||||
sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm,
|
||||
sched_pdsch->R,
|
||||
sched_pdsch->rbSize,
|
||||
tda_info.nrOfSymbols,
|
||||
sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT,
|
||||
0 /* N_PRB_oh, 0 for initialBWP */,
|
||||
0 /* tb_scaling */,
|
||||
sched_pdsch->nrOfLayers)
|
||||
>> 3;
|
||||
|
||||
/* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */
|
||||
sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
|
||||
|
||||
/* mark the corresponding RBs as used */
|
||||
for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
|
||||
vrb_map[rb + sched_pdsch->rbStart + BWPStart] = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||||
|
||||
if ((frame & 127) == 0)
|
||||
LOG_D(MAC, "phytest: %d.%d DL mcs %d, DL rbStart %d, DL rbSize %d\n", frame, slot, sched_pdsch->mcs, rbStart, rbSize);
|
||||
}
|
||||
|
||||
sched_ctrl->cce_index = CCEIndex;
|
||||
|
||||
fill_pdcch_vrb_map(mac,
|
||||
CC_id,
|
||||
&sched_ctrl->sched_pdcch,
|
||||
CCEIndex,
|
||||
sched_ctrl->aggregation_level,
|
||||
beam);
|
||||
|
||||
//AssertFatal(alloc,
|
||||
// "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n",
|
||||
// rnti, frame, slot);
|
||||
|
||||
sched_pdsch->pucch_allocation = alloc;
|
||||
sched_pdsch->rbStart = rbStart;
|
||||
sched_pdsch->rbSize = rbSize;
|
||||
sched_pdsch->bwp_info = get_pdsch_bwp_start_size(mac, UE);
|
||||
sched_pdsch->dmrs_parms = get_dl_dmrs_params(scc,
|
||||
dl_bwp,
|
||||
&tda_info,
|
||||
target_dl_Nl);
|
||||
|
||||
sched_pdsch->mcs = target_dl_mcs;
|
||||
sched_pdsch->nrOfLayers = target_dl_Nl;
|
||||
sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
|
||||
sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, dl_bwp->mcsTableIdx);
|
||||
sched_ctrl->dl_bler_stats.mcs = target_dl_mcs; /* for logging output */
|
||||
sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm,
|
||||
sched_pdsch->R,
|
||||
sched_pdsch->rbSize,
|
||||
tda_info.nrOfSymbols,
|
||||
sched_pdsch->dmrs_parms.N_PRB_DMRS * sched_pdsch->dmrs_parms.N_DMRS_SLOT,
|
||||
0 /* N_PRB_oh, 0 for initialBWP */,
|
||||
0 /* tb_scaling */,
|
||||
sched_pdsch->nrOfLayers)
|
||||
>> 3;
|
||||
|
||||
/* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */
|
||||
sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
|
||||
|
||||
/* mark the corresponding RBs as used */
|
||||
for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
|
||||
vrb_map[rb + sched_pdsch->rbStart + BWPStart] = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
|
||||
|
||||
if ((frame&127) == 0) LOG_D(MAC,"phytest: %d.%d DL mcs %d, DL rbStart %d, DL rbSize %d\n", frame, slot, sched_pdsch->mcs, rbStart,rbSize);
|
||||
}
|
||||
|
||||
uint32_t target_ul_mcs = 9;
|
||||
@@ -218,8 +273,6 @@ void nr_ul_preprocessor_phytest(gNB_MAC_INST *nr_mac, post_process_pusch_t *pp_p
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE = nr_mac->UE_info.connected_ue_list[0];
|
||||
|
||||
AssertFatal(nr_mac->UE_info.connected_ue_list[1] == NULL,
|
||||
"cannot handle more than one UE\n");
|
||||
if (UE == NULL)
|
||||
return;
|
||||
|
||||
|
||||
@@ -3380,7 +3380,7 @@ void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, const nr_mac_
|
||||
mac->fapi_beam_index[i] = fapi_index;
|
||||
index++;
|
||||
} else
|
||||
mac->fapi_beam_index[i] = -1;
|
||||
mac->fapi_beam_index[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3399,7 +3399,7 @@ NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame,
|
||||
for (int i = 0; i < beam_info->beams_per_period; i++) {
|
||||
NR_beam_alloc_t beam_struct = {.new_beam = false, .idx = i};
|
||||
int *beam = &beam_info->beam_allocation[i][index];
|
||||
if (*beam == -1) {
|
||||
if (*beam == 0) { // beamId 0 is no BF as per O-RAN spec
|
||||
beam_struct.new_beam = true;
|
||||
*beam = beam_index;
|
||||
}
|
||||
@@ -3412,6 +3412,13 @@ NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame,
|
||||
return (NR_beam_alloc_t) {.new_beam = false, .idx = -1};
|
||||
}
|
||||
|
||||
int get_allocated_beam(const NR_beam_info_t *beam_info, int frame, int slot, int slots_per_frame, int beam_number_in_period)
|
||||
{
|
||||
const int index = get_beam_index(beam_info, frame, slot, slots_per_frame);
|
||||
uint16_t beam_idx = beam_info->beam_allocation[beam_number_in_period][index];
|
||||
return (beam_info->beam_mode == LOPHY_BEAM_IDX) ? SET_BIT(beam_idx, 15) : beam_idx;
|
||||
}
|
||||
|
||||
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam)
|
||||
{
|
||||
if(!new_beam) // need to reset only if the beam was allocated specifically for this instance
|
||||
|
||||
@@ -456,6 +456,7 @@ int ul_buffer_index(int frame, int slot, int slots_per_frame, int size);
|
||||
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
|
||||
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac);
|
||||
int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx);
|
||||
int get_allocated_beam(const NR_beam_info_t *beam_info, int frame, int slot, int slots_per_frame, int beam_number_in_period);
|
||||
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame);
|
||||
void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame, bool new_beam);
|
||||
void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE);
|
||||
|
||||
@@ -551,8 +551,11 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
|
||||
int CC_id = 0;
|
||||
rnti_t rnti;
|
||||
if (get_softmodem_params()->phy_test) {
|
||||
AssertFatal(mac->UE_info.connected_ue_list[0] == NULL, "phytest: UE already present\n");
|
||||
rnti = 0x1234;
|
||||
NR_UE_info_t *prev_UE = NULL;
|
||||
UE_iterator (mac->UE_info.connected_ue_list, UE) {
|
||||
prev_UE = UE;
|
||||
}
|
||||
rnti = (prev_UE) ? prev_UE->rnti + 1 : 0x1234;
|
||||
} else {
|
||||
bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti);
|
||||
if (!found)
|
||||
|
||||
@@ -756,7 +756,7 @@ typedef struct {
|
||||
NR_UE_NR_Capability_t *capability;
|
||||
measgap_config_t measgap_config;
|
||||
// UE selected beam index
|
||||
uint8_t UE_beam_index;
|
||||
uint16_t UE_beam_index;
|
||||
float ul_thr_ue;
|
||||
float dl_thr_ue;
|
||||
long pdsch_HARQ_ACK_Codebook;
|
||||
|
||||
@@ -440,8 +440,12 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id)
|
||||
free_f1ap_setup_response(&resp);
|
||||
|
||||
/* we need to setup one default UE for phy-test and do-ra modes in the MAC */
|
||||
if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0)
|
||||
if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) {
|
||||
rrc_add_nsa_user(rrc, NULL, assoc_id);
|
||||
// Schedule one more UE if MU-MIMO flag activated
|
||||
if (get_softmodem_params()->mu_mimo > 0)
|
||||
rrc_add_nsa_user(rrc, NULL, assoc_id);
|
||||
}
|
||||
}
|
||||
|
||||
static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id)
|
||||
|
||||
@@ -467,6 +467,25 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define MAX_NR_PRBS 273
|
||||
/* numPrbc can range only till 255. If more than 255 PRBs used, the section
|
||||
is split into two */
|
||||
static void fragment_sections_if_needed(struct oai_ofh_section *s)
|
||||
{
|
||||
const uint8_t max_numPrbc = UINT8_MAX;
|
||||
for (int_fast16_t i = 0; i < s->num_sections; i++) {
|
||||
if (s->sec[i].num_prb == MAX_NR_PRBS)
|
||||
continue;
|
||||
else if (s->sec[i].num_prb > max_numPrbc) {
|
||||
s->sec[s->num_sections] = s->sec[i];
|
||||
s->sec[s->num_sections].num_prb -= max_numPrbc;
|
||||
s->sec[s->num_sections].start_prb = max_numPrbc;
|
||||
s->sec[i].num_prb = max_numPrbc;
|
||||
s->num_sections++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @details Write PDSCH IQ-data from OAI txdataF_BF buffer to xran buffers. If
|
||||
* I/Q compression (bitwidth < 16 bits) is configured, compresses the data
|
||||
* before writing. */
|
||||
@@ -484,34 +503,58 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
int nPRBs = fh_cfg->nDLRBs;
|
||||
int fftsize = 1 << fh_cfg->ru_conf.fftSize;
|
||||
int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports;
|
||||
uint8_t *last_data_pointer[ru->nb_tx][XRAN_NUM_OF_SYMBOL_PER_SLOT];
|
||||
memset(last_data_pointer, 0, sizeof(last_data_pointer));
|
||||
|
||||
fragment_sections_if_needed(&ru->tx_sections);
|
||||
for (uint16_t cc_id = 0; cc_id < 1 /*nSectorNum*/; cc_id++) { // OAI does not support multiple CC yet.
|
||||
for (uint8_t ant_id = 0; ant_id < ru->nb_tx; ant_id++) {
|
||||
oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_tx_per_ru);
|
||||
// This loop would better be more inner to avoid confusion and maybe also errors.
|
||||
for (int32_t sym_idx = 0; sym_idx < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_idx++) {
|
||||
uint8_t *pData =
|
||||
bufs->src[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT].pData;
|
||||
uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
|
||||
struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData;
|
||||
ptr = pData;
|
||||
pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize];
|
||||
uint8_t *pPrbMapData = bufs->srccp[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
|
||||
struct xran_prb_map *pRbMap = (struct xran_prb_map *)pPrbMapData;
|
||||
struct xran_prb_map *txd = (struct xran_prb_map *)bufs->bufs.tx_prbmap[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pData;
|
||||
const int num_elm = ru->tx_sections.num_sections;
|
||||
int num_port_elm = 0;
|
||||
for (int_fast32_t idxElm = 0; idxElm < num_elm; idxElm++) {
|
||||
struct oai_ofh_section_def *l1_s = ru->tx_sections.sec + idxElm;
|
||||
// Tmp hack for mu-mimo
|
||||
if (l1_s->start_port != ant_id) {
|
||||
continue;
|
||||
}
|
||||
struct xran_prb_elm *p_prbMapElm = &pRbMap->prbMap[num_port_elm];
|
||||
p_prbMapElm->nRBStart = l1_s->start_prb;
|
||||
p_prbMapElm->nRBSize = l1_s->num_prb;
|
||||
p_prbMapElm->nStartSymb = l1_s->start_symbol;
|
||||
p_prbMapElm->numSymb = l1_s->num_symbols;
|
||||
p_prbMapElm->nBeamIndex = l1_s->beam_id;
|
||||
p_prbMapElm->compMethod = fh_cfg->ru_conf.compMeth;
|
||||
p_prbMapElm->iqWidth = fh_cfg->ru_conf.iqWidth;
|
||||
LOG_D(PHY,
|
||||
"%d.%d sec id:%ld, start rb:%d, num rb:%d, start sym:%d, num sym:%d\n",
|
||||
frame,
|
||||
slot,
|
||||
idxElm,
|
||||
p_prbMapElm->nRBStart,
|
||||
p_prbMapElm->nRBSize,
|
||||
p_prbMapElm->nStartSymb,
|
||||
p_prbMapElm->numSymb);
|
||||
for (int32_t sym_idx = p_prbMapElm->nStartSymb; sym_idx < p_prbMapElm->nStartSymb + p_prbMapElm->numSymb; sym_idx++) {
|
||||
uint8_t *pData =
|
||||
bufs->src[ant_id % nb_tx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers[sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT].pData;
|
||||
ptr = pData;
|
||||
pos = &ru->txdataF_BF[ant_id][sym_idx * fftsize];
|
||||
|
||||
uint8_t *u8dptr;
|
||||
struct xran_prb_map *pRbMap = pPrbMap;
|
||||
int32_t sym_id = sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT;
|
||||
if (ptr && pos) {
|
||||
uint32_t idxElm = 0;
|
||||
u8dptr = (uint8_t *)ptr;
|
||||
int16_t payload_len = 0;
|
||||
uint8_t *u8dptr;
|
||||
int32_t sym_id = sym_idx % XRAN_NUM_OF_SYMBOL_PER_SLOT;
|
||||
if (ptr && pos) {
|
||||
u8dptr = (uint8_t *)ptr;
|
||||
int16_t payload_len = 0;
|
||||
|
||||
uint8_t *dst = (uint8_t *)u8dptr;
|
||||
uint8_t *dst = (uint8_t *)u8dptr;
|
||||
dst = last_data_pointer[ant_id][sym_idx] != NULL ? last_data_pointer[ant_id][sym_idx] : dst;
|
||||
|
||||
struct xran_prb_elm *p_prbMapElm = &pRbMap->prbMap[idxElm];
|
||||
|
||||
for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
|
||||
struct xran_section_desc *p_sec_desc = NULL;
|
||||
p_prbMapElm = &pRbMap->prbMap[idxElm];
|
||||
// assumes one fragment per symbol
|
||||
#ifdef E_RELEASE
|
||||
p_sec_desc = p_prbMapElm->p_sec_desc[sym_id][0];
|
||||
@@ -530,7 +573,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
int pos_len = 0;
|
||||
int neg_len = 0;
|
||||
|
||||
if (p_prbMapElm->nRBStart < (nPRBs >> 1)) // there are PRBs left of DC
|
||||
if (p_prbMapElm->nRBStart <= (nPRBs >> 1)) // there are PRBs left of DC
|
||||
neg_len = min((nPRBs * 6) - (p_prbMapElm->nRBStart * 12), p_prbMapElm->nRBSize * N_SC_PER_PRB);
|
||||
pos_len = (p_prbMapElm->nRBSize * N_SC_PER_PRB) - neg_len;
|
||||
// Calculation of the pointer for the section in the buffer.
|
||||
@@ -581,16 +624,20 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
|
||||
dst += payload_len;
|
||||
dst = xran_add_hdr_offset(dst, p_prbMapElm->compMethod);
|
||||
last_data_pointer[ant_id][sym_idx] = dst;
|
||||
|
||||
// The tti should be updated as it increased.
|
||||
pRbMap->tti_id = tti;
|
||||
|
||||
} else {
|
||||
printf("ptr ==NULL\n");
|
||||
exit(-1); // fails here??
|
||||
}
|
||||
|
||||
// The tti should be updated as it increased.
|
||||
pRbMap->tti_id = tti;
|
||||
|
||||
} else {
|
||||
printf("ptr ==NULL\n");
|
||||
exit(-1); // fails here??
|
||||
}
|
||||
num_port_elm++;
|
||||
}
|
||||
pRbMap->nPrbElm = num_port_elm;
|
||||
xran_init_PrbMap_from_cfg(pRbMap, txd, fh_init->mtu);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
|
||||
@@ -94,16 +94,19 @@ static struct xran_prb_map get_xran_prb_map(const struct xran_fh_config *f, cons
|
||||
.cc_id = 0,
|
||||
.ru_port_id = 0,
|
||||
.tti_id = 0,
|
||||
.nPrbElm = 1,
|
||||
.nPrbElm = XRAN_MIN_SECTIONS_PER_SLOT,
|
||||
};
|
||||
struct xran_prb_elm *e = &prbmap.prbMap[0];
|
||||
e->nStartSymb = start_sym;
|
||||
e->numSymb = num_sym;
|
||||
e->nRBStart = 0;
|
||||
e->nRBSize = (dir == XRAN_DIR_DL) ? f->nDLRBs : f->nULRBs;
|
||||
e->nBeamIndex = 0;
|
||||
e->compMethod = f->ru_conf.compMeth;
|
||||
e->iqWidth = f->ru_conf.iqWidth;
|
||||
for (int i = 0; i < prbmap.nPrbElm; i++) {
|
||||
struct xran_prb_elm *e = &prbmap.prbMap[0];
|
||||
e->nStartSymb = start_sym;
|
||||
e->numSymb = num_sym;
|
||||
e->nRBStart = 0;
|
||||
e->nRBSize = 0;
|
||||
e->nBeamIndex = 0;
|
||||
e->compMethod = f->ru_conf.compMeth;
|
||||
e->iqWidth = f->ru_conf.iqWidth;
|
||||
}
|
||||
|
||||
return prbmap;
|
||||
}
|
||||
|
||||
|
||||
@@ -269,6 +269,7 @@ void oran_fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
ru_info_t ru_info;
|
||||
ru_info.nb_tx = ru->nb_tx * ru->num_beams_period;
|
||||
ru_info.txdataF_BF = ru->common.txdataF_BF;
|
||||
memcpy(&ru_info.tx_sections, &ru->common.tx_sections, sizeof(ru_info.tx_sections));
|
||||
// printf("south_out:\tframe=%d\tslot=%d\ttimestamp=%ld\n",frame,slot,timestamp);
|
||||
|
||||
int ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp);
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
#include "xran_fh_o_du.h"
|
||||
|
||||
#include "openair1/PHY/defs_RU.h"
|
||||
|
||||
/*
|
||||
* Structure added to bear the information needed from OAI RU
|
||||
*/
|
||||
@@ -43,6 +45,7 @@ typedef struct ru_info_s {
|
||||
|
||||
// Needed for Prach
|
||||
int16_t **prach_buf;
|
||||
struct oai_ofh_section tx_sections;
|
||||
} ru_info_t;
|
||||
|
||||
/** @brief Reads RX data (PRACH/PUSCH) of next slot.
|
||||
|
||||
Reference in New Issue
Block a user