mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 13:10:28 +00:00
Compare commits
12 Commits
develop
...
NR_analog_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5b02c2e9d | ||
|
|
12ba1f91ce | ||
|
|
594a8d4665 | ||
|
|
c8cc3718dc | ||
|
|
ef0ba10f41 | ||
|
|
83a4d5ff3f | ||
|
|
0986bac1c3 | ||
|
|
66bc362ab7 | ||
|
|
61d1437ecc | ||
|
|
7017420888 | ||
|
|
881a30888b | ||
|
|
d68795bb98 |
@@ -21,7 +21,6 @@ gNBs =
|
||||
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
beam_weights = [0]; // single SSB -> one analog beam
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
@@ -179,6 +178,7 @@ MACRLCs = ({
|
||||
set_analog_beamforming = 1;
|
||||
beam_duration = 1;
|
||||
beams_per_period = 1;
|
||||
beam_weights = [0]; // single SSB -> one analog beam
|
||||
});
|
||||
|
||||
L1s = (
|
||||
|
||||
@@ -18,8 +18,7 @@ In the `MACRLC` section of configuration files, there are three new parameters:
|
||||
- `set_analog_beamforming` can be set to 1 or 0 to activate or desactivate analog beamforming (default value is 0)
|
||||
- `beam_duration` is the number of slots (currently minimum duration of a beam) the scheduler is tied to a beam (default value is 1)
|
||||
- `beams_per_period` is the number of concurrent beams the RU can handle in the beam duration (default value is 1)
|
||||
|
||||
In the `gNBs` section of the configuration file, under the phyisical parameters, a vector field containing the set of beam indices to be provided by the OAI L1 to the RU is also required. This field is called `beam_weights`. In current implementation, the number of beam indices should be equal to the number of SSBs transmitted.
|
||||
- `beam_weights` is a vector field containing the set of beam indices to be provided by the OAI L1 to the RU is also required. In current implementation, the number of beam indices should be equal to the number of SSBs transmitted.
|
||||
|
||||
# Implementation in OAI scheduler
|
||||
|
||||
@@ -28,3 +27,24 @@ This matrix contains the beams already allocated in a given slot, to flag the sc
|
||||
To this goal, we extended the virtual resource block (VRB) map by one dimension to also contain information per allocated beam. As said, the scheduler can independently schedule users in a number of beams up to `beams_per_period` concurrently.
|
||||
|
||||
It is important to note that in current implementation, there are several periodical channels, e.g. PRACH or PUCCH for CSI et cetera, that have the precendence in being assigned a beam, that is because the scheduling is automatic, set in RRC configuration, and not up to the scheduler. For these instances, we assume the beam is available (if not there are assertions to stop the process). For data channels, the currently implemented PF scheduler is used. The only modification is that a UE can be served only if there is a free beam available or the one of the beams already in use correspond to that UE beam.
|
||||
|
||||
# FAPI implementation
|
||||
|
||||
In `config_request` structure, a vendor extension (`nfapi_nr_analog_beamforming_ve_t`) configures the lower layers at initialization with the following information:
|
||||
- `analog_bf_vendor_ext` which can assume values 1 or 0 for enabling or disabling analog beamforming
|
||||
- `num_beams_period_vendor_ext` which corresponds to the configuration parameter `beams_per_period`
|
||||
- `total_num_beams_vendor_ext` which corresponds to the number of beams configured in `beam_weights`
|
||||
- `analog_beam_list` which contains the RU beamforming indices configured in `beam_weights`
|
||||
|
||||
Additionally, L2 provides in each channel FAPI message information about the beam index. Small Cell Forum (SCF) FAPI provides in its PHY API specifications for the channels only a field for digital beamforming ad part of the `precoding_and_beamforming` stucture. There without a better option, we are currently using that one to store the internal analog beamforming index. This is the index used internally by the code to progressively identify the beam with a value from 0 to `total_num_beams_vendor_ext`.
|
||||
|
||||
# L1 implementation
|
||||
|
||||
To handle multiple concurrent beam, the buffers containing Tx and Rx data in frequency domain (`txdataF` and `rxdataF`) have been extended by one dimension to contain multiple concurrent beam to be transmitted/received.
|
||||
The function `beam_index_allocation`, called by every L1 channel, is responsible to match the FAPI analog beam index to the RU beam index and to store the latter `beam_id` structure, which allocates the beams per symbol, despite L2 only supporting beam change at slot level. At the same time, the function returns the concurrent beam index, to be used to store data in frequency domain buffers. While doing so, the function also checks if there is room for current beam in the list of concurrent beams, which should always be the case, if L2 properly allocated the channels.
|
||||
|
||||
# RU implementation
|
||||
|
||||
The implementation is still work in progress.
|
||||
|
||||
The first dimension of the Tx and Rx buffers that used to contain the number of Tx/Rx antennas, it is now extended to contain the number of parallel streams which is the number of antennas multiplied by the number of concurrent beams.
|
||||
|
||||
@@ -370,32 +370,29 @@ void term_gNB_Tpool(int inst) {
|
||||
}
|
||||
|
||||
/// eNB kept in function name for nffapi calls, TO FIX
|
||||
void init_eNB_afterRU(void) {
|
||||
int inst,ru_id,i,aa;
|
||||
PHY_VARS_gNB *gNB;
|
||||
|
||||
for (inst=0; inst<RC.nb_nr_L1_inst; inst++) {
|
||||
gNB = RC.gNB[inst];
|
||||
|
||||
void init_eNB_afterRU(void)
|
||||
{
|
||||
for (int inst = 0; inst < RC.nb_nr_L1_inst; inst++) {
|
||||
PHY_VARS_gNB *gNB = RC.gNB[inst];
|
||||
phy_init_nr_gNB(gNB);
|
||||
|
||||
// map antennas and PRACH signals to gNB RX
|
||||
if (0) AssertFatal(gNB->num_RU>0,"Number of RU attached to gNB %d is zero\n",gNB->Mod_id);
|
||||
|
||||
LOG_D(NR_PHY, "Mapping RX ports from %d RUs to gNB %d\n", gNB->num_RU, gNB->Mod_id);
|
||||
|
||||
for (ru_id=0,aa=0; ru_id<gNB->num_RU; ru_id++) {
|
||||
int aa = 0;
|
||||
for (int ru_id = 0; ru_id < gNB->num_RU; ru_id++) {
|
||||
AssertFatal(gNB->RU_list[ru_id]->common.rxdataF != NULL, "RU %d : common.rxdataF is NULL\n", gNB->RU_list[ru_id]->idx);
|
||||
AssertFatal(gNB->RU_list[ru_id]->prach_rxsigF != NULL, "RU %d : prach_rxsigF is NULL\n", gNB->RU_list[ru_id]->idx);
|
||||
|
||||
for (i=0; i<gNB->RU_list[ru_id]->nb_rx; aa++,i++) {
|
||||
LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa);
|
||||
for (int i = 0; i < gNB->RU_list[ru_id]->nb_rx; aa++, i++) {
|
||||
LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n", gNB->RU_list[ru_id]->idx, i, aa);
|
||||
gNB->prach_vars.rxsigF[aa] = gNB->RU_list[ru_id]->prach_rxsigF[0][i];
|
||||
// TODO hardcoded beam to 0, still need to understand how to handle this properly
|
||||
gNB->common_vars.rxdataF[0][aa] = (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[i];
|
||||
for (int b = 0; b < gNB->RU_list[ru_id]->num_beams_period; b++) {
|
||||
int idx = i + b * gNB->RU_list[ru_id]->nb_rx;
|
||||
gNB->common_vars.rxdataF[b][aa] = (c16_t *)gNB->RU_list[ru_id]->common.rxdataF[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: review this code, there is something wrong.
|
||||
* In monolithic mode, we come here with nb_antennas_rx == 0
|
||||
* (not tested in other modes).
|
||||
@@ -403,7 +400,6 @@ void init_eNB_afterRU(void) {
|
||||
//init_precoding_weights(RC.gNB[inst]);
|
||||
init_gNB_Tpool(inst);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -239,20 +239,20 @@ int connect_rau(RU_t *ru) {
|
||||
void fh_if5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) {
|
||||
if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
int offset = ru->nr_frame_parms->get_samples_slot_timestamp(slot,ru->nr_frame_parms,0);
|
||||
void *buffs[ru->nb_tx];
|
||||
for (int aid=0;aid<ru->nb_tx;aid++) buffs[aid] = (void*)&ru->common.txdata[aid][offset];
|
||||
void *buffs[ru->nb_tx];
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++)
|
||||
buffs[aid] = (void*)&ru->common.txdata[aid][offset];
|
||||
struct timespec txmeas;
|
||||
clock_gettime(CLOCK_MONOTONIC, &txmeas);
|
||||
LOG_D(NR_PHY,"IF5 TX %d.%d, TS %llu, buffs[0] %p, buffs[1] %p ener0 %f dB, tx start %d\n",frame,slot,(unsigned long long)timestamp,buffs[0],buffs[1],
|
||||
10*log10((double)signal_energy(buffs[0],ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms))),(int)txmeas.tv_nsec);
|
||||
ru->ifdevice.trx_write_func2(&ru->ifdevice,
|
||||
timestamp,
|
||||
timestamp,
|
||||
buffs,
|
||||
0,
|
||||
ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms),
|
||||
0,
|
||||
ru->nb_tx);
|
||||
|
||||
0,
|
||||
ru->nr_frame_parms->get_samples_per_slot(slot,ru->nr_frame_parms),
|
||||
0,
|
||||
ru->nb_tx);
|
||||
}
|
||||
|
||||
// southbound IF4p5 fronthaul
|
||||
@@ -590,33 +590,28 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
openair0_config_t *cfg = &ru->openair0_cfg;
|
||||
void *rxp[ru->nb_rx];
|
||||
unsigned int rxs;
|
||||
int i;
|
||||
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot,fp);
|
||||
uint32_t samples_per_slot_prev ;
|
||||
openair0_timestamp ts,old_ts;
|
||||
AssertFatal(*slot<fp->slots_per_frame && *slot>=0, "slot %d is illegal (%d)\n",*slot,fp->slots_per_frame);
|
||||
uint32_t samples_per_slot = fp->get_samples_per_slot(*slot, fp);
|
||||
AssertFatal(*slot < fp->slots_per_frame && *slot >= 0, "slot %d is illegal (%d)\n", *slot, fp->slots_per_frame);
|
||||
|
||||
start_meas(&ru->rx_fhaul);
|
||||
for (i=0; i<ru->nb_rx; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot,fp,0)];
|
||||
int nb = ru->nb_rx * ru->num_beams_period;
|
||||
void *rxp[nb];
|
||||
for (int i = 0; i < nb; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][fp->get_samples_slot_timestamp(*slot, fp, 0)];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
|
||||
old_ts = proc->timestamp_rx;
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n",samples_per_slot,*slot,rxp[0]);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1);
|
||||
openair0_timestamp old_ts = proc->timestamp_rx;
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n", samples_per_slot, *slot, rxp[0]);
|
||||
|
||||
openair0_timestamp ts;
|
||||
unsigned int rxs;
|
||||
if(emulate_rf) {
|
||||
wait_on_condition(&proc->mutex_emulateRF,&proc->cond_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
|
||||
release_thread(&proc->mutex_emulateRF,&proc->instance_cnt_emulateRF,"emulatedRF_thread");
|
||||
rxs = samples_per_slot;
|
||||
ts = old_ts + rxs;
|
||||
} else {
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
|
||||
&ts,
|
||||
rxp,
|
||||
samples_per_slot,
|
||||
ru->nb_rx);
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, &ts, rxp, samples_per_slot, nb);
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
|
||||
@@ -628,7 +623,7 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
LOG_E(PHY, "rx_rf: Asked for %d samples, got %d from USRP\n", samples_per_slot, rxs);
|
||||
|
||||
if (proc->first_rx != 1) {
|
||||
samples_per_slot_prev = fp->get_samples_per_slot((*slot-1)%fp->slots_per_frame,fp);
|
||||
uint32_t samples_per_slot_prev = fp->get_samples_per_slot((*slot - 1) % fp->slots_per_frame, fp);
|
||||
|
||||
if (proc->timestamp_rx - old_ts != samples_per_slot_prev) {
|
||||
LOG_D(PHY,
|
||||
@@ -751,8 +746,6 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
void *txp[ru->nb_tx];
|
||||
int i;
|
||||
T(T_ENB_PHY_OUTPUT_SIGNAL,
|
||||
T_INT(0),
|
||||
T_INT(0),
|
||||
@@ -819,7 +812,9 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot);
|
||||
|
||||
for (i = 0; i < ru->nb_tx; i++)
|
||||
int nt = ru->nb_tx * ru->num_beams_period;
|
||||
void *txp[nt];
|
||||
for (int i = 0; i < nt; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot, fp, 0)] - sf_extension * sizeof(int32_t);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp + ru->ts_offset) & 0xffffffff);
|
||||
@@ -829,12 +824,12 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
timestamp + ru->ts_offset - sf_extension,
|
||||
txp,
|
||||
siglen + sf_extension,
|
||||
ru->nb_tx, flags);
|
||||
nt,
|
||||
flags);
|
||||
LOG_D(PHY,
|
||||
"[TXPATH] RU %d aa %d tx_rf, writing to TS %llu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, "
|
||||
"[TXPATH] RU %d tx_rf, writing to TS %llu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, "
|
||||
"returned %d, E %f\n",
|
||||
ru->idx,
|
||||
i,
|
||||
(long long unsigned int)(timestamp + ru->ts_offset - sf_extension),
|
||||
frame,
|
||||
slot,
|
||||
@@ -1301,10 +1296,12 @@ void *ru_thread(void *param)
|
||||
|
||||
for (int prach_oc = 0; prach_oc<ru->prach_list[prach_id].num_prach_ocas; prach_oc++) {
|
||||
int prachStartSymbol = ru->prach_list[prach_id].prachStartSymbol + prach_oc * N_dur;
|
||||
int beam_id = ru->prach_list[prach_id].beam ? ru->prach_list[prach_id].beam[prach_oc] : 0;
|
||||
//comment FK: the standard 38.211 section 5.3.2 has one extra term +14*N_RA_slot. This is because there prachStartSymbol is given wrt to start of the 15kHz slot or 60kHz slot. Here we work slot based, so this function is anyway only called in slots where there is PRACH. Its up to the MAC to schedule another PRACH PDU in the case there are there N_RA_slot \in {0,1}.
|
||||
rx_nr_prach_ru(ru,
|
||||
ru->prach_list[prach_id].fmt, //could also use format
|
||||
ru->prach_list[prach_id].numRA,
|
||||
beam_id,
|
||||
prachStartSymbol,
|
||||
prach_oc,
|
||||
proc->frame_rx,
|
||||
@@ -1940,6 +1937,7 @@ static void NRRCconfig_RU(configmodule_interface_t *cfg)
|
||||
|
||||
RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr);
|
||||
RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
|
||||
RC.ru[j]->das_enabled = *(RUParamList.paramarray[j][RU_DAS_CONTROL].uptr);
|
||||
RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
|
||||
RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
|
||||
RC.ru[j]->if_frequency = *(RUParamList.paramarray[j][RU_IF_FREQUENCY].u64ptr);
|
||||
|
||||
@@ -1124,6 +1124,33 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
|
||||
// only increase if it was set
|
||||
numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
|
||||
|
||||
AssertFatal(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == 0,
|
||||
"Total num beams Vendor extension shouldn't be set!");
|
||||
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
|
||||
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
|
||||
retval &= pack_nr_tlv(NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG,
|
||||
&(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext),
|
||||
ppWritePackedMsg,
|
||||
end,
|
||||
&pack_uint8_tlv_value);
|
||||
// only increase if it was set
|
||||
numTLVs +=
|
||||
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
|
||||
|
||||
for (int beam = 0; beam < pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.value; beam++) {
|
||||
AssertFatal(pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam].tl.tag == 0,
|
||||
"Analog beams list Vendor extension shouldn't be set!");
|
||||
// The call to pack the TLV would be the same as any other TLV, it is only packed if the tag is set,
|
||||
// so, it's safe to add the call to pack_nr_tlv even if it is not always set
|
||||
retval &= pack_nr_tlv(NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG,
|
||||
&(pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam]),
|
||||
ppWritePackedMsg,
|
||||
end,
|
||||
&pack_uint8_tlv_value);
|
||||
// only increase if it was set
|
||||
numTLVs += pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
|
||||
}
|
||||
|
||||
pNfapiMsg->num_tlv = numTLVs;
|
||||
retval &= push8(pNfapiMsg->num_tlv, &pNumTLVFields, end);
|
||||
return retval;
|
||||
@@ -1138,6 +1165,7 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
|
||||
int config_beam_idx = 0;
|
||||
int tdd_periodicity_idx = 0;
|
||||
int symbol_per_slot_idx = 0;
|
||||
int beam_ve_idx = 0;
|
||||
nfapi_nr_config_request_scf_t *pNfapiMsg = (nfapi_nr_config_request_scf_t *)msg;
|
||||
// unpack TLVs
|
||||
|
||||
@@ -1188,6 +1216,10 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
|
||||
&unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_CONFIG_TDD_PERIOD_TAG, &(pNfapiMsg->tdd_table.tdd_period), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_CONFIG_SLOT_CONFIG_TAG, NULL, &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG, &(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, NULL, &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_CONFIG_RSSI_MEASUREMENT_TAG, &(pNfapiMsg->measurement_config.rssi_measurement), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv4), &unpack_ipv4_address_value},
|
||||
{NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG, &(pNfapiMsg->nfapi_config.p7_vnf_address_ipv6), &unpack_ipv6_address_value},
|
||||
@@ -1221,6 +1253,21 @@ uint8_t unpack_nr_config_request(uint8_t **ppReadPackedMsg, uint8_t *end, void *
|
||||
}
|
||||
int result = 0;
|
||||
switch (generic_tl.tag) {
|
||||
case NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG:
|
||||
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag = generic_tl.tag;
|
||||
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.length = generic_tl.length;
|
||||
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext, ppReadPackedMsg, end);
|
||||
pNfapiMsg->analog_beamforming_ve.analog_beam_list = (nfapi_uint8_tlv_t *)malloc(
|
||||
pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
|
||||
beam_ve_idx = 0;
|
||||
break;
|
||||
case NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG:
|
||||
unpack_fns[idx].tlv = &pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx];
|
||||
pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx].tl.tag = generic_tl.tag;
|
||||
pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx].tl.length = generic_tl.length;
|
||||
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->analog_beamforming_ve.analog_beam_list[beam_ve_idx], ppReadPackedMsg, end);
|
||||
beam_ve_idx ++;
|
||||
break;
|
||||
case NFAPI_NR_CONFIG_NUM_PRACH_FD_OCCASIONS_TAG:
|
||||
pNfapiMsg->prach_config.num_prach_fd_occasions.tl.tag = generic_tl.tag;
|
||||
pNfapiMsg->prach_config.num_prach_fd_occasions.tl.length = generic_tl.length;
|
||||
|
||||
@@ -276,6 +276,17 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const
|
||||
EQ_TLV(unpacked_req->nfapi_config.timing_info_mode, req->nfapi_config.timing_info_mode);
|
||||
|
||||
EQ_TLV(unpacked_req->nfapi_config.timing_info_period, req->nfapi_config.timing_info_period);
|
||||
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.num_beams_period_vendor_ext, req->analog_beamforming_ve.num_beams_period_vendor_ext);
|
||||
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.analog_bf_vendor_ext, req->analog_beamforming_ve.analog_bf_vendor_ext);
|
||||
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.total_num_beams_vendor_ext, req->analog_beamforming_ve.total_num_beams_vendor_ext);
|
||||
|
||||
for (int i = 0; i < unpacked_req->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.analog_beam_list[i], req->analog_beamforming_ve.analog_beam_list[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -422,6 +433,10 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg)
|
||||
if (msg->pmi_list.pmi_pdu) {
|
||||
free(msg->pmi_list.pmi_pdu);
|
||||
}
|
||||
|
||||
if (msg->analog_beamforming_ve.analog_beam_list) {
|
||||
free(msg->analog_beamforming_ve.analog_beam_list);
|
||||
}
|
||||
}
|
||||
|
||||
void free_config_response(nfapi_nr_config_response_scf_t *msg)
|
||||
@@ -832,6 +847,21 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf
|
||||
COPY_TLV(dst->nfapi_config.ul_dci_timing_offset, src->nfapi_config.ul_dci_timing_offset);
|
||||
|
||||
COPY_TLV(dst->nfapi_config.tx_data_timing_offset, src->nfapi_config.tx_data_timing_offset);
|
||||
|
||||
COPY_TLV(dst->analog_beamforming_ve.num_beams_period_vendor_ext, src->analog_beamforming_ve.num_beams_period_vendor_ext);
|
||||
|
||||
COPY_TLV(dst->analog_beamforming_ve.analog_bf_vendor_ext, src->analog_beamforming_ve.analog_bf_vendor_ext);
|
||||
|
||||
COPY_TLV(dst->analog_beamforming_ve.total_num_beams_vendor_ext, src->analog_beamforming_ve.total_num_beams_vendor_ext);
|
||||
|
||||
if (dst->analog_beamforming_ve.total_num_beams_vendor_ext.value > 0) {
|
||||
dst->analog_beamforming_ve.analog_beam_list = (nfapi_uint8_tlv_t *)malloc(
|
||||
dst->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
|
||||
for (int i = 0; i < src->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
COPY_TLV(dst->analog_beamforming_ve.analog_beam_list[i], src->analog_beamforming_ve.analog_beam_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void copy_config_response(const nfapi_nr_config_response_scf_t *src, nfapi_nr_config_response_scf_t *dst)
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120
|
||||
#define NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG 0xA000
|
||||
#define NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG 0xA001
|
||||
#define NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG 0xA002
|
||||
#define NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG 0xA003
|
||||
|
||||
typedef struct {
|
||||
uint16_t phy_id;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define NFAPI_MAX_NUM_GROUPS 8
|
||||
#define NFAPI_MAX_NUM_CB 8
|
||||
#define NFAPI_MAX_NUM_PRGS 1
|
||||
#define NFAPI_MAX_NUM_BG_IF 1
|
||||
#define NFAPI_MAX_NUM_BG_IF 6
|
||||
#define NFAPI_MAX_NUM_PERIODS 8
|
||||
|
||||
// Extension to the generic structures for single tlv values
|
||||
@@ -496,6 +496,8 @@ typedef struct {
|
||||
typedef struct {
|
||||
nfapi_uint8_tlv_t num_beams_period_vendor_ext;
|
||||
nfapi_uint8_tlv_t analog_bf_vendor_ext;
|
||||
nfapi_uint8_tlv_t total_num_beams_vendor_ext;
|
||||
nfapi_uint8_tlv_t *analog_beam_list;
|
||||
} nfapi_nr_analog_beamforming_ve_t;
|
||||
|
||||
// ERROR enums
|
||||
|
||||
@@ -229,6 +229,33 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap
|
||||
|
||||
FILL_TLV(nfapi_resp->nfapi_config.timing_info_period, NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG, rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
/*
|
||||
// TODO: Uncomment this block when ready to enable the pack of the following VE TLVs in nr_fapi_p5.c
|
||||
// NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG
|
||||
// NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG
|
||||
// NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG
|
||||
// NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.num_beams_period_vendor_ext,
|
||||
NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG,
|
||||
rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.analog_bf_vendor_ext, NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG, rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext,
|
||||
NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG,
|
||||
rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
|
||||
if (nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value > 0) {
|
||||
nfapi_resp->analog_beamforming_ve.analog_beam_list =
|
||||
(nfapi_uint8_tlv_t *)malloc(nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
|
||||
for (int i = 0; i < nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.analog_beam_list[i], NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG, rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
static void test_pack_unpack(nfapi_nr_config_request_scf_t *req)
|
||||
|
||||
@@ -172,8 +172,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
for (int i = 0; i < common_vars->num_beams_period; i++)
|
||||
common_vars->rxdataF[i] = (c16_t **)malloc16(Prx * sizeof(c16_t*));
|
||||
|
||||
common_vars->num_beams = cfg->dbt_config.num_dig_beams;
|
||||
if (common_vars->num_beams > 0) {
|
||||
if (cfg->analog_beamforming_ve.analog_bf_vendor_ext.value) {
|
||||
common_vars->beam_id = (int **)malloc16(common_vars->num_beams_period * sizeof(int*));
|
||||
for (int i = 0; i < common_vars->num_beams_period; i++)
|
||||
common_vars->beam_id[i] = (int*)malloc16_clear(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int));
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
void init_prach_ru_list(RU_t *ru);
|
||||
|
||||
int nr_phy_init_RU(RU_t *ru)
|
||||
void nr_phy_init_RU(RU_t *ru)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
@@ -47,36 +47,40 @@ int nr_phy_init_RU(RU_t *ru)
|
||||
|
||||
AssertFatal(ru->nb_log_antennas > 0 && ru->nb_log_antennas < 13, "ru->nb_log_antennas %d ! \n",ru->nb_log_antennas);
|
||||
|
||||
ru->common.beam_id = malloc16_clear(MAX_NUM_BEAM_PERIODS * sizeof(int*));
|
||||
for(int i = 0; i < MAX_NUM_BEAM_PERIODS; i++)
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_config = &cfg->analog_beamforming_ve;
|
||||
ru->num_beams_period = analog_config->analog_bf_vendor_ext.value ? analog_config->num_beams_period_vendor_ext.value : 1;
|
||||
int nb_tx_streams = ru->nb_tx * ru->num_beams_period;
|
||||
int nb_rx_streams = ru->nb_rx * ru->num_beams_period;
|
||||
|
||||
ru->common.beam_id = malloc16_clear(ru->num_beams_period * sizeof(int*));
|
||||
for(int i = 0; i < ru->num_beams_period; i++)
|
||||
ru->common.beam_id[i] = malloc16_clear(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int));
|
||||
|
||||
if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so allocate memory for time-domain signals
|
||||
// Time-domain signals
|
||||
ru->common.txdata = (int32_t**)malloc16(ru->nb_tx*sizeof(int32_t*));
|
||||
ru->common.rxdata = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) );
|
||||
ru->common.txdata = (int32_t**)malloc16(nb_tx_streams * sizeof(int32_t*));
|
||||
ru->common.rxdata = (int32_t**)malloc16(nb_rx_streams * sizeof(int32_t*));
|
||||
|
||||
|
||||
for (int i = 0; i < ru->nb_tx; i++) {
|
||||
for (int i = 0; i < nb_tx_streams; i++) {
|
||||
// Allocate 10 subframes of I/Q TX signal data (time) if not
|
||||
ru->common.txdata[i] = (int32_t*)malloc16_clear((ru->sf_extension + fp->samples_per_frame)*sizeof(int32_t));
|
||||
ru->common.txdata[i] = (int32_t*)malloc16_clear((ru->sf_extension + fp->samples_per_frame) * sizeof(int32_t));
|
||||
LOG_D(PHY,
|
||||
"[INIT] common.txdata[%d] = %p (%lu bytes,sf_extension %d)\n",
|
||||
i,
|
||||
ru->common.txdata[i],
|
||||
(ru->sf_extension + fp->samples_per_frame) * sizeof(int32_t),
|
||||
ru->sf_extension);
|
||||
ru->common.txdata[i] = &ru->common.txdata[i][ru->sf_extension];
|
||||
ru->common.txdata[i] = &ru->common.txdata[i][ru->sf_extension];
|
||||
|
||||
LOG_D(PHY, "[INIT] common.txdata[%d] = %p \n", i, ru->common.txdata[i]);
|
||||
}
|
||||
for (int i = 0; i < ru->nb_rx; i++) {
|
||||
ru->common.rxdata[i] = (int32_t*)malloc16_clear( fp->samples_per_frame*sizeof(int32_t) );
|
||||
for (int i = 0; i < nb_rx_streams; i++) {
|
||||
ru->common.rxdata[i] = (int32_t*)malloc16_clear(fp->samples_per_frame * sizeof(int32_t));
|
||||
}
|
||||
} // IF5 or local RF
|
||||
else {
|
||||
ru->common.txdata = (int32_t**)NULL;
|
||||
ru->common.rxdata = (int32_t**)NULL;
|
||||
ru->common.txdata = (int32_t**)NULL;
|
||||
ru->common.rxdata = (int32_t**)NULL;
|
||||
}
|
||||
if (ru->function != NGFI_RRU_IF5) { // we need to do RX/TX RU processing
|
||||
LOG_D(PHY, "nb_tx %d\n", ru->nb_tx);
|
||||
@@ -85,7 +89,6 @@ int nr_phy_init_RU(RU_t *ru)
|
||||
ru->common.rxdata_7_5kHz[i] = (int32_t*)malloc16_clear( 2*fp->samples_per_subframe*2*sizeof(int32_t) );
|
||||
LOG_D(PHY, "rxdata_7_5kHz[%d] %p for RU %d\n", i, ru->common.rxdata_7_5kHz[i], ru->idx);
|
||||
}
|
||||
|
||||
|
||||
// allocate precoding input buffers (TX)
|
||||
ru->common.txdataF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*));
|
||||
@@ -94,15 +97,15 @@ int nr_phy_init_RU(RU_t *ru)
|
||||
ru->common.txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP * sizeof(int32_t));
|
||||
|
||||
// allocate IFFT input buffers (TX)
|
||||
ru->common.txdataF_BF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*));
|
||||
LOG_D(PHY, "[INIT] common.txdata_BF= %p (%lu bytes)\n", ru->common.txdataF_BF, ru->nb_tx * sizeof(int32_t *));
|
||||
for (int i = 0; i < ru->nb_tx; i++) {
|
||||
ru->common.txdataF_BF[i] = (int32_t*)malloc16_clear(fp->samples_per_subframe_wCP*sizeof(int32_t) );
|
||||
ru->common.txdataF_BF = (int32_t **)malloc16(nb_tx_streams * sizeof(int32_t*));
|
||||
LOG_D(PHY, "[INIT] common.txdata_BF= %p (%lu bytes)\n", ru->common.txdataF_BF, nb_tx_streams * sizeof(int32_t *));
|
||||
for (int i = 0; i < nb_tx_streams; i++) {
|
||||
ru->common.txdataF_BF[i] = (int32_t*)malloc16_clear(fp->samples_per_subframe_wCP * sizeof(int32_t));
|
||||
LOG_D(PHY, "txdataF_BF[%d] %p for RU %d\n", i, ru->common.txdataF_BF[i], ru->idx);
|
||||
}
|
||||
// allocate FFT output buffers (RX)
|
||||
ru->common.rxdataF = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) );
|
||||
for (int i = 0; i < ru->nb_rx; i++) {
|
||||
ru->common.rxdataF = (int32_t**)malloc16(nb_rx_streams * sizeof(int32_t*));
|
||||
for (int i = 0; i < nb_rx_streams; i++) {
|
||||
// allocate 4 slots of I/Q signal data (frequency)
|
||||
int size = RU_RX_SLOT_DEPTH * fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
ru->common.rxdataF[i] = (int32_t*)malloc16_clear(sizeof(**ru->common.rxdataF) * size);
|
||||
@@ -117,36 +120,34 @@ int nr_phy_init_RU(RU_t *ru)
|
||||
|
||||
for (int i = 0; i < ru->nb_rx; i++) {
|
||||
// largest size for PRACH FFT is 4x98304 (16*24576)
|
||||
ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear( 4*98304*2*sizeof(int16_t) );
|
||||
LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[j][i]);
|
||||
ru->prach_rxsigF[j][i] = (int16_t*)malloc16_clear(4 * 98304 * 2 * sizeof(int16_t));
|
||||
LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n", i, ru->prach_rxsigF[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
AssertFatal(ru->num_gNB <= NUMBER_OF_gNB_MAX,"gNB instances %d > %d\n",
|
||||
ru->num_gNB,NUMBER_OF_gNB_MAX);
|
||||
|
||||
AssertFatal(ru->num_gNB <= NUMBER_OF_gNB_MAX, "gNB instances %d > %d\n", ru->num_gNB,NUMBER_OF_gNB_MAX);
|
||||
|
||||
LOG_D(PHY, "[INIT] %s() ru->num_gNB:%d \n", __FUNCTION__, ru->num_gNB);
|
||||
|
||||
} // !=IF5
|
||||
|
||||
init_prach_ru_list(ru);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void nr_phy_free_RU(RU_t *ru)
|
||||
{
|
||||
LOG_D(PHY, "Freeing RU signal buffers (if_south %s) nb_tx %d\n", ru_if_types[ru->if_south], ru->nb_tx);
|
||||
int nb_tx_streams = ru->nb_tx * ru->num_beams_period;
|
||||
int nb_rx_streams = ru->nb_rx * ru->num_beams_period;
|
||||
|
||||
if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals
|
||||
// Hack: undo what is done at allocation
|
||||
for (int i = 0; i < ru->nb_tx; i++) {
|
||||
for (int i = 0; i < nb_tx_streams; i++) {
|
||||
int32_t *p = &ru->common.txdata[i][-ru->sf_extension];
|
||||
free_and_zero(p);
|
||||
}
|
||||
free_and_zero(ru->common.txdata);
|
||||
|
||||
for (int i = 0; i < ru->nb_rx; i++)
|
||||
for (int i = 0; i < nb_rx_streams; i++)
|
||||
free_and_zero(ru->common.rxdata[i]);
|
||||
free_and_zero(ru->common.rxdata);
|
||||
} // else: IF5 or local RF -> nothing to free()
|
||||
@@ -162,12 +163,12 @@ void nr_phy_free_RU(RU_t *ru)
|
||||
free_and_zero(ru->common.txdataF);
|
||||
|
||||
// free IFFT input buffers (TX)
|
||||
for (int i = 0; i < ru->nb_tx; i++)
|
||||
for (int i = 0; i < nb_tx_streams; i++)
|
||||
free_and_zero(ru->common.txdataF_BF[i]);
|
||||
free_and_zero(ru->common.txdataF_BF);
|
||||
|
||||
// free FFT output buffers (RX)
|
||||
for (int i = 0; i < ru->nb_rx; i++)
|
||||
for (int i = 0; i < nb_rx_streams; i++)
|
||||
free_and_zero(ru->common.rxdataF[i]);
|
||||
free_and_zero(ru->common.rxdataF);
|
||||
|
||||
@@ -176,7 +177,7 @@ void nr_phy_free_RU(RU_t *ru)
|
||||
free_and_zero(ru->prach_rxsigF[j][i]);
|
||||
free_and_zero(ru->prach_rxsigF[j]);
|
||||
}
|
||||
for(int i = 0; i < MAX_NUM_BEAM_PERIODS; ++i)
|
||||
for(int i = 0; i < ru->num_beams_period; ++i)
|
||||
free_and_zero(ru->common.beam_id[i]);
|
||||
free_and_zero(ru->common.beam_id);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
// multi-beam number (for concurrent beams)
|
||||
int bitmap = SL_to_bitmap(cset_start_symb, pdcch_pdu_rel15->DurationSymbols);
|
||||
int beam_nb = beam_index_allocation(dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&gNB->gNB_config,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
|
||||
@@ -519,6 +519,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
// beam number in multi-beam scenario (concurrent beams)
|
||||
int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
||||
int beam_nb = beam_index_allocation(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&gNB->gNB_config,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
|
||||
@@ -42,7 +42,6 @@ void init_prach_list(PHY_VARS_gNB *gNB)
|
||||
for (int i = 0; i < NUMBER_OF_NR_PRACH_MAX; i++){
|
||||
gNB->prach_vars.list[i].frame = -1;
|
||||
gNB->prach_vars.list[i].slot = -1;
|
||||
gNB->prach_vars.list[i].beam_nb = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +49,7 @@ void free_nr_prach_entry(PHY_VARS_gNB *gNB, int prach_id)
|
||||
{
|
||||
gNB->prach_vars.list[prach_id].frame = -1;
|
||||
gNB->prach_vars.list[prach_id].slot = -1;
|
||||
gNB->prach_vars.list[prach_id].beam_nb = -1;
|
||||
free_and_zero(gNB->prach_vars.list[prach_id].beam_nb);
|
||||
}
|
||||
|
||||
int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) {
|
||||
@@ -73,23 +72,31 @@ int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame, int slot, find_type_t type) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
|
||||
int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
|
||||
{
|
||||
int prach_id = find_nr_prach(gNB, SFN, Slot, SEARCH_EXIST_OR_FREE);
|
||||
AssertFatal(((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX)), "illegal or no prach_id found!!! prach_id %d\n", prach_id);
|
||||
gNB_PRACH_list_t *prach = &gNB->prach_vars.list[prach_id];
|
||||
prach->frame = SFN;
|
||||
prach->slot = Slot;
|
||||
prach->beam_nb = 0;
|
||||
if (gNB->common_vars.beam_id) {
|
||||
int fapi_beam_idx = prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx;
|
||||
// TODO no idea how to compute final prach symbol here so for now we go til the end of the slot
|
||||
int temp_nb_symbols = NR_NUMBER_OF_SYMBOLS_PER_SLOT - prach_pdu->prach_start_symbol;
|
||||
int bitmap = SL_to_bitmap(prach_pdu->prach_start_symbol, temp_nb_symbols);
|
||||
prach->beam_nb = beam_index_allocation(fapi_beam_idx, &gNB->common_vars, Slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap);
|
||||
int n_symb = get_nr_prach_duration(prach_pdu->prach_format);
|
||||
prach->beam_nb = calloc(prach_pdu->beamforming.dig_bf_interface, sizeof(*prach->beam_nb));
|
||||
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(fapi_beam_idx,
|
||||
&gNB->gNB_config,
|
||||
&gNB->common_vars,
|
||||
Slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
}
|
||||
}
|
||||
LOG_D(NR_PHY,"Copying prach pdu %d bytes to index %d\n", (int)sizeof(*prach_pdu), prach_id);
|
||||
memcpy(&prach->pdu, prach_pdu, sizeof(*prach_pdu));
|
||||
return prach_id;
|
||||
}
|
||||
|
||||
void init_prach_ru_list(RU_t *ru)
|
||||
@@ -125,10 +132,10 @@ int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
|
||||
void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu, int *beam_id)
|
||||
{
|
||||
int prach_id = find_nr_prach_ru(ru, SFN, Slot, SEARCH_EXIST_OR_FREE);
|
||||
AssertFatal(((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX)) || (prach_id < 0),
|
||||
AssertFatal((prach_id >= 0) && (prach_id < NUMBER_OF_NR_PRACH_MAX),
|
||||
"illegal or no prach_id found!!! prach_id %d\n",
|
||||
prach_id);
|
||||
|
||||
@@ -137,6 +144,7 @@ void nr_fill_prach_ru(RU_t *ru, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_p
|
||||
ru->prach_list[prach_id].slot = Slot;
|
||||
ru->prach_list[prach_id].fmt = prach_pdu->prach_format;
|
||||
ru->prach_list[prach_id].numRA = prach_pdu->num_ra;
|
||||
ru->prach_list[prach_id].beam = beam_id;
|
||||
ru->prach_list[prach_id].prachStartSymbol = prach_pdu->prach_start_symbol;
|
||||
ru->prach_list[prach_id].num_prach_ocas = prach_pdu->num_prach_ocas;
|
||||
pthread_mutex_unlock(&ru->prach_list_mutex);
|
||||
@@ -151,11 +159,10 @@ void free_nr_ru_prach_entry(RU_t *ru, int prach_id)
|
||||
}
|
||||
|
||||
|
||||
void rx_nr_prach_ru(RU_t *ru, int prachFormat, int numRA, int prachStartSymbol, int prachOccasion, int frame, int slot)
|
||||
void rx_nr_prach_ru(RU_t *ru, int prachFormat, int numRA, int beam, int prachStartSymbol, int prachOccasion, int frame, int slot)
|
||||
{
|
||||
AssertFatal(ru != NULL,"ru is null\n");
|
||||
|
||||
int16_t **rxsigF = NULL;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int slot2 = slot;
|
||||
int16_t *prach[ru->nb_rx];
|
||||
@@ -186,15 +193,21 @@ void rx_nr_prach_ru(RU_t *ru, int prachFormat, int numRA, int prachStartSymbol,
|
||||
prachStartSymbol,
|
||||
prachOccasion);
|
||||
|
||||
rxsigF = ru->prach_rxsigF[prachOccasion];
|
||||
int16_t **rxsigF = ru->prach_rxsigF[prachOccasion];
|
||||
|
||||
AssertFatal(ru->if_south == LOCAL_RF || ru->if_south == REMOTE_IF5,
|
||||
"we shouldn't call this if if_south != LOCAL_RF or REMOTE_IF5\n");
|
||||
|
||||
for (int aa=0; aa<ru->nb_rx; aa++){
|
||||
for (int aa = 0; aa < ru->nb_rx; aa++) {
|
||||
if (prach_sequence_length == 0)
|
||||
slot2 = (slot / fp->slots_per_subframe) * fp->slots_per_subframe;
|
||||
prach[aa] = (int16_t*)&ru->common.rxdata[aa][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - ru->N_TA_offset];
|
||||
int idx = aa + beam * ru->nb_rx;
|
||||
if (ru->gNB_list[0]->common_vars.analog_bf && ru->das_enabled) {
|
||||
int bb = beam_in_slot(fp->symbols_per_slot, &ru->gNB_list[0]->common_vars.beam_id[beam][slot * fp->symbols_per_slot]);
|
||||
AssertFatal(bb > -1, "Invalid PRACH beam selection\n");
|
||||
idx = aa + bb * ru->nb_rx;
|
||||
}
|
||||
prach[aa] = (int16_t*)&ru->common.rxdata[idx][fp->get_samples_slot_timestamp(slot2, fp, 0) + sample_offset_slot - ru->N_TA_offset];
|
||||
}
|
||||
|
||||
int reps;
|
||||
|
||||
@@ -257,14 +257,11 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB,
|
||||
int slot,
|
||||
nfapi_nr_pusch_pdu_t *ulsch_pdu);
|
||||
|
||||
void nr_fill_prach(PHY_VARS_gNB *gNB,
|
||||
int SFN,
|
||||
int Slot,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu);
|
||||
int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu);
|
||||
|
||||
void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu,
|
||||
int prachOccasion,
|
||||
int prachOccasion,
|
||||
int frame,
|
||||
int subframe,
|
||||
uint16_t *max_preamble,
|
||||
@@ -274,15 +271,13 @@ void rx_nr_prach(PHY_VARS_gNB *gNB,
|
||||
void rx_nr_prach_ru(RU_t *ru,
|
||||
int prach_fmt,
|
||||
int numRA,
|
||||
int beam,
|
||||
int prachStartSymbol,
|
||||
int prachOccasion,
|
||||
int prachOccasion,
|
||||
int frame,
|
||||
int subframe);
|
||||
|
||||
void nr_fill_prach_ru(RU_t *ru,
|
||||
int SFN,
|
||||
int Slot,
|
||||
nfapi_nr_prach_pdu_t *prach_pdu);
|
||||
void nr_fill_prach_ru(RU_t *ru,int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu, int *beam_nb);
|
||||
|
||||
int16_t find_nr_prach(PHY_VARS_gNB *gNB,int frame,int slot, find_type_t type);
|
||||
int16_t find_nr_prach_ru(RU_t *ru,int frame,int slot, find_type_t type);
|
||||
|
||||
@@ -76,7 +76,12 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pusch_pdu_t
|
||||
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(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap);
|
||||
ulsch->beam_nb = beam_index_allocation(fapi_beam_idx,
|
||||
&gNB->gNB_config,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
}
|
||||
ulsch->frame = frame;
|
||||
ulsch->slot = slot;
|
||||
|
||||
@@ -73,7 +73,12 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB,
|
||||
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(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap);
|
||||
pucch->beam_nb = beam_index_allocation(fapi_beam_idx,
|
||||
&gNB->gNB_config,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
}
|
||||
memcpy((void *)&pucch->pucch_pdu, (void *)pucch_pdu, sizeof(nfapi_nr_pucch_pdu_t));
|
||||
LOG_D(PHY,
|
||||
|
||||
@@ -59,7 +59,12 @@ void nr_fill_srs(PHY_VARS_gNB *gNB, frame_t frame, slot_t slot, nfapi_nr_srs_pdu
|
||||
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(fapi_beam_idx, &gNB->common_vars, slot, NR_NUMBER_OF_SYMBOLS_PER_SLOT, bitmap);
|
||||
srs->beam_nb = beam_index_allocation(fapi_beam_idx,
|
||||
&gNB->gNB_config,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
bitmap);
|
||||
}
|
||||
memcpy((void *)&srs->srs_pdu, (void *)srs_pdu, sizeof(nfapi_nr_srs_pdu_t));
|
||||
break;
|
||||
|
||||
@@ -457,7 +457,7 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc,
|
||||
LOG_I(PHY, "[UE%d] Initial sync failed : Estimated power: %d dB\n", ue->Mod_id, ue->measurements.rx_power_avg_dB[0]);
|
||||
#endif
|
||||
} else {
|
||||
LOG_A(PHY, "Initial sync successful, PCI: %d\n",fp->Nid_cell);
|
||||
LOG_A(PHY, "Initial sync successful, PCI: %d SSB %d\n", fp->Nid_cell, fp->ssb_index);
|
||||
}
|
||||
// exit_fun("debug exit");
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT);
|
||||
|
||||
@@ -172,6 +172,7 @@ typedef struct RU_prec_t_s{
|
||||
|
||||
typedef struct {
|
||||
int aid;
|
||||
int beam;
|
||||
struct RU_t_s *ru;
|
||||
int startSymbol;
|
||||
int endSymbol;
|
||||
@@ -181,6 +182,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int aid;
|
||||
int beam;
|
||||
struct RU_t_s *ru;
|
||||
int slot;
|
||||
int startSymbol;
|
||||
@@ -195,6 +197,7 @@ typedef struct {
|
||||
int numRA;
|
||||
int prachStartSymbol;
|
||||
int num_prach_ocas;
|
||||
int *beam;
|
||||
} RU_PRACH_list_t;
|
||||
|
||||
#define NUMBER_OF_NR_RU_PRACH_MAX 8
|
||||
@@ -488,8 +491,12 @@ typedef struct RU_t_s {
|
||||
int nb_rx;
|
||||
/// number of TX paths on device
|
||||
int nb_tx;
|
||||
/// number of concurrent analog beams in period
|
||||
int num_beams_period;
|
||||
/// number of logical antennas at TX beamformer input
|
||||
int nb_log_antennas;
|
||||
// analog DAS enabled
|
||||
bool das_enabled;
|
||||
/// maximum PDSCH RS EPRE
|
||||
int max_pdschReferenceSignalPower;
|
||||
/// maximum RX gain
|
||||
|
||||
@@ -140,7 +140,7 @@ typedef struct {
|
||||
int frame;
|
||||
int slot;
|
||||
// identifier for concurrent beams
|
||||
int beam_nb;
|
||||
int *beam_nb;
|
||||
nfapi_nr_prach_pdu_t pdu;
|
||||
} gNB_PRACH_list_t;
|
||||
|
||||
@@ -287,7 +287,6 @@ typedef struct {
|
||||
/// - first index: beam index (for concurrent beams)
|
||||
/// - second index: beam_id [0.. symbols_per_frame[
|
||||
int **beam_id;
|
||||
int num_beams;
|
||||
int num_beams_period;
|
||||
bool analog_bf;
|
||||
int32_t *debugBuff;
|
||||
|
||||
@@ -157,9 +157,9 @@ void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti
|
||||
UL_tti_req->SFN,
|
||||
UL_tti_req->Slot);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu;
|
||||
nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
int id = nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
if (gNB->RU_list[0]->if_south == LOCAL_RF || gNB->RU_list[0]->if_south == REMOTE_IF5)
|
||||
nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu, gNB->prach_vars.list[id].beam_nb);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE:
|
||||
LOG_D(NR_PHY,
|
||||
|
||||
@@ -42,56 +42,41 @@
|
||||
#include "assertions.h"
|
||||
|
||||
#include <time.h>
|
||||
uint8_t get_nr_prach_duration(uint8_t prach_format){
|
||||
|
||||
switch(prach_format){
|
||||
|
||||
case 0: // format 0
|
||||
return 0;
|
||||
|
||||
case 1: // format 1
|
||||
return 0;
|
||||
|
||||
case 2: // format 2
|
||||
return 0;
|
||||
|
||||
case 3: // format 3
|
||||
return 0;
|
||||
|
||||
case 4: // format A1
|
||||
return 2;
|
||||
|
||||
case 5: // format A2
|
||||
return 4;
|
||||
|
||||
case 6: // format A3
|
||||
return 6;
|
||||
|
||||
case 7: // format B1
|
||||
return 2;
|
||||
|
||||
case 8: // format B4
|
||||
return 12;
|
||||
|
||||
case 9: // format C0
|
||||
return 2;
|
||||
|
||||
case 10: // format C2
|
||||
return 6;
|
||||
|
||||
case 11: // format A1/B1
|
||||
return 2;
|
||||
|
||||
case 12: // format A2/B2
|
||||
return 4;
|
||||
|
||||
case 13: // format A3/B3
|
||||
return 6;
|
||||
|
||||
default :
|
||||
AssertFatal(1==0,"Invalid Prach format\n");
|
||||
break;
|
||||
|
||||
uint8_t get_nr_prach_duration(uint8_t prach_format)
|
||||
{
|
||||
switch(prach_format) {
|
||||
case 0: // format 0
|
||||
return 0;
|
||||
case 1: // format 1
|
||||
return 0;
|
||||
case 2: // format 2
|
||||
return 0;
|
||||
case 3: // format 3
|
||||
return 0;
|
||||
case 4: // format A1
|
||||
return 2;
|
||||
case 5: // format A2
|
||||
return 4;
|
||||
case 6: // format A3
|
||||
return 6;
|
||||
case 7: // format B1
|
||||
return 2;
|
||||
case 8: // format B4
|
||||
return 12;
|
||||
case 9: // format C0
|
||||
return 2;
|
||||
case 10: // format C2
|
||||
return 6;
|
||||
case 11: // format A1/B1
|
||||
return 2;
|
||||
case 12: // format A2/B2
|
||||
return 4;
|
||||
case 13: // format A3/B3
|
||||
return 6;
|
||||
default :
|
||||
AssertFatal(false, "Invalid Prach format\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
// RU OFDM Modulator gNodeB
|
||||
// OFDM modulation core routine, generates a first_symbol to first_symbol+num_symbols on a particular slot and TX antenna port
|
||||
void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa)
|
||||
void nr_feptx0(RU_t *ru, int tti_tx, int first_symbol, int num_symbols, int aa)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
@@ -175,57 +175,54 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
|
||||
|
||||
}
|
||||
|
||||
void nr_feptx_prec(RU_t *ru, int frame_tx, int tti_tx)
|
||||
int beam_in_slot(uint16_t symbols_per_slot, int *beam_id)
|
||||
{
|
||||
PHY_VARS_gNB **gNB_list = ru->gNB_list,*gNB;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
int slot_tx = tti_tx;
|
||||
int txdataF_offset = (tti_tx*fp->samples_per_slot_wCP);
|
||||
int beam = -1;
|
||||
for (int i = 0; i < symbols_per_slot; i++) {
|
||||
if (beam_id[i] != -1) {
|
||||
if (beam == -1)
|
||||
beam = beam_id[i];
|
||||
AssertFatal(beam == beam_id[i], "Error! Two beams in the same slot for the same index\n");
|
||||
} else {
|
||||
beam = beam_id[i];
|
||||
}
|
||||
}
|
||||
return beam;
|
||||
}
|
||||
|
||||
void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx)
|
||||
{
|
||||
PHY_VARS_gNB **gNB_list = ru->gNB_list;
|
||||
AssertFatal(ru->num_gNB == 1, "Cannot handle more than 1 gNB\n");
|
||||
PHY_VARS_gNB *gNB = gNB_list[0];
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int txdataF_offset = slot_tx * fp->samples_per_slot_wCP;
|
||||
start_meas(&ru->precoding_stats);
|
||||
AssertFatal(ru->nb_log_antennas > 0, "ru->nb_log_antennas is 0!\n");
|
||||
|
||||
if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT)
|
||||
return;
|
||||
|
||||
if (ru->num_gNB == 1) {
|
||||
gNB = gNB_list[0];
|
||||
if (gNB->common_vars.analog_bf) {
|
||||
for (int i = 0; i < ru->num_beams_period; i++) {
|
||||
memcpy((void*) &ru->common.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(void*) &gNB->common_vars.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
if (ru->config.dbt_config.num_dig_beams != 0) {
|
||||
for(int i = 0; i < gNB->common_vars.num_beams_period; ++i) {
|
||||
memcpy((void*) &ru->common.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(void*) &gNB->common_vars.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
if (ru->config.dbt_config.num_dig_beams == 0 || gNB->common_vars.analog_bf) {
|
||||
for (int i = 0; i < ru->nb_log_antennas; ++i) {
|
||||
// TODO hardcoded beam to 0, still need to understand how to handle this properly
|
||||
memcpy(ru->common.txdataF_BF[i], &gNB->common_vars.txdataF[0][i][txdataF_offset], fp->samples_per_slot_wCP * sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i = 0; i < ru->nb_log_antennas; ++i) {
|
||||
// TODO hardcoded beam to 0, still need to understand how to handle this properly
|
||||
memcpy(ru->common.txdataF[i], &gNB->common_vars.txdataF[0][i][txdataF_offset], fp->samples_per_slot_wCP * sizeof(int32_t));
|
||||
}
|
||||
for (int l = 0; l < fp->symbols_per_slot; l++) {
|
||||
for (int aa = 0; aa < ru->nb_tx; aa++) {
|
||||
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
|
||||
nr_beam_precoding((c16_t **)ru->common.txdataF,
|
||||
(c16_t **)ru->common.txdataF_BF,
|
||||
fp,
|
||||
ru->beam_weights[0],
|
||||
tti_tx,
|
||||
l,
|
||||
aa,
|
||||
ru->nb_log_antennas,
|
||||
0);
|
||||
}
|
||||
// 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++) {
|
||||
for (int i = 0; i < ru->nb_tx; ++i) {
|
||||
int tx_idx = i + b * ru->nb_tx;
|
||||
memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_offset],
|
||||
(void*)&gNB->common_vars.txdataF[b][i][txdataF_offset],
|
||||
fp->samples_per_slot_wCP * sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
|
||||
}
|
||||
stop_meas(&ru->precoding_stats);
|
||||
}
|
||||
@@ -238,6 +235,7 @@ void nr_feptx(void *arg)
|
||||
RU_t *ru = feptx->ru;
|
||||
int slot = feptx->slot;
|
||||
int aa = feptx->aid;
|
||||
int bb = feptx->beam;
|
||||
int startSymbol = feptx->startSymbol;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
int numSymbols = feptx->numSymbols;
|
||||
@@ -246,44 +244,41 @@ void nr_feptx(void *arg)
|
||||
int txdataF_BF_offset = startSymbol * fp->ofdm_symbol_size;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->aid , 1);
|
||||
int tx_idx = aa + bb * ru->nb_tx;
|
||||
|
||||
if (aa == 0)
|
||||
if (tx_idx == 0)
|
||||
start_meas(&ru->precoding_stats);
|
||||
|
||||
if (ru->config.dbt_config.num_dig_beams != 0) {
|
||||
for(int i = 0; i < ru->gNB_list[0]->common_vars.num_beams_period; i++) {
|
||||
memcpy(&ru->common.beam_id[i][slot * fp->symbols_per_slot],
|
||||
&ru->gNB_list[0]->common_vars.beam_id[i][slot * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
if (ru->gNB_list[0]->common_vars.analog_bf && !ru->das_enabled) {
|
||||
memcpy(&ru->common.beam_id[bb][slot * fp->symbols_per_slot],
|
||||
&ru->gNB_list[0]->common_vars.beam_id[bb][slot * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
|
||||
// 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)
|
||||
memcpy((void*)&ru->common.txdataF_BF[aa][txdataF_BF_offset],
|
||||
(void*)&ru->gNB_list[0]->common_vars.txdataF[0][aa][txdataF_offset], // TODO hardcoded beam to 0, still need to understand how to handle this properly
|
||||
numSamples * sizeof(int32_t));
|
||||
else {
|
||||
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
|
||||
for(int i = 0; i < fp->symbols_per_slot; ++i) {
|
||||
nr_beam_precoding((c16_t **)ru->gNB_list[0]->common_vars.txdataF,
|
||||
(c16_t **)ru->common.txdataF_BF,
|
||||
fp,
|
||||
ru->beam_weights[0],
|
||||
slot,
|
||||
i,
|
||||
aa,
|
||||
ru->nb_log_antennas,
|
||||
txdataF_offset);
|
||||
}
|
||||
if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) {
|
||||
int beam_idx;
|
||||
if (ru->das_enabled) {
|
||||
AssertFatal(ru->gNB_list[0]->common_vars.analog_bf, "DAS implemented only for analog beamforming\n");
|
||||
beam_idx = beam_in_slot(fp->symbols_per_slot, &ru->gNB_list[0]->common_vars.beam_id[bb][slot * fp->symbols_per_slot]);
|
||||
if (beam_idx > -1)
|
||||
beam_idx = aa + beam_idx * ru->nb_tx;
|
||||
} else
|
||||
beam_idx = tx_idx;
|
||||
if (beam_idx > -1)
|
||||
memcpy((void*)&ru->common.txdataF_BF[beam_idx][txdataF_BF_offset],
|
||||
(void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset],
|
||||
numSamples * sizeof(int32_t));
|
||||
} else {
|
||||
AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n");
|
||||
}
|
||||
|
||||
if (aa==0)
|
||||
if (tx_idx == 0)
|
||||
stop_meas(&ru->precoding_stats);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+feptx->aid , 0);
|
||||
|
||||
////////////FEPTX////////////
|
||||
nr_feptx0(ru, slot, startSymbol, numSymbols, aa);
|
||||
nr_feptx0(ru, slot, startSymbol, numSymbols, tx_idx);
|
||||
|
||||
// Task completed in //
|
||||
completed_task_ans(feptx->ans);
|
||||
@@ -304,34 +299,43 @@ void nr_feptx_tp(RU_t *ru, int frame_tx, int slot)
|
||||
task_ans_t ans;
|
||||
init_task_ans(&ans, sz);
|
||||
|
||||
if (ru->das_enabled) {
|
||||
for (int i = 0; i < ru->num_beams_period * ru->nb_tx; i++) {
|
||||
// TODO why is it allocated per subframe?
|
||||
memset(&ru->common.txdataF_BF[i][0], 0, ru->nr_frame_parms->samples_per_subframe_wCP * sizeof(int32_t));
|
||||
}
|
||||
}
|
||||
|
||||
int nbfeptx = 0;
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++) {
|
||||
feptx_cmd_t *feptx_cmd = &arr[nbfeptx];
|
||||
feptx_cmd->ans = &ans;
|
||||
|
||||
feptx_cmd->aid = aid;
|
||||
feptx_cmd->ru = ru;
|
||||
feptx_cmd->slot = slot;
|
||||
feptx_cmd->startSymbol = 0;
|
||||
feptx_cmd->numSymbols =
|
||||
(ru->half_slot_parallelization > 0) ? ru->nr_frame_parms->symbols_per_slot >> 1 : ru->nr_frame_parms->symbols_per_slot;
|
||||
|
||||
task_t t = {.func = nr_feptx, .args = feptx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
nbfeptx++;
|
||||
if (ru->half_slot_parallelization > 0) {
|
||||
for (int beam = 0; beam < ru->num_beams_period; beam++) {
|
||||
for (int aid = 0; aid < ru->nb_tx; aid++) {
|
||||
feptx_cmd_t *feptx_cmd = &arr[nbfeptx];
|
||||
feptx_cmd->ans = &ans;
|
||||
|
||||
feptx_cmd->beam = beam;
|
||||
feptx_cmd->aid = aid;
|
||||
feptx_cmd->ru = ru;
|
||||
feptx_cmd->slot = slot;
|
||||
feptx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feptx_cmd->numSymbols = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feptx_cmd->startSymbol = 0;
|
||||
feptx_cmd->numSymbols =
|
||||
(ru->half_slot_parallelization > 0) ? ru->nr_frame_parms->symbols_per_slot >> 1 : ru->nr_frame_parms->symbols_per_slot;
|
||||
|
||||
task_t t = {.func = nr_feptx, .args = feptx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
nbfeptx++;
|
||||
if (ru->half_slot_parallelization > 0) {
|
||||
feptx_cmd_t *feptx_cmd = &arr[nbfeptx];
|
||||
feptx_cmd->ans = &ans;
|
||||
feptx_cmd->beam = beam;
|
||||
feptx_cmd->aid = aid;
|
||||
feptx_cmd->ru = ru;
|
||||
feptx_cmd->slot = slot;
|
||||
feptx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feptx_cmd->numSymbols = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
|
||||
task_t t = {.func = nr_feptx, .args = feptx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
nbfeptx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
join_task_ans(&ans);
|
||||
@@ -345,26 +349,35 @@ void nr_feptx_tp(RU_t *ru, int frame_tx, int slot)
|
||||
void nr_fep(void* arg)
|
||||
{
|
||||
feprx_cmd_t *feprx_cmd = (feprx_cmd_t *)arg;
|
||||
RU_t *ru = feprx_cmd->ru;
|
||||
int aid = feprx_cmd->aid;
|
||||
int tti_rx = feprx_cmd->slot;
|
||||
int startSymbol = feprx_cmd->startSymbol;
|
||||
int endSymbol = feprx_cmd->endSymbol;
|
||||
RU_t *ru = feprx_cmd->ru;
|
||||
int aid = feprx_cmd->aid;
|
||||
int beam = feprx_cmd->beam;
|
||||
int slot = feprx_cmd->slot;
|
||||
int startSymbol = feprx_cmd->startSymbol;
|
||||
int endSymbol = feprx_cmd->endSymbol;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
|
||||
LOG_D(PHY,"aid %d, frame %d slot %d, startSymbol %d, endSymbol %d\n", aid, ru->proc.frame_rx, tti_rx, startSymbol, endSymbol);
|
||||
|
||||
LOG_D(PHY,"aid %d, frame %d slot %d, startSymbol %d, endSymbol %d\n", aid, ru->proc.frame_rx, slot, startSymbol, endSymbol);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+aid, 1);
|
||||
|
||||
int offset = (tti_rx % RU_RX_SLOT_DEPTH) * fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
for (int l = startSymbol; l <= endSymbol; l++)
|
||||
nr_slot_fep_ul(fp,
|
||||
ru->common.rxdata[aid],
|
||||
&ru->common.rxdataF[aid][offset],
|
||||
l,
|
||||
tti_rx,
|
||||
ru->N_TA_offset);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+aid, 0);
|
||||
int idx = aid + beam * ru->nb_rx;
|
||||
int beam_idx = idx;
|
||||
if (ru->gNB_list[0]->common_vars.analog_bf && ru->das_enabled) {
|
||||
int bb = beam_in_slot(fp->symbols_per_slot, &ru->gNB_list[0]->common_vars.beam_id[beam][slot * fp->symbols_per_slot]);
|
||||
beam_idx = bb > -1 ? aid + bb * ru->nb_rx : -1;
|
||||
}
|
||||
int offset = (slot % RU_RX_SLOT_DEPTH) * fp->symbols_per_slot * fp->ofdm_symbol_size;
|
||||
if (beam_idx > -1) {
|
||||
for (int l = startSymbol; l <= endSymbol; l++)
|
||||
nr_slot_fep_ul(fp,
|
||||
ru->common.rxdata[beam_idx],
|
||||
&ru->common.rxdataF[idx][offset],
|
||||
l,
|
||||
slot,
|
||||
ru->N_TA_offset);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX + aid, 0);
|
||||
|
||||
// Task completed in //
|
||||
completed_task_ans(feprx_cmd->ans);
|
||||
@@ -382,34 +395,36 @@ void nr_fep_tp(RU_t *ru, int slot) {
|
||||
task_ans_t ans;
|
||||
init_task_ans(&ans, sz);
|
||||
|
||||
for (int aid=0;aid<ru->nb_rx;aid++) {
|
||||
feprx_cmd_t *feprx_cmd = &arr[nbfeprx];
|
||||
feprx_cmd->ans = &ans;
|
||||
|
||||
feprx_cmd->aid = aid;
|
||||
feprx_cmd->ru = ru;
|
||||
feprx_cmd->slot = ru->proc.tti_rx;
|
||||
feprx_cmd->startSymbol = 0;
|
||||
feprx_cmd->endSymbol = (ru->half_slot_parallelization > 0) ? (ru->nr_frame_parms->symbols_per_slot >> 1) - 1
|
||||
: (ru->nr_frame_parms->symbols_per_slot - 1);
|
||||
|
||||
task_t t = {.func = nr_fep, .args = feprx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
nbfeprx++;
|
||||
if (ru->half_slot_parallelization > 0) {
|
||||
for (int beam = 0; beam < ru->num_beams_period; beam++) {
|
||||
for (int aid = 0; aid < ru->nb_rx; aid++) {
|
||||
feprx_cmd_t *feprx_cmd = &arr[nbfeprx];
|
||||
feprx_cmd->ans = &ans;
|
||||
|
||||
feprx_cmd->beam = beam;
|
||||
feprx_cmd->aid = aid;
|
||||
feprx_cmd->ru = ru;
|
||||
feprx_cmd->slot = ru->proc.tti_rx;
|
||||
feprx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feprx_cmd->endSymbol = ru->nr_frame_parms->symbols_per_slot - 1;
|
||||
feprx_cmd->startSymbol = 0;
|
||||
feprx_cmd->endSymbol = (ru->half_slot_parallelization > 0) ? (ru->nr_frame_parms->symbols_per_slot >> 1) - 1
|
||||
: (ru->nr_frame_parms->symbols_per_slot - 1);
|
||||
|
||||
task_t t = {.func = nr_fep, .args = feprx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
|
||||
nbfeprx++;
|
||||
if (ru->half_slot_parallelization > 0) {
|
||||
feprx_cmd_t *feprx_cmd = &arr[nbfeprx];
|
||||
feprx_cmd->ans = &ans;
|
||||
feprx_cmd->beam = beam;
|
||||
feprx_cmd->aid = aid;
|
||||
feprx_cmd->ru = ru;
|
||||
feprx_cmd->slot = ru->proc.tti_rx;
|
||||
feprx_cmd->startSymbol = ru->nr_frame_parms->symbols_per_slot >> 1;
|
||||
feprx_cmd->endSymbol = ru->nr_frame_parms->symbols_per_slot - 1;
|
||||
|
||||
task_t t = {.func = nr_fep, .args = feprx_cmd};
|
||||
pushTpool(ru->threadPool, t);
|
||||
|
||||
nbfeprx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
join_task_ans(&ans);
|
||||
|
||||
@@ -45,18 +45,23 @@
|
||||
//#define DEBUG_RXDATA
|
||||
//#define SRS_IND_DEBUG
|
||||
|
||||
int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, int bitmap_symbols)
|
||||
int beam_index_allocation(int fapi_beam_index,
|
||||
nfapi_nr_config_request_scf_t *cfg,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
int bitmap_symbols)
|
||||
{
|
||||
if (!common_vars->beam_id)
|
||||
return 0;
|
||||
|
||||
int idx = -1;
|
||||
int ru_beam_idx = cfg->analog_beamforming_ve.analog_beam_list[fapi_beam_index].value;
|
||||
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++) {
|
||||
if (((bitmap_symbols >> i) & 0x01) == 0)
|
||||
continue;
|
||||
int current_beam = common_vars->beam_id[j][slot * symbols_per_slot + i];
|
||||
if (current_beam == -1 || current_beam == fapi_beam_index)
|
||||
if (current_beam == -1 || current_beam == ru_beam_idx)
|
||||
idx = j;
|
||||
else {
|
||||
idx = -1;
|
||||
@@ -66,12 +71,12 @@ int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int s
|
||||
if (idx != -1)
|
||||
break;
|
||||
}
|
||||
AssertFatal(idx >= 0, "Couldn't allocate beam ID %d\n", fapi_beam_index);
|
||||
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))
|
||||
common_vars->beam_id[idx][slot * symbols_per_slot + j] = fapi_beam_index;
|
||||
common_vars->beam_id[idx][slot * symbols_per_slot + j] = ru_beam_idx;
|
||||
}
|
||||
LOG_D(PHY, "Allocating beam %d in slot %d\n", idx, slot);
|
||||
LOG_D(PHY, "Allocating beam_id[%d] %d in slot %d\n", idx, ru_beam_idx, slot);
|
||||
return idx;
|
||||
}
|
||||
|
||||
@@ -132,6 +137,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n
|
||||
// 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(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
cfg,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
@@ -273,6 +279,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
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(pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
cfg,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
|
||||
@@ -44,8 +44,14 @@ void nr_feptx_prec_control(RU_t *ru,int frame,int tti_tx);
|
||||
void nr_fep_tp(RU_t *ru, int slot);
|
||||
void nr_feptx_tp(RU_t *ru, int frame_tx, int slot);
|
||||
void feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
|
||||
int nr_phy_init_RU(RU_t *ru);
|
||||
void nr_phy_init_RU(RU_t *ru);
|
||||
void nr_phy_free_RU(RU_t *ru);
|
||||
void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot);
|
||||
int beam_index_allocation(int fapi_beam_index, NR_gNB_COMMON *common_vars, int slot, int symbols_per_slot, int bitmap_symbols);
|
||||
int beam_in_slot(uint16_t symbols_per_slot, int *beam_id);
|
||||
int beam_index_allocation(int fapi_beam_index,
|
||||
nfapi_nr_config_request_scf_t *cfg,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
int bitmap_symbols);
|
||||
#endif
|
||||
|
||||
@@ -774,7 +774,7 @@ int main(int argc, char **argv){
|
||||
}
|
||||
}
|
||||
|
||||
rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, prachOccasion, frame, slot);
|
||||
rx_nr_prach_ru(ru, prach_format, numRA, 0, prachStartSymbol, prachOccasion, frame, slot);
|
||||
|
||||
for (int i = 0; i < ru->nb_rx; ++i)
|
||||
gNB->prach_vars.rxsigF[i] = ru->prach_rxsigF[prachOccasion][i];
|
||||
|
||||
@@ -112,7 +112,8 @@ typedef enum {
|
||||
#define CONFIG_STRING_RU_NUM_INTERFACES "num_interfaces"
|
||||
#define CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION "half_slot_parallelization"
|
||||
#define CONFIG_STRING_RU_RU_THREAD_CORE "ru_thread_core"
|
||||
#define CONFIG_STRING_RU_GPIO_CONTROL "gpio_controller"
|
||||
#define CONFIG_STRING_RU_DAS_CONTROL "enable_analog_das"
|
||||
#define CONFIG_STRING_RU_GPIO_CONTROL "gpio_controller"
|
||||
|
||||
#define HLP_RU_SF_AHEAD "LTE TX processing advance"
|
||||
#define HLP_RU_SL_AHEAD "NR TX processing advance"
|
||||
@@ -125,6 +126,7 @@ typedef enum {
|
||||
#define HLP_RU_NUM_INTERFACES "Number of network interfaces for RU"
|
||||
#define HLP_RU_HALF_SLOT_PARALLELIZATION "run half slots in parallel in RU FEP"
|
||||
#define HLP_RU_RU_THREAD_CORE "id of core to pin ru_thread, -1 is default"
|
||||
#define HLP_RU_DAS_CONTROL "enable DAS via analog beamforming"
|
||||
#define HLP_RU_GPIO_CONTROL "set the GPIO control type for the RU"
|
||||
|
||||
#define RU_LOCAL_IF_NAME_IDX 0
|
||||
@@ -169,7 +171,9 @@ typedef enum {
|
||||
#define RU_NUM_INTERFACES 39
|
||||
#define RU_HALF_SLOT_PARALLELIZATION 40
|
||||
#define RU_RU_THREAD_CORE 41
|
||||
#define RU_GPIO_CONTROL 42
|
||||
#define RU_DAS_CONTROL 42
|
||||
#define RU_GPIO_CONTROL 43
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* RU configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
@@ -217,7 +221,8 @@ typedef enum {
|
||||
{CONFIG_STRING_RU_NUM_TP_CORES, HLP_RU_NUM_TP_CORES, 0, .uptr=NULL, .defintval=2, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_NUM_INTERFACES, HLP_RU_NUM_INTERFACES, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION, HLP_RU_HALF_SLOT_PARALLELIZATION, 0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_RU_THREAD_CORE, HLP_RU_RU_THREAD_CORE, 0, .uptr=NULL, .defintval=-1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_DAS_CONTROL, HLP_RU_DAS_CONTROL, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_RU_GPIO_CONTROL, HLP_RU_GPIO_CONTROL, 0, .strptr=NULL, .defstrval="generic", TYPE_STRING, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
#define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming"
|
||||
#define CONFIG_STRING_MACRLC_BEAM_DURATION "beam_duration"
|
||||
#define CONFIG_STRING_MACRLC_BEAMS_PERIOD "beams_per_period"
|
||||
#define CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST "beam_weights"
|
||||
#define CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD "pusch_RSSI_Threshold"
|
||||
#define CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD "pucch_RSSI_Threshold"
|
||||
|
||||
@@ -140,6 +141,7 @@
|
||||
{CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING, HLP_MACRLC_AB, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_BEAM_DURATION, HLP_MACRLC_BEAM_DURATION, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_BEAMS_PERIOD, HLP_MACRLC_BEAMS_PERIOD, 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY,0}, \
|
||||
{CONFIG_STRING_MACRLC_PUSCH_RSSI_THRESHOLD, HLP_MACRLC_PUSCH_RSSI_THRESHOLD, \
|
||||
0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{CONFIG_STRING_MACRLC_PUCCH_RSSI_THRESHOLD, HLP_MACRLC_PUCCH_RSSI_THRESHOLD, \
|
||||
@@ -185,8 +187,9 @@
|
||||
#define MACRLC_ANALOG_BEAMFORMING_IDX 35
|
||||
#define MACRLC_ANALOG_BEAM_DURATION_IDX 36
|
||||
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 37
|
||||
#define MACRLC_PUSCH_RSSI_THRES_IDX 38
|
||||
#define MACRLC_PUCCH_RSSI_THRES_IDX 39
|
||||
#define MACRLC_BEAMWEIGHTS_IDX 38
|
||||
#define MACRLC_PUSCH_RSSI_THRES_IDX 39
|
||||
#define MACRLC_PUCCH_RSSI_THRES_IDX 40
|
||||
|
||||
#define MACRLCPARAMS_CHECK { \
|
||||
{ .s5 = { NULL } }, \
|
||||
@@ -227,6 +230,7 @@
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s2 = { config_check_intrange, {-1280, 0}} }, /* PUSCH RSSI threshold range */ \
|
||||
{ .s2 = { config_check_intrange, {-1280, 0}} }, /* PUCCH RSSI threshold range */ \
|
||||
}
|
||||
|
||||
@@ -1465,19 +1465,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
config.timer_config.n311,
|
||||
config.timer_config.t319);
|
||||
|
||||
if (config_isparamset(GNBParamList.paramarray[0], GNB_BEAMWEIGHTS_IDX)) {
|
||||
int n = GNBParamList.paramarray[0][GNB_BEAMWEIGHTS_IDX].numelt;
|
||||
AssertFatal(n % num_tx == 0, "Error! Number of beam input needs to be multiple of TX antennas\n");
|
||||
// each beam is described by a set of weights (one for each antenna)
|
||||
// on the other hand in case of analog beamforming an index to the RU beam identifier is provided
|
||||
config.nb_bfw[0] = num_tx; // number of tx antennas
|
||||
config.nb_bfw[1] = n / num_tx; // number of beams
|
||||
config.bw_list = malloc16_clear(n * sizeof(*config.bw_list));
|
||||
for (int b = 0; b < n; b++) {
|
||||
config.bw_list[b] = GNBParamList.paramarray[0][GNB_BEAMWEIGHTS_IDX].iptr[b];
|
||||
}
|
||||
}
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = get_scc_config(cfg, config.minRXTXTIME);
|
||||
//xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc);
|
||||
NR_ServingCellConfig_t *scd = get_scd_config(cfg);
|
||||
@@ -1581,6 +1568,22 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
beam_info->beams_per_period = beams_per_period;
|
||||
beam_info->beam_allocation_size = -1; // to be initialized once we have information on frame configuration
|
||||
}
|
||||
if (config_isparamset(MacRLC_ParamList.paramarray[j], MACRLC_BEAMWEIGHTS_IDX)) {
|
||||
int n = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].numelt;
|
||||
int num_beam = n;
|
||||
if (!ab) {
|
||||
AssertFatal(n % num_tx == 0, "Error! Number of beam input needs to be multiple of TX antennas\n");
|
||||
num_beam = n / num_tx;
|
||||
}
|
||||
// each beam is described by a set of weights (one for each antenna)
|
||||
// in case of analog beamforming an index to the RU beam identifier is provided
|
||||
// (one for each beam regardless of the number of antennas per beam)
|
||||
config.nb_bfw[0] = num_tx; // number of tx antennas
|
||||
config.nb_bfw[1] = num_beam; // number of beams weights/indices
|
||||
config.bw_list = malloc16_clear(n * sizeof(*config.bw_list));
|
||||
for (int b = 0; b < n; b++)
|
||||
config.bw_list[b] = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].iptr[b];
|
||||
}
|
||||
// triggers also PHY initialization in case we have L1 via FAPI
|
||||
nr_mac_config_scc(RC.nrmac[j], scc, &config);
|
||||
} // for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
||||
|
||||
@@ -137,7 +137,6 @@ typedef enum {
|
||||
#define GNB_CONFIG_STRING_GNB_CU_UP_ID "gNB_CU_UP_ID"
|
||||
#define GNB_CONFIG_STRING_NUM_DL_HARQPROCESSES "num_dlharq"
|
||||
#define GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES "num_ulharq"
|
||||
#define GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST "beam_weights"
|
||||
|
||||
#define GNB_CONFIG_HLP_STRING_ENABLE_SDAP "enable the SDAP layer\n"
|
||||
#define GNB_CONFIG_HLP_FORCE256QAMOFF "suppress activation of 256 QAM despite UE support"
|
||||
@@ -190,7 +189,6 @@ typedef enum {
|
||||
{GNB_CONFIG_STRING_DISABLE_HARQ, GNB_CONFIG_HLP_DISABLE_HARQ, PARAMFLAG_BOOL, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_NUM_DL_HARQPROCESSES, GNB_CONFIG_HLP_NUM_DL_HARQ, 0, .iptr=NULL, .defintval=16, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_NUM_UL_HARQPROCESSES, GNB_CONFIG_HLP_NUM_UL_HARQ, 0, .iptr=NULL, .defintval=16, TYPE_INT, 0}, \
|
||||
{GNB_CONFIG_STRING_BEAM_WEIGHTS_LIST, NULL, 0, .iptr=NULL, .defintarrayval=0, TYPE_INTARRAY, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -230,7 +228,6 @@ typedef enum {
|
||||
#define GNB_DISABLE_HARQ_IDX 32
|
||||
#define GNB_NUM_DL_HARQ_IDX 33
|
||||
#define GNB_NUM_UL_HARQ_IDX 34
|
||||
#define GNB_BEAMWEIGHTS_IDX 35
|
||||
|
||||
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
|
||||
#define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32}
|
||||
@@ -272,7 +269,6 @@ typedef enum {
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s1 = { config_check_intval, NUM_DL_HARQ_OKVALUES,8 } }, \
|
||||
{ .s1 = { config_check_intval, NUM_UL_HARQ_OKVALUES,2 } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -821,36 +821,32 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
uint8_t mu = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
config_frame_structure(mu, scc, cfg, &nrmac->frame_structure);
|
||||
|
||||
int nb_tx = config->nb_bfw[0]; // number of tx antennas
|
||||
int nb_beams = config->nb_bfw[1]; // number of beams
|
||||
// precoding matrix configuration (to be improved)
|
||||
cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts);
|
||||
// beamforming matrix configuration
|
||||
cfg->dbt_config.num_dig_beams = nb_beams;
|
||||
if (nb_beams > 0) {
|
||||
cfg->dbt_config.num_txrus = nb_tx;
|
||||
cfg->dbt_config.dig_beam_list = malloc16(nb_beams * sizeof(*cfg->dbt_config.dig_beam_list));
|
||||
AssertFatal(cfg->dbt_config.dig_beam_list, "out of memory\n");
|
||||
for (int i = 0; i < nb_beams; i++) {
|
||||
nfapi_nr_dig_beam_t *beam = &cfg->dbt_config.dig_beam_list[i];
|
||||
beam->beam_idx = i;
|
||||
beam->txru_list = malloc16(nb_tx * sizeof(*beam->txru_list));
|
||||
for (int j = 0; j < nb_tx; j++) {
|
||||
nfapi_nr_txru_t *txru = &beam->txru_list[j];
|
||||
txru->dig_beam_weight_Re = config->bw_list[j + i * nb_tx] & 0xffff;
|
||||
txru->dig_beam_weight_Im = (config->bw_list[j + i * nb_tx] >> 16) & 0xffff;
|
||||
LOG_D(NR_MAC, "Beam %d Tx %d Weight (%d, %d)\n", i, j, txru->dig_beam_weight_Re, txru->dig_beam_weight_Im);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nb_beams = config->nb_bfw[1]; // number of beams
|
||||
if (nrmac->beam_info.beam_allocation) {
|
||||
LOG_I(NR_MAC, "Configuring analog beamforming in config_request message\n");
|
||||
cfg->analog_beamforming_ve.num_beams_period_vendor_ext.tl.tag = NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.num_beams_period_vendor_ext.value = nrmac->beam_info.beams_per_period;
|
||||
cfg->num_tlv++;
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag = NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 1; // analog BF enabled
|
||||
cfg->num_tlv++;
|
||||
cfg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag = NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.total_num_beams_vendor_ext.value = nb_beams;
|
||||
cfg->num_tlv++;
|
||||
cfg->analog_beamforming_ve.analog_beam_list = malloc16(nb_beams * sizeof(*cfg->analog_beamforming_ve.analog_beam_list));
|
||||
for (int i = 0; i < nb_beams; i++) {
|
||||
cfg->analog_beamforming_ve.analog_beam_list[i].tl.tag = NFAPI_NR_FAPI_ANALOG_BEAM_VENDOR_EXTENSION_TAG;
|
||||
cfg->analog_beamforming_ve.analog_beam_list[i].value = config->bw_list[i];
|
||||
}
|
||||
} else {
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 0; // analog BF disabled
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag = NFAPI_NR_FAPI_ANALOG_BF_VENDOR_EXTENSION_TAG;
|
||||
cfg->num_tlv++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -365,10 +365,11 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
|
||||
NR_COMMON_channels_t *cc = gNB->common_channels;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
|
||||
NR_BWP_UplinkCommon_t *initialUplinkBWP = scc->uplinkConfigCommon->initialUplinkBWP;
|
||||
NR_RACH_ConfigCommon_t *rach_ConfigCommon = initialUplinkBWP->rach_ConfigCommon->choice.setup;
|
||||
NR_MsgA_ConfigCommon_r16_t *msgacc = NULL;
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16)
|
||||
msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup;
|
||||
if (initialUplinkBWP->ext1 && initialUplinkBWP->ext1->msgA_ConfigCommon_r16)
|
||||
msgacc = initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup;
|
||||
int mu = nr_get_prach_mu(msgacc, rach_ConfigCommon);
|
||||
int index = ul_buffer_index(frameP, slotP, mu, gNB->UL_tti_req_ahead_size);
|
||||
nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index];
|
||||
@@ -384,7 +385,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
int slot_index = 0;
|
||||
uint16_t prach_occasion_id = -1;
|
||||
|
||||
int bwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
int bwp_start = NRRIV2PRBOFFSET(initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
|
||||
// prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
|
||||
@@ -419,6 +420,16 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
UL_tti_req->rach_present = 1;
|
||||
NR_beam_alloc_t beam = {0};
|
||||
for (int fdm_index = 0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
|
||||
AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]),
|
||||
"Invalid UL_tti_req->n_pdus %d\n",
|
||||
UL_tti_req->n_pdus);
|
||||
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE;
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu;
|
||||
memset(prach_pdu, 0, sizeof(nfapi_nr_prach_pdu_t));
|
||||
UL_tti_req->n_pdus += 1;
|
||||
int num_td_occ = 0;
|
||||
for (int td_index = 0; td_index < N_t_slot; td_index++) {
|
||||
|
||||
prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) +
|
||||
@@ -427,6 +438,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
if (prach_occasion_id >= cc->total_prach_occasions) // to be confirmed: unused occasion?
|
||||
continue;
|
||||
|
||||
num_td_occ++;
|
||||
float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];
|
||||
int beam_index = 0;
|
||||
if(num_ssb_per_RO <= 1) {
|
||||
@@ -437,8 +449,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
// multi-beam allocation structure
|
||||
beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, beam_index, nr_slots_per_frame[mu]);
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to %d SSB transmitted in any available beam\n", n_ssb + 1);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
int first_ssb_index = (prach_occasion_id * (int)num_ssb_per_RO) % cc->num_active_ssb;
|
||||
for(int j = first_ssb_index; j < first_ssb_index + num_ssb_per_RO; j++) {
|
||||
// fapi beam index
|
||||
@@ -448,39 +459,17 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
AssertFatal(beam.idx >= 0, "Cannot allocate PRACH corresponding to SSB %d in any available beam\n", j);
|
||||
}
|
||||
}
|
||||
if(td_index == 0) {
|
||||
AssertFatal(UL_tti_req->n_pdus < sizeof(UL_tti_req->pdus_list) / sizeof(UL_tti_req->pdus_list[0]),
|
||||
"Invalid UL_tti_req->n_pdus %d\n", UL_tti_req->n_pdus);
|
||||
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE;
|
||||
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu;
|
||||
memset(prach_pdu,0,sizeof(nfapi_nr_prach_pdu_t));
|
||||
UL_tti_req->n_pdus+=1;
|
||||
if(num_td_occ == 1) {
|
||||
|
||||
// filling the prach fapi structure
|
||||
prach_pdu->phys_cell_id = *scc->physCellId;
|
||||
prach_pdu->num_prach_ocas = N_t_slot;
|
||||
|
||||
prach_pdu->prach_start_symbol = start_symbol;
|
||||
prach_pdu->num_ra = fdm_index;
|
||||
prach_pdu->num_cs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig,
|
||||
format0,
|
||||
rach_ConfigCommon->restrictedSetConfig);
|
||||
|
||||
prach_pdu->beamforming.num_prgs = 0;
|
||||
prach_pdu->beamforming.prg_size = 0;
|
||||
prach_pdu->beamforming.dig_bf_interface = 1;
|
||||
prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n",
|
||||
frameP,
|
||||
slotP,
|
||||
prach_occasion_id,
|
||||
prach_pdu->num_ra,
|
||||
prach_pdu->prach_start_symbol,
|
||||
slot_index,
|
||||
RA_sfn_index);
|
||||
// SCF PRACH PDU format field does not consider A1/B1 etc. possibilities
|
||||
// We added 9 = A1/B1 10 = A2/B2 11 A3/B3
|
||||
if (format1!=0xff) {
|
||||
@@ -537,8 +526,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
AssertFatal(1==0,"Invalid PRACH format");
|
||||
}
|
||||
}
|
||||
if (scc->uplinkConfigCommon->initialUplinkBWP->ext1
|
||||
&& scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) {
|
||||
if (initialUplinkBWP->ext1 && initialUplinkBWP->ext1->msgA_ConfigCommon_r16) {
|
||||
if (gNB->UE_info.list[0] == NULL)
|
||||
schedule_nr_MsgA_pusch(scc->uplinkConfigCommon,
|
||||
gNB,
|
||||
@@ -550,7 +538,24 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
*scc->physCellId);
|
||||
}
|
||||
}
|
||||
prach_pdu->num_prach_ocas = num_td_occ;
|
||||
prach_pdu->beamforming.num_prgs = 0;
|
||||
prach_pdu->beamforming.prg_size = 0;
|
||||
prach_pdu->beamforming.dig_bf_interface = num_td_occ;
|
||||
prach_pdu->beamforming.prgs_list[0].dig_bf_interface_list[num_td_occ - 1].beam_idx = beam_index;
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"Frame %d, Slot %d: Prach Occasion id = %u fdm index = %u start symbol = %u slot index = %u subframe index = %u \n",
|
||||
frameP,
|
||||
slotP,
|
||||
prach_occasion_id,
|
||||
prach_pdu->num_ra,
|
||||
prach_pdu->prach_start_symbol,
|
||||
slot_index,
|
||||
RA_sfn_index);
|
||||
}
|
||||
if (num_td_occ == 0) // no TD PRACH occasion -> no PRACH PDU
|
||||
UL_tti_req->n_pdus -= 1;
|
||||
}
|
||||
|
||||
// block resources in vrb_map_UL
|
||||
|
||||
Reference in New Issue
Block a user