mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-17 14:40:31 +00:00
Compare commits
23 Commits
mp_testing
...
oran_pbbf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6014f65602 | ||
|
|
5722b09095 | ||
|
|
1c3f7d41f8 | ||
|
|
08e8eecef8 | ||
|
|
5f81e85ff9 | ||
|
|
cd7e09ab9c | ||
|
|
7be2077ca5 | ||
|
|
fd7cee2c5c | ||
|
|
0425f4bb7b | ||
|
|
62c2885039 | ||
|
|
f3ea944d30 | ||
|
|
419c52e9fc | ||
|
|
366e706e47 | ||
|
|
84e91d831c | ||
|
|
788d1cbc1c | ||
|
|
867c01e896 | ||
|
|
af7baede1b | ||
|
|
247e3ccd4c | ||
|
|
5661e639f3 | ||
|
|
8c7bc93e9c | ||
|
|
407a049ac9 | ||
|
|
e564b0dc69 | ||
|
|
9d98aee083 |
@@ -175,10 +175,10 @@ MACRLCs = ({
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 200;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
set_analog_beamforming = 1;
|
||||
set_timedomain_beamforming = 1;
|
||||
beam_duration = 1;
|
||||
beams_per_period = 1;
|
||||
beam_weights = [0]; // single SSB -> one analog beam
|
||||
beam_weights = [0]; // single SSB -> one TD beam
|
||||
});
|
||||
|
||||
L1s = (
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -218,8 +218,8 @@ In the `MACRLCs` section of the gNB/DU configuration file:
|
||||
`ulsch_max_frame_inactivity`) or after scheduling request (SR)
|
||||
* `identity_precoding_matrix` (default 0=false): flag to enable to use only
|
||||
the identity precoding matrix in DL precoding
|
||||
* `set_analog_beamforming` (default 0=false): flag to enable analog
|
||||
beamforming (for more information [`analog_beamforming.md`](../analog_beamforming.md))
|
||||
* `set_timedomain_beamforming` (default 0=false): flag to enable time domain
|
||||
beamforming (for more information [`time_domain_beamforming.md`](../time_domain_beamforming.md))
|
||||
* `beam_duration` (default 1): duration/number of consecutive slots for a given set of
|
||||
beams, depending on hardware switching performance
|
||||
* `beams_per_period` (default 1): set of beams that can be simultaneously allocated in a
|
||||
|
||||
@@ -85,7 +85,7 @@ Legacy unmaintained files:
|
||||
- [L1 threads in NR-UE](./nr-ue-design.md)
|
||||
- [Information on gNB MAC](./MAC/mac-usage.md)
|
||||
- [Information on gNB RRC](./RRC/rrc-usage.md)
|
||||
- [Information on analog beamforming implementation](./analog_beamforming.md)
|
||||
- [Information on time domain beamforming implementation](./time_domain_beamforming.md)
|
||||
- [Information on the UE 5G NAS implementation](./5Gnas.md)
|
||||
|
||||
# Building and running from images
|
||||
|
||||
@@ -1,32 +1,36 @@
|
||||
This document explains the implementation of analog beamforming in OAI codebase.
|
||||
This document explains the implementation of time domain beamforming in OAI codebase.
|
||||
|
||||
[[_TOC_]]
|
||||
|
||||
# Introduction to analog beamforming
|
||||
# Introduction to time domain beamforming
|
||||
|
||||
Beamforming is a technique applied to antenna arrays to create a directional radiation pattern. This often consists in providing a different phase shift to each element of the array such that signals with a different angle of arrival/departure experience a change in radiation pattern because of constructive or destructive interference.
|
||||
|
||||
There are three main beamforming techinques: analog, digital and hybrid. The names refer to the phase shift application before or after the digital to analog conversion (or analog to digital in reception). When we speak about analog beamforming we generally refer to a techinique where the phase shifts that produce the beam stearing are applied by the radio unit (RU) choosing from a finite set of steering directions. The advantage of analog beamforming is a simplified analog circuitry and therefore reduced costs.
|
||||
|
||||
The presence of a limited number of predefined beams at RU poses constraints to the scheduler at gNB. As a matter of fact, the scheduler can serve only a limited number of beams, depending on the RU characteristics (possibly only 1), in a given time scale, that also depends on the RU characteristics (e.g. 1 slot or 1 symbol). This limitation doesn't exist for digital beamforming.
|
||||
For consistency with O-RAN specifications, we introduce the concept of time and frequency domain beamforming. While analog beamforming is necessarily time domain, digital can both be time and frequency domain (while normally it corresponds to frequency fomain beamforming).
|
||||
|
||||
Analog beamforming implementation also allows to enable distributed antenna systems (DAS), where each beam corrisponds to one antenna (or a set of antennas) of the system. In this scenario, the scheduler constaint is alleviated because normally the number of concurrent beams allowed equals the total number of beams.
|
||||
In time domain beamforming, the presence of a limited number of predefined beams at RU poses constraints to the scheduler at gNB. As a matter of fact, the scheduler can serve only a limited number of beams, depending on the RU characteristics (possibly only 1), in a given time scale, that also depends on the RU characteristics (e.g. 1 slot or 1 symbol). This limitation doesn't exist for frequency domain beamforming.
|
||||
|
||||
# Configuration file fields for analog beamforming
|
||||
Time domain beamforming implementation also allows to enable distributed antenna systems (DAS), where each beam corrisponds to one antenna (or a set of antennas) of the system. In this scenario, the scheduler constaint is alleviated because normally the number of concurrent beams allowed equals the total number of beams.
|
||||
|
||||
A set of parameters in configuration files controls the implementation of analog beamforming and instructs the scheduler on how to behave in such scenarios. Since most notably this technique in 5G is employed in FR2, the configuration file example currently available is a RFsim one for band 261. [Config file example](../ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf)
|
||||
# Configuration file fields for time domain beamforming
|
||||
|
||||
In the `MACRLC` section of configuration files, there are three new parameters: `set_analog_beamforming`, `beam_duration` and `beams_per_period`. The explanation of these parameters is here provided:
|
||||
- `set_analog_beamforming` can be set to 1 or 0 to activate or desactivate analog beamforming (default value is 0)
|
||||
A set of parameters in configuration files controls the implementation of time domain beamforming and instructs the scheduler on how to behave in such scenarios. Since most notably this technique in 5G is employed in FR2, the configuration file example currently available is a RFsim one for band 261. [Config file example](../ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf)
|
||||
|
||||
In the `MACRLC` section of configuration files, there are three new parameters: `set_timedomain_beamforming`, `beam_duration` and `beams_per_period`. The explanation of these parameters is here provided:
|
||||
- `set_timedomain_beamforming` can be set a value equal to 1 or 2 to activate or 0 to desactivate time domain 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)
|
||||
- `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
|
||||
|
||||
Setting time domain beamforming to 1 or 2 changes the way FAPI beam index is treated. By setting 1, we instruct L1 to look up in Hi-PHY preconfigured DBM beam index. By setting 2, we instruct L2 to directly signal to Lo-PHY the beam index (e.g. over 7.2x fronthaul).
|
||||
|
||||
DAS is enabled by setting to 1 the parameter `enable_das` in the L1 section of the configuration file. In case of DAS enabled, the field `beam_weights` in `MACRLC` section can be omitted.
|
||||
|
||||
# Implementation in OAI scheduler
|
||||
|
||||
A new MAC structure `NR_beam_info_t` controls the behavior of the scheduler in presence of analog beamforming. Besides the already mentioned parameters `beam_duration` and `beams_per_period`, the structure also holds a matrix `beam_allocation[i][j]`, whose indices `i` and `j` stands respectively for the number of beams in the period and the slot index (the size of the latter depends on the frame characteristics).
|
||||
A new MAC structure `NR_beam_info_t` controls the behavior of the scheduler in presence of time domain beamforming. Besides the already mentioned parameters `beam_duration` and `beams_per_period`, the structure also holds a matrix `beam_allocation[i][j]`, whose indices `i` and `j` stands respectively for the number of beams in the period and the slot index (the size of the latter depends on the frame characteristics).
|
||||
This matrix contains the beams already allocated in a given slot, to flag the scheduler to use one of these to schedule a UE in one of these beams. If the matrix is full (all the beams in the given period, e.g. slot) are already allocated, the scheduler can't allocate a UE in a new beam.
|
||||
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.
|
||||
|
||||
@@ -34,20 +38,20 @@ It is important to note that in current implementation, there are several period
|
||||
|
||||
# FAPI implementation
|
||||
|
||||
To be noted that in our implementation analog beamforming is only supported in non-split/monolithic mode because we don't support yet SCF P19 interface that would be needed to manage these procedure in a split scenario with SCF FAPI.
|
||||
To be noted that in our implementation time domain beamforming is only supported in non-split/monolithic mode because we don't support yet SCF P19 interface that would be needed to manage these procedure in a split scenario with SCF FAPI.
|
||||
|
||||
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
|
||||
In `config_request` structure, a vendor extension (`nfapi_nr_timedomain_beamforming_ve_t`) configures the lower layers at initialization with the following information:
|
||||
- `timedomain_bf_vendor_ext` which can assume values 1 or 0 for enabling or disabling time domain 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`
|
||||
- `timedomain_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 as part of the `precoding_and_beamforming` stucture. Therefore 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`.
|
||||
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 as part of the `precoding_and_beamforming` stucture. Therefore without a better option, we are currently using that one to store the internal time domain 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 beams, the buffers containing Tx and Rx data in frequency domain (`txdataF` and `rxdataF`) have been extended by one dimension to contain multiple concurrent beams 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.
|
||||
The function `beam_index_allocation`, called by every L1 channel, is responsible to match the FAPI time domain 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.
|
||||
|
||||
In case of DAS, since each beam corresponds to a specific antenna port, the `beam_index_allocation` function is simplified in the sense that the beam index corresponds to the antenna port index of the frequency domain buffers.
|
||||
|
||||
@@ -1155,53 +1155,53 @@ uint8_t pack_nr_config_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *e
|
||||
}
|
||||
#endif
|
||||
|
||||
AssertFatal(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext.tl.tag == 0, "BF Vendor extension shouldn't be set!");
|
||||
AssertFatal(pNfapiMsg->timedomain_beamforming_ve.num_beams_period_vendor_ext.tl.tag == 0, "BF 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_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG,
|
||||
&(pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext),
|
||||
&(pNfapiMsg->timedomain_beamforming_ve.num_beams_period_vendor_ext),
|
||||
ppWritePackedMsg,
|
||||
end,
|
||||
&pack_uint8_tlv_value);
|
||||
// only increase if it was set
|
||||
numTLVs += pNfapiMsg->analog_beamforming_ve.num_beams_period_vendor_ext.tl.tag == NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG;
|
||||
numTLVs += pNfapiMsg->timedomain_beamforming_ve.num_beams_period_vendor_ext.tl.tag == NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG;
|
||||
|
||||
AssertFatal(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext.tl.tag == 0, "BF Vendor extension shouldn't be set!");
|
||||
AssertFatal(pNfapiMsg->timedomain_beamforming_ve.timedomain_bf_vendor_ext.tl.tag == 0, "BF 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_BF_VENDOR_EXTENSION_TAG,
|
||||
&(pNfapiMsg->analog_beamforming_ve.analog_bf_vendor_ext),
|
||||
retval &= pack_nr_tlv(NFAPI_NR_FAPI_TD_BF_VENDOR_EXTENSION_TAG,
|
||||
&(pNfapiMsg->timedomain_beamforming_ve.timedomain_bf_vendor_ext),
|
||||
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_ANALOG_BF_VENDOR_EXTENSION_TAG;
|
||||
numTLVs += pNfapiMsg->timedomain_beamforming_ve.timedomain_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_TD_BF_VENDOR_EXTENSION_TAG;
|
||||
|
||||
AssertFatal(pNfapiMsg->analog_beamforming_ve.total_num_beams_vendor_ext.tl.tag == 0,
|
||||
AssertFatal(pNfapiMsg->timedomain_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),
|
||||
&(pNfapiMsg->timedomain_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;
|
||||
pNfapiMsg->timedomain_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!");
|
||||
for (int beam = 0; beam < pNfapiMsg->timedomain_beamforming_ve.total_num_beams_vendor_ext.value; beam++) {
|
||||
AssertFatal(pNfapiMsg->timedomain_beamforming_ve.timedomain_beam_list[beam].tl.tag == 0,
|
||||
"Time domain 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]),
|
||||
retval &= pack_nr_tlv(NFAPI_NR_FAPI_TD_BEAM_VENDOR_EXTENSION_TAG,
|
||||
&(pNfapiMsg->timedomain_beamforming_ve.timedomain_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;
|
||||
numTLVs += pNfapiMsg->timedomain_beamforming_ve.timedomain_bf_vendor_ext.tl.tag == NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
|
||||
}
|
||||
|
||||
pNfapiMsg->num_tlv = numTLVs;
|
||||
@@ -1325,10 +1325,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_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG, &(pNfapiMsg->timedomain_beamforming_ve.num_beams_period_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_TD_BF_VENDOR_EXTENSION_TAG, &(pNfapiMsg->timedomain_beamforming_ve.timedomain_bf_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG, &(pNfapiMsg->timedomain_beamforming_ve.total_num_beams_vendor_ext), &unpack_uint8_tlv_value},
|
||||
{NFAPI_NR_FAPI_TD_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_CONFIG_BEAMFORMING_TABLE_TAG, NULL, &unpack_dbt_table_tlv_value},
|
||||
{NFAPI_NR_CONFIG_PRECODING_TABLE_V6_TAG, NULL, &unpack_pm_table_tlv_value},
|
||||
@@ -1365,18 +1365,18 @@ 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));
|
||||
pNfapiMsg->timedomain_beamforming_ve.total_num_beams_vendor_ext.tl.tag = generic_tl.tag;
|
||||
pNfapiMsg->timedomain_beamforming_ve.total_num_beams_vendor_ext.tl.length = generic_tl.length;
|
||||
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->timedomain_beamforming_ve.total_num_beams_vendor_ext, ppReadPackedMsg, end);
|
||||
pNfapiMsg->timedomain_beamforming_ve.timedomain_beam_list = (nfapi_uint8_tlv_t *)malloc(
|
||||
pNfapiMsg->timedomain_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);
|
||||
case NFAPI_NR_FAPI_TD_BEAM_VENDOR_EXTENSION_TAG:
|
||||
unpack_fns[idx].tlv = &pNfapiMsg->timedomain_beamforming_ve.timedomain_beam_list[beam_ve_idx];
|
||||
pNfapiMsg->timedomain_beamforming_ve.timedomain_beam_list[beam_ve_idx].tl.tag = generic_tl.tag;
|
||||
pNfapiMsg->timedomain_beamforming_ve.timedomain_beam_list[beam_ve_idx].tl.length = generic_tl.length;
|
||||
result = (*unpack_fns[idx].unpack_func)(&pNfapiMsg->timedomain_beamforming_ve.timedomain_beam_list[beam_ve_idx], ppReadPackedMsg, end);
|
||||
beam_ve_idx ++;
|
||||
break;
|
||||
case NFAPI_NR_CONFIG_BEAMFORMING_TABLE_TAG:
|
||||
|
||||
@@ -311,14 +311,14 @@ bool eq_config_request(const nfapi_nr_config_request_scf_t *unpacked_req, const
|
||||
|
||||
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->timedomain_beamforming_ve.num_beams_period_vendor_ext, req->timedomain_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->timedomain_beamforming_ve.timedomain_bf_vendor_ext, req->timedomain_beamforming_ve.timedomain_bf_vendor_ext);
|
||||
|
||||
EQ_TLV(unpacked_req->analog_beamforming_ve.total_num_beams_vendor_ext, req->analog_beamforming_ve.total_num_beams_vendor_ext);
|
||||
EQ_TLV(unpacked_req->timedomain_beamforming_ve.total_num_beams_vendor_ext, req->timedomain_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]);
|
||||
for (int i = 0; i < unpacked_req->timedomain_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
EQ_TLV(unpacked_req->timedomain_beamforming_ve.timedomain_beam_list[i], req->timedomain_beamforming_ve.timedomain_beam_list[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -465,8 +465,8 @@ void free_config_request(nfapi_nr_config_request_scf_t *msg)
|
||||
|
||||
free(msg->pmi_list.pmi_pdu);
|
||||
|
||||
if (msg->analog_beamforming_ve.analog_beam_list) {
|
||||
free(msg->analog_beamforming_ve.analog_beam_list);
|
||||
if (msg->timedomain_beamforming_ve.timedomain_beam_list) {
|
||||
free(msg->timedomain_beamforming_ve.timedomain_beam_list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,17 +895,17 @@ void copy_config_request(const nfapi_nr_config_request_scf_t *src, nfapi_nr_conf
|
||||
|
||||
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->timedomain_beamforming_ve.num_beams_period_vendor_ext, src->timedomain_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->timedomain_beamforming_ve.timedomain_bf_vendor_ext, src->timedomain_beamforming_ve.timedomain_bf_vendor_ext);
|
||||
|
||||
COPY_TLV(dst->analog_beamforming_ve.total_num_beams_vendor_ext, src->analog_beamforming_ve.total_num_beams_vendor_ext);
|
||||
COPY_TLV(dst->timedomain_beamforming_ve.total_num_beams_vendor_ext, src->timedomain_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]);
|
||||
if (dst->timedomain_beamforming_ve.total_num_beams_vendor_ext.value > 0) {
|
||||
dst->timedomain_beamforming_ve.timedomain_beam_list = (nfapi_uint8_tlv_t *)malloc(
|
||||
dst->timedomain_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
|
||||
for (int i = 0; i < src->timedomain_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
COPY_TLV(dst->timedomain_beamforming_ve.timedomain_beam_list[i], src->timedomain_beamforming_ve.timedomain_beam_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1362,9 +1362,9 @@ void dump_config_request(const nfapi_nr_config_request_scf_t *msg)
|
||||
INDENTED_TLV_FORMAT_PRINT("UL_DCI Timing Offset", "%d", nfapi_config->ul_dci_timing_offset);
|
||||
INDENTED_TLV_FORMAT_PRINT("TX_DATA Timing Offset", "%d", nfapi_config->tx_data_timing_offset);
|
||||
/* Beamforming VE */
|
||||
const nfapi_nr_analog_beamforming_ve_t *analog_beamforming_ve = &msg->analog_beamforming_ve;
|
||||
INDENTED_TLV_FORMAT_PRINT("Num Beams per Period", "%d", analog_beamforming_ve->num_beams_period_vendor_ext);
|
||||
INDENTED_TLV_PRINT("Analog Beamforming VE", analog_beamforming_ve->analog_bf_vendor_ext);
|
||||
const nfapi_nr_timedomain_beamforming_ve_t *timedomain_beamforming_ve = &msg->timedomain_beamforming_ve;
|
||||
INDENTED_TLV_FORMAT_PRINT("Num Beams per Period", "%d", timedomain_beamforming_ve->num_beams_period_vendor_ext);
|
||||
INDENTED_TLV_PRINT("Time domain Beamforming VE", timedomain_beamforming_ve->timedomain_bf_vendor_ext);
|
||||
/* Vendor Extension */
|
||||
if (msg->vendor_extension) {
|
||||
const nfapi_tl_t *vendor_extension = (nfapi_tl_t *)&msg->vendor_extension;
|
||||
|
||||
@@ -708,7 +708,7 @@ static uint8_t pack_nr_rx_beamforming_pdu(const nfapi_nr_ul_beamforming_t *beamf
|
||||
uint8_t **ppWritePackedMsg,
|
||||
uint8_t *end)
|
||||
{ // Pack RX Beamforming PDU
|
||||
if (!(push8(beamforming_pdu->trp_scheme, ppWritePackedMsg, end) && push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end)
|
||||
if (!(push16(beamforming_pdu->num_prgs, ppWritePackedMsg, end)
|
||||
&& push16(beamforming_pdu->prg_size, ppWritePackedMsg, end)
|
||||
&& push8(beamforming_pdu->dig_bf_interface, ppWritePackedMsg, end))) {
|
||||
return 0;
|
||||
@@ -1033,7 +1033,7 @@ uint8_t pack_ul_tti_request(void *msg, uint8_t **ppWritePackedMsg, uint8_t *end,
|
||||
|
||||
static uint8_t unpack_nr_rx_beamforming_pdu(nfapi_nr_ul_beamforming_t *beamforming_pdu, uint8_t **ppReadPackedMsg, uint8_t *end)
|
||||
{ // Unpack RX Beamforming PDU
|
||||
if (!(pull8(ppReadPackedMsg, &beamforming_pdu->trp_scheme, end) && pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end)
|
||||
if (!(pull16(ppReadPackedMsg, &beamforming_pdu->num_prgs, end)
|
||||
&& pull16(ppReadPackedMsg, &beamforming_pdu->prg_size, end)
|
||||
&& pull8(ppReadPackedMsg, &beamforming_pdu->dig_bf_interface, end))) {
|
||||
return 0;
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
#define NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG 0x011F
|
||||
#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_TD_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
|
||||
#define NFAPI_NR_FAPI_TD_BEAM_VENDOR_EXTENSION_TAG 0xA003
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -507,10 +507,10 @@ 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 timedomain_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;
|
||||
nfapi_uint8_tlv_t *timedomain_beam_list;
|
||||
} nfapi_nr_timedomain_beamforming_ve_t;
|
||||
|
||||
// ERROR enums
|
||||
typedef enum { // Table 2-22
|
||||
@@ -625,7 +625,7 @@ typedef struct {
|
||||
nfapi_nr_nfapi_t nfapi_config;
|
||||
nfapi_nr_pm_list_t pmi_list;
|
||||
nfapi_nr_dbt_pdu_t dbt_config;
|
||||
nfapi_nr_analog_beamforming_ve_t analog_beamforming_ve;
|
||||
nfapi_nr_timedomain_beamforming_ve_t timedomain_beamforming_ve;
|
||||
} nfapi_nr_config_request_scf_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -743,31 +743,31 @@ typedef struct {
|
||||
|
||||
// 3.4.2
|
||||
|
||||
//for pdcch_pdu:
|
||||
typedef struct {
|
||||
// Index of the digital beam weight vector pre-stored at cell configuration.
|
||||
// The vector maps this input port to output TXRUs. Value: 0->65535
|
||||
uint16_t beam_idx;
|
||||
} nfapi_nr_dig_bf_interface_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t beam_idx;//Index of the digital beam weight vector pre-stored at cell configuration. The vector maps this input port to output TXRUs. Value: 0->65535
|
||||
|
||||
}nfapi_nr_dig_bf_interface_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t pm_idx;//Index to precoding matrix (PM) pre-stored at cell configuration. Note: If precoding is not used this parameter should be set to 0. Value: 0->65535.
|
||||
nfapi_nr_dig_bf_interface_t dig_bf_interface_list[NFAPI_MAX_NUM_BG_IF];//max dig_bf_interfaces
|
||||
|
||||
}nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t;
|
||||
typedef struct {
|
||||
// Index to precoding matrix (PM) pre-stored at cell configuration.
|
||||
// Note: If precoding is not used this parameter should be set to 0. Value: 0->65535.
|
||||
uint16_t pm_idx;
|
||||
nfapi_nr_dig_bf_interface_t dig_bf_interface_list[NFAPI_MAX_NUM_BG_IF]; // max dig_bf_interfaces
|
||||
} nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t;
|
||||
|
||||
//table 3-43
|
||||
typedef struct
|
||||
{
|
||||
uint16_t num_prgs;//Number of PRGs spanning this allocation. Value : 1->275
|
||||
uint16_t prg_size;//Size in RBs of a precoding resource block group (PRG) – to which same precoding and digital beamforming gets applied. Value: 1->275
|
||||
//watchout: dig_bf_interfaces here, in table 3-53 it's dig_bf_interface
|
||||
uint8_t dig_bf_interfaces;//Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255
|
||||
nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t prgs_list[NFAPI_MAX_NUM_PRGS];//max prg_size
|
||||
|
||||
}nfapi_nr_tx_precoding_and_beamforming_t;
|
||||
typedef struct {
|
||||
// Number of PRGs spanning this allocation. Value : 1->275
|
||||
uint16_t num_prgs;
|
||||
// Size in RBs of a precoding resource block group (PRG) to which same precoding and digital beamforming gets applied.
|
||||
// Value: 1->275
|
||||
uint16_t prg_size;
|
||||
// watchout: dig_bf_interfaces here, in table 3-53 it's dig_bf_interface
|
||||
uint8_t dig_bf_interfaces;
|
||||
// Number of STD ant ports (parallel streams) feeding into the digBF Value: 0->255
|
||||
nfapi_nr_tx_precoding_and_beamforming_number_of_prgs_t prgs_list[NFAPI_MAX_NUM_PRGS]; // max prg_size
|
||||
} nfapi_nr_tx_precoding_and_beamforming_t;
|
||||
|
||||
|
||||
//table 3-37
|
||||
|
||||
@@ -288,27 +288,27 @@ static void fill_config_request_tlv_tdd_rand(nfapi_nr_config_request_scf_t *nfap
|
||||
/*
|
||||
// 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_TD_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_TD_BEAM_VENDOR_EXTENSION_TAG
|
||||
FILL_TLV(nfapi_resp->timedomain_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());
|
||||
FILL_TLV(nfapi_resp->timedomain_beamforming_ve.timedomain_bf_vendor_ext, NFAPI_NR_FAPI_TD_BF_VENDOR_EXTENSION_TAG, rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
|
||||
FILL_TLV(nfapi_resp->analog_beamforming_ve.total_num_beams_vendor_ext,
|
||||
FILL_TLV(nfapi_resp->timedomain_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());
|
||||
if (nfapi_resp->timedomain_beamforming_ve.total_num_beams_vendor_ext.value > 0) {
|
||||
nfapi_resp->timedomain_beamforming_ve.timedomain_beam_list =
|
||||
(nfapi_uint8_tlv_t *)malloc(nfapi_resp->timedomain_beamforming_ve.total_num_beams_vendor_ext.value * sizeof(nfapi_uint8_tlv_t));
|
||||
for (int i = 0; i < nfapi_resp->timedomain_beamforming_ve.total_num_beams_vendor_ext.value; ++i) {
|
||||
FILL_TLV(nfapi_resp->timedomain_beamforming_ve.timedomain_beam_list[i], NFAPI_NR_FAPI_TD_BEAM_VENDOR_EXTENSION_TAG, rand8());
|
||||
nfapi_resp->num_tlv++;
|
||||
}
|
||||
}*/
|
||||
@@ -502,7 +502,7 @@ static void fill_config_request_tlv_fdd(nfapi_nr_config_request_scf_t *req)
|
||||
|
||||
/* Digital beamforming NULL */
|
||||
|
||||
/* Analog beamforming NULL */
|
||||
/* Time domain beamforming NULL */
|
||||
|
||||
//DevAssert(req->num_tlv == 103);
|
||||
}
|
||||
|
||||
@@ -107,10 +107,10 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
NR_gNB_COMMON *const common_vars = &gNB->common_vars;
|
||||
NR_gNB_PRACH *const prach_vars = &gNB->prach_vars;
|
||||
|
||||
common_vars->analog_bf = cfg->analog_beamforming_ve.analog_bf_vendor_ext.value;
|
||||
LOG_I(PHY, "L1 configured with%s analog beamforming\n", common_vars->analog_bf ? "" : "out");
|
||||
if (common_vars->analog_bf) {
|
||||
common_vars->num_beams_period = cfg->analog_beamforming_ve.num_beams_period_vendor_ext.value;
|
||||
common_vars->timedomain_bf = cfg->timedomain_beamforming_ve.timedomain_bf_vendor_ext.value;
|
||||
LOG_I(PHY, "L1 configured with%s time domain beamforming\n", common_vars->timedomain_bf ? "" : "out");
|
||||
if (common_vars->timedomain_bf) {
|
||||
common_vars->num_beams_period = cfg->timedomain_beamforming_ve.num_beams_period_vendor_ext.value;
|
||||
LOG_I(PHY, "Max number of concurrent beams: %d\n", common_vars->num_beams_period);
|
||||
} else
|
||||
common_vars->num_beams_period = 1;
|
||||
@@ -173,10 +173,12 @@ 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*));
|
||||
|
||||
if (cfg->analog_beamforming_ve.analog_bf_vendor_ext.value) {
|
||||
if (cfg->timedomain_beamforming_ve.timedomain_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));
|
||||
for (int i = 0; i < common_vars->num_beams_period; i++) {
|
||||
common_vars->beam_id[i] = (int*)malloc16(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int));
|
||||
memset(common_vars->beam_id[i], -1, fp->symbols_per_slot * fp->slots_per_frame * sizeof(int));
|
||||
}
|
||||
}
|
||||
common_vars->txdataF = (c16_t ***)malloc16(common_vars->num_beams_period * sizeof(c16_t**));
|
||||
for (int i = 0; i < common_vars->num_beams_period; i++) {
|
||||
|
||||
@@ -47,14 +47,16 @@ void 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);
|
||||
|
||||
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;
|
||||
nfapi_nr_timedomain_beamforming_ve_t *timedomain_config = &cfg->timedomain_beamforming_ve;
|
||||
ru->num_beams_period = timedomain_config->timedomain_bf_vendor_ext.value ? timedomain_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;
|
||||
LOG_I(NR_PHY, "nb_tx_streams %d, nb_rx_streams %d, num_Beams_period %d\n", nb_tx_streams, nb_rx_streams, 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));
|
||||
for(int i = 0; i < ru->num_beams_period; i++) {
|
||||
ru->common.beam_id[i] = malloc16(fp->symbols_per_slot * fp->slots_per_frame * sizeof(int));
|
||||
memset(ru->common.beam_id[i], -1, 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
|
||||
|
||||
@@ -81,9 +81,9 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
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,
|
||||
int beam_nb = beam_index_allocation(gNB->enable_timedomain_das,
|
||||
dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->gNB_config.timedomain_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
|
||||
@@ -680,9 +680,9 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
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,
|
||||
int beam_nb = beam_index_allocation(gNB->enable_timedomain_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->gNB_config.timedomain_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
frame_parms->symbols_per_slot,
|
||||
|
||||
@@ -85,9 +85,9 @@ int nr_fill_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *pr
|
||||
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,
|
||||
prach->beam_nb[i] = beam_index_allocation(gNB->enable_timedomain_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->gNB_config.timedomain_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
Slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
|
||||
@@ -76,9 +76,9 @@ 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(gNB->enable_analog_das,
|
||||
ulsch->beam_nb = beam_index_allocation(gNB->enable_timedomain_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->gNB_config.timedomain_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
|
||||
@@ -70,9 +70,9 @@ void nr_fill_pucch(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_pucch_pdu_t
|
||||
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,
|
||||
pucch->beam_nb = beam_index_allocation(gNB->enable_timedomain_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->gNB_config.timedomain_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
|
||||
@@ -59,9 +59,9 @@ 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(gNB->enable_analog_das,
|
||||
srs->beam_nb = beam_index_allocation(gNB->enable_timedomain_das,
|
||||
fapi_beam_idx,
|
||||
&gNB->gNB_config.analog_beamforming_ve,
|
||||
&gNB->gNB_config.timedomain_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
|
||||
@@ -491,7 +491,7 @@ typedef struct RU_t_s {
|
||||
int nb_rx;
|
||||
/// number of TX paths on device
|
||||
int nb_tx;
|
||||
/// number of concurrent analog beams in period
|
||||
/// number of concurrent time domain beams in period
|
||||
int num_beams_period;
|
||||
/// number of logical antennas at TX beamformer input
|
||||
int nb_log_antennas;
|
||||
|
||||
@@ -288,7 +288,7 @@ typedef struct {
|
||||
/// - second index: beam_id [0.. symbols_per_frame[
|
||||
int **beam_id;
|
||||
int num_beams_period;
|
||||
bool analog_bf;
|
||||
bool timedomain_bf;
|
||||
int32_t *debugBuff;
|
||||
int32_t debugBuff_sample_offset;
|
||||
} NR_gNB_COMMON;
|
||||
@@ -492,7 +492,7 @@ typedef struct PHY_VARS_gNB_s {
|
||||
int num_ulprbbl;
|
||||
uint16_t ulprbbl [MAX_BWP_SIZE];
|
||||
|
||||
bool enable_analog_das;
|
||||
bool enable_timedomain_das;
|
||||
|
||||
time_stats_t phy_proc_tx;
|
||||
time_stats_t phy_proc_rx;
|
||||
|
||||
@@ -185,10 +185,7 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx)
|
||||
int txdataF_offset = slot_tx * fp->samples_per_slot_wCP;
|
||||
start_meas(&ru->precoding_stats);
|
||||
|
||||
if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT)
|
||||
return;
|
||||
|
||||
if (gNB->common_vars.analog_bf) {
|
||||
if (gNB->common_vars.timedomain_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],
|
||||
@@ -196,8 +193,11 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx)
|
||||
}
|
||||
}
|
||||
|
||||
if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT)
|
||||
return;
|
||||
|
||||
// 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) {
|
||||
if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.timedomain_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;
|
||||
@@ -234,14 +234,14 @@ void nr_feptx(void *arg)
|
||||
if (tx_idx == 0)
|
||||
start_meas(&ru->precoding_stats);
|
||||
|
||||
if (ru->gNB_list[0]->common_vars.analog_bf) {
|
||||
if (ru->gNB_list[0]->common_vars.timedomain_bf) {
|
||||
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)
|
||||
if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.timedomain_bf)
|
||||
memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset],
|
||||
(void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset],
|
||||
numSamples * sizeof(int32_t));
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
int beam_index_allocation(bool das,
|
||||
int fapi_beam_index,
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_bf,
|
||||
nfapi_nr_timedomain_beamforming_ve_t *timedomain_bf,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
@@ -60,10 +60,10 @@ int beam_index_allocation(bool das,
|
||||
if (das)
|
||||
return fapi_beam_index;
|
||||
|
||||
int ru_beam_idx = analog_bf->analog_beam_list[fapi_beam_index].value;
|
||||
int ru_beam_idx = timedomain_bf->timedomain_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
|
||||
// L2 timedomain 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)
|
||||
@@ -141,9 +141,9 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n
|
||||
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,
|
||||
int beam_nb = beam_index_allocation(gNB->enable_timedomain_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&cfg->timedomain_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
@@ -284,9 +284,9 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
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,
|
||||
int beam_nb = beam_index_allocation(gNB->enable_timedomain_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&cfg->timedomain_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
|
||||
@@ -49,7 +49,7 @@ void nr_phy_free_RU(RU_t *ru);
|
||||
void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot);
|
||||
int beam_index_allocation(bool das,
|
||||
int fapi_beam_index,
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_bf,
|
||||
nfapi_nr_timedomain_beamforming_ve_t *timedomain_bf,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
#define HLP_L1_PHASE_COMP "Apply NR symbolwise phase rotation"
|
||||
#define CONFIG_STRING_NUM_ANTENNAS_PER_THREAD "dmrs_num_antennas_per_thread"
|
||||
#define HLP_NUM_ARX "Number of antennas per thread for PUSCH channel estimation"
|
||||
#define CONFIG_STRING_ANALOG_DAS "enable_das"
|
||||
#define CONFIG_STRING_TD_DAS "enable_das"
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* L1 configuration parameters */
|
||||
@@ -89,7 +89,7 @@
|
||||
{CONFIG_STRING_L1_TX_AMP_BACKOFF_dB, HLP_L1TX_BO,0, .uptr=NULL, .defintval=36, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_L1_PHASE_COMP, HLP_L1_PHASE_COMP,PARAMFLAG_BOOL, .uptr=NULL,.defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_NUM_ANTENNAS_PER_THREAD, HLP_NUM_ARX,0, .uptr=NULL, .defintval=1, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_ANALOG_DAS, NULL, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
|
||||
{CONFIG_STRING_TD_DAS, NULL, 0, .uptr=NULL, .defintval=0, TYPE_UINT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
#define L1_CC_IDX 0
|
||||
@@ -112,7 +112,7 @@
|
||||
#define L1_TX_AMP_BACKOFF_dB 17
|
||||
#define L1_PHASE_COMP 18
|
||||
#define NUM_ANTENNAS_PER_THREAD 19
|
||||
#define L1_ANALOG_DAS 20
|
||||
#define L1_TD_DAS 20
|
||||
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
#define CONFIG_STRING_MACRLC_UL_HARQ_ROUND_MAX "ul_harq_round_max"
|
||||
#define CONFIG_STRING_MACRLC_MIN_GRANT_PRB "min_grant_prb"
|
||||
#define CONFIG_STRING_MACRLC_IDENTITY_PM "identity_precoding_matrix"
|
||||
#define CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING "set_analog_beamforming"
|
||||
#define CONFIG_STRING_MACRLC_TD_BEAMFORMING "set_timedomain_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"
|
||||
@@ -93,7 +93,7 @@
|
||||
#define HLP_MACRLC_UL_HARQ_MAX "Maximum number of UL HARQ rounds"
|
||||
#define HLP_MACRLC_MIN_GRANT_PRB "Minimal Periodic ULSCH Grant PRBs"
|
||||
#define HLP_MACRLC_IDENTITY_PM "Flag to use only identity matrix in DL precoding"
|
||||
#define HLP_MACRLC_AB "Flag to enable analog beamforming"
|
||||
#define HLP_MACRLC_AB "Flag to enable time domain beamforming"
|
||||
#define HLP_MACRLC_BEAM_DURATION "number of consecutive slots for a given set of beams"
|
||||
#define HLP_MACRLC_BEAMS_PERIOD "set of beams that can be simultaneously allocated in a period"
|
||||
#define HLP_MACRLC_PUSCH_RSSI_THRESHOLD "Limits PUSCH TPC commands based on RSSI to prevent ADC railing. Value range [-1280, 0], unit 0.1 dBm/dBFS"
|
||||
@@ -141,7 +141,7 @@
|
||||
{CONFIG_STRING_MACRLC_LOCAL_N_ADDRESS_F1U, NULL, 0, .strptr=NULL, .defstrval=NULL, TYPE_STRING, 0}, \
|
||||
{CONFIG_STRING_MACRLC_TRANSPORT_S_SHM_PREFIX, NULL, 0, .strptr=NULL, .defstrval="nvipc", TYPE_STRING, 0}, \
|
||||
{CONFIG_STRING_MACRLC_TRANSPORT_S_POLL_CORE, NULL, 0, .i8ptr=NULL, .defintval=-1, TYPE_INT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_ANALOG_BEAMFORMING, HLP_MACRLC_AB, PARAMFLAG_BOOL, .u8ptr=NULL, .defintval=0, TYPE_UINT8, 0}, \
|
||||
{CONFIG_STRING_MACRLC_TD_BEAMFORMING, HLP_MACRLC_AB, 0, .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}, \
|
||||
@@ -188,9 +188,9 @@
|
||||
#define MACRLC_LOCAL_N_ADDRESS_F1U_IDX 33
|
||||
#define MACRLC_TRANSPORT_S_SHM_PREFIX 34
|
||||
#define MACRLC_TRANSPORT_S_POLL_CORE 35
|
||||
#define MACRLC_ANALOG_BEAMFORMING_IDX 36
|
||||
#define MACRLC_ANALOG_BEAM_DURATION_IDX 37
|
||||
#define MACRLC_ANALOG_BEAMS_PERIOD_IDX 38
|
||||
#define MACRLC_TD_BEAMFORMING_IDX 36
|
||||
#define MACRLC_TD_BEAM_DURATION_IDX 37
|
||||
#define MACRLC_TD_BEAMS_PERIOD_IDX 38
|
||||
#define MACRLC_BEAMWEIGHTS_IDX 39
|
||||
#define MACRLC_PUSCH_RSSI_THRES_IDX 40
|
||||
#define MACRLC_PUCCH_RSSI_THRES_IDX 41
|
||||
|
||||
@@ -1116,7 +1116,7 @@ void RCconfig_NR_L1(void)
|
||||
gNB->TX_AMP = min(32767.0 / pow(10.0, .05 * (double)(*L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr)), INT16_MAX);
|
||||
gNB->phase_comp = *L1_ParamList.paramarray[j][L1_PHASE_COMP].uptr;
|
||||
gNB->dmrs_num_antennas_per_thread = *(L1_ParamList.paramarray[j][NUM_ANTENNAS_PER_THREAD].uptr);
|
||||
gNB->enable_analog_das = *(L1_ParamList.paramarray[j][L1_ANALOG_DAS].uptr);
|
||||
gNB->enable_timedomain_das = *(L1_ParamList.paramarray[j][L1_TD_DAS].uptr);
|
||||
LOG_I(NR_PHY, "TX_AMP = %d (-%d dBFS)\n", gNB->TX_AMP, *L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr);
|
||||
AssertFatal(gNB->TX_AMP > 300, "TX_AMP is too small, must be larger than 300 (is %d)\n", gNB->TX_AMP);
|
||||
// Midhaul configuration
|
||||
@@ -1786,29 +1786,32 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
|
||||
LOG_I(NR_PHY, "Copying %d blacklisted PRB to L1 context\n", num_ulprbbl);
|
||||
memcpy(RC.nrmac[j]->ulprbbl, prbbl, MAX_BWP_SIZE * sizeof(prbbl[0]));
|
||||
}
|
||||
bool ab = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMFORMING_IDX].u8ptr;
|
||||
if (ab) {
|
||||
AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Analog beamforming only supported for monolithic scenario\n");
|
||||
int tdbf = *MacRLC_ParamList.paramarray[j][MACRLC_TD_BEAMFORMING_IDX].u8ptr;
|
||||
if (tdbf > 0) {
|
||||
if (tdbf == 1)
|
||||
AssertFatal(NFAPI_MODE == NFAPI_MONOLITHIC, "Time domain beamforming only supported for monolithic scenario\n");
|
||||
NR_beam_info_t *beam_info = &RC.nrmac[j]->beam_info;
|
||||
int beams_per_period = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAMS_PERIOD_IDX].u8ptr;
|
||||
int beams_per_period = *MacRLC_ParamList.paramarray[j][MACRLC_TD_BEAMS_PERIOD_IDX].u8ptr;
|
||||
beam_info->beam_allocation = malloc16(beams_per_period * sizeof(int *));
|
||||
beam_info->beam_duration = *MacRLC_ParamList.paramarray[j][MACRLC_ANALOG_BEAM_DURATION_IDX].u8ptr;
|
||||
beam_info->beam_duration = *MacRLC_ParamList.paramarray[j][MACRLC_TD_BEAM_DURATION_IDX].u8ptr;
|
||||
beam_info->beams_per_period = beams_per_period;
|
||||
beam_info->beam_allocation_size = -1; // to be initialized once we have information on frame configuration
|
||||
}
|
||||
beam_info->beam_mode = tdbf == 1 ? PRECONFIGURED_BEAM_IDX : LOPHY_BEAM_IDX;
|
||||
} else
|
||||
RC.nrmac[j]->beam_info.beam_mode = NO_BEAM_MODE;
|
||||
if (config_isparamset(MacRLC_ParamList.paramarray[j], MACRLC_BEAMWEIGHTS_IDX)) {
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
GET_PARAMS_LIST(L1_ParamList, L1_Params, L1PARAMS_DESC, CONFIG_STRING_L1_LIST, NULL);
|
||||
AssertFatal(*(L1_ParamList.paramarray[j][L1_ANALOG_DAS].uptr) == 0, "No need to set beam weights in case of DAS\n");
|
||||
AssertFatal(*(L1_ParamList.paramarray[j][L1_TD_DAS].uptr) == 0, "No need to set beam weights in case of DAS\n");
|
||||
}
|
||||
int n = MacRLC_ParamList.paramarray[j][MACRLC_BEAMWEIGHTS_IDX].numelt;
|
||||
int num_beam = n;
|
||||
if (!ab) {
|
||||
if (!tdbf) {
|
||||
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
|
||||
// in case of time domain 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
|
||||
|
||||
@@ -393,9 +393,7 @@ int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed)
|
||||
return ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_period;
|
||||
}
|
||||
|
||||
static void config_common(gNB_MAC_INST *nrmac,
|
||||
const nr_mac_config_t *config,
|
||||
NR_ServingCellConfigCommon_t *scc)
|
||||
static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR_ServingCellConfigCommon_t *scc)
|
||||
{
|
||||
nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0];
|
||||
nrmac->common_channels[0].ServingCellConfigCommon = scc;
|
||||
@@ -713,26 +711,26 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
cfg->pmi_list = init_DL_MIMO_codebook(nrmac, pdsch_AntennaPorts);
|
||||
|
||||
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;
|
||||
if (nrmac->beam_info.beam_mode == PRECONFIGURED_BEAM_IDX) {
|
||||
LOG_I(NR_MAC, "Configuring time domain beamforming in config_request message\n");
|
||||
cfg->timedomain_beamforming_ve.num_beams_period_vendor_ext.tl.tag = NFAPI_NR_FAPI_NUM_BEAMS_PERIOD_VENDOR_EXTENSION_TAG;
|
||||
cfg->timedomain_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->timedomain_beamforming_ve.timedomain_bf_vendor_ext.tl.tag = NFAPI_NR_FAPI_TD_BF_VENDOR_EXTENSION_TAG;
|
||||
cfg->timedomain_beamforming_ve.timedomain_bf_vendor_ext.value = 1; // time domain 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->timedomain_beamforming_ve.total_num_beams_vendor_ext.tl.tag = NFAPI_NR_FAPI_TOTAL_NUM_BEAMS_VENDOR_EXTENSION_TAG;
|
||||
cfg->timedomain_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));
|
||||
cfg->timedomain_beamforming_ve.timedomain_beam_list = malloc16(nb_beams * sizeof(*cfg->timedomain_beamforming_ve.timedomain_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];
|
||||
cfg->timedomain_beamforming_ve.timedomain_beam_list[i].tl.tag = NFAPI_NR_FAPI_TD_BEAM_VENDOR_EXTENSION_TAG;
|
||||
cfg->timedomain_beamforming_ve.timedomain_beam_list[i].value = config->bw_list[i];
|
||||
}
|
||||
} else {
|
||||
cfg->analog_beamforming_ve.analog_bf_vendor_ext.value = 0; // analog BF disabled
|
||||
cfg->timedomain_beamforming_ve.timedomain_bf_vendor_ext.value = 0; // time domain 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->timedomain_beamforming_ve.timedomain_bf_vendor_ext.tl.tag = NFAPI_NR_FAPI_TD_BF_VENDOR_EXTENSION_TAG;
|
||||
cfg->num_tlv++;
|
||||
}
|
||||
}
|
||||
@@ -740,7 +738,7 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
|
||||
static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int slots_per_frame)
|
||||
{
|
||||
if (!beam_info->beam_allocation)
|
||||
if (beam_info->beam_mode == NO_BEAM_MODE)
|
||||
return;
|
||||
|
||||
int size = mu == 0 ? slots_per_frame << 1 : slots_per_frame;
|
||||
@@ -817,7 +815,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
nrmac->vrb_map_UL_size = size;
|
||||
|
||||
int num_beams = 1;
|
||||
if(nrmac->beam_info.beam_allocation)
|
||||
if(nrmac->beam_info.beam_mode != NO_BEAM_MODE)
|
||||
num_beams = nrmac->beam_info.beams_per_period;
|
||||
for (int i = 0; i < num_beams; i++) {
|
||||
nrmac->common_channels[0].vrb_map_UL[i] = calloc(size * MAX_BWP_SIZE, sizeof(uint16_t));
|
||||
@@ -834,7 +832,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
LOG_D(NR_MAC, "Configuring common parameters from NR ServingCellConfig\n");
|
||||
|
||||
config_common(nrmac, config, scc);
|
||||
fapi_beam_index_allocation(scc, nrmac);
|
||||
fapi_beam_index_allocation(scc, config, nrmac);
|
||||
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
// nothing to be sent in the other cases
|
||||
|
||||
@@ -108,7 +108,7 @@ static void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slo
|
||||
{
|
||||
// for now we use the same logic of UL_tti_req_ahead
|
||||
// reset after 1 frame with the exception of 15kHz
|
||||
if(!beam_info->beam_allocation)
|
||||
if (beam_info->beam_mode == NO_BEAM_MODE)
|
||||
return;
|
||||
// initialization done only once
|
||||
AssertFatal(beam_info->beam_allocation_size >= 0, "Beam information not initialized\n");
|
||||
@@ -179,7 +179,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo
|
||||
|
||||
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
||||
int num_beams = 1;
|
||||
if(gNB->beam_info.beam_allocation)
|
||||
if(gNB->beam_info.beam_mode != NO_BEAM_MODE)
|
||||
num_beams = gNB->beam_info.beams_per_period;
|
||||
// clear vrb_maps
|
||||
for (int i = 0; i < num_beams; i++)
|
||||
|
||||
@@ -368,6 +368,9 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
// prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
|
||||
uint16_t RA_sfn_index = -1;
|
||||
frequency_range_t freq_range = get_freq_range_from_arfcn(scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
|
||||
// block resources in vrb_map_UL
|
||||
const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
|
||||
if (get_nr_prach_sched_from_info(cc->prach_info, config_index, frameP, slotP, mu, freq_range, &RA_sfn_index, cc->frame_type)) {
|
||||
uint16_t format0 = cc->prach_info.format & 0xff; // first column of format from table
|
||||
uint16_t format1 = (cc->prach_info.format >> 8) & 0xff; // second column of format from table
|
||||
@@ -505,8 +508,8 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
}
|
||||
}
|
||||
prach_pdu->num_prach_ocas = num_td_occ;
|
||||
prach_pdu->beamforming.num_prgs = 0;
|
||||
prach_pdu->beamforming.prg_size = 0;
|
||||
prach_pdu->beamforming.num_prgs = 1;
|
||||
prach_pdu->beamforming.prg_size = n_ra_rb;
|
||||
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;
|
||||
|
||||
@@ -526,9 +529,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP)
|
||||
gNB->num_scheduled_prach_rx += num_td_occ;
|
||||
}
|
||||
|
||||
// block resources in vrb_map_UL
|
||||
const int mu_pusch = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
const int16_t n_ra_rb = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
|
||||
|
||||
// mark PRBs as occupied for current and future slots if prach extends beyond current slot
|
||||
int total_prach_slots;
|
||||
uint32_t N_dur = cc->prach_info.N_dur;
|
||||
|
||||
@@ -79,7 +79,7 @@ static void schedule_ssb(frame_t frame,
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = payload;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.num_prgs = 1;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size = 275; //1 PRG of max size for analogue beamforming
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prg_size = 20; //SSB is always 20RBs
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.dig_bf_interfaces = 1;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].pm_idx = 0;
|
||||
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
|
||||
|
||||
@@ -993,10 +993,10 @@ nfapi_nr_dl_tti_pdsch_pdu_rel15_t *prepare_pdsch_pdu(nfapi_nr_dl_tti_request_pdu
|
||||
pdsch_pdu->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(pdsch_pdu->mcsTable[0], dl_bw_tbslbrm, nl_tbslbrm);
|
||||
pdsch_pdu->maintenance_parms_v3.ldpcBaseGraph = get_BG(sched_pdsch->tb_size << 3, sched_pdsch->R);
|
||||
// Precoding and beamforming
|
||||
pdsch_pdu->precodingAndBeamforming.num_prgs = 0;
|
||||
pdsch_pdu->precodingAndBeamforming.num_prgs = 1;
|
||||
pdsch_pdu->precodingAndBeamforming.prg_size = pdsch_pdu->rbSize;
|
||||
pdsch_pdu->precodingAndBeamforming.dig_bf_interfaces = 0;
|
||||
pdsch_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = sched_pdsch->pm_index;
|
||||
pdsch_pdu->precodingAndBeamforming.dig_bf_interfaces = 1;
|
||||
pdsch_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = sched_pdsch->pm_index;
|
||||
pdsch_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
|
||||
return pdsch_pdu;
|
||||
}
|
||||
|
||||
@@ -496,21 +496,7 @@ NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac,
|
||||
pdcch.ShiftIndex = 0;
|
||||
}
|
||||
|
||||
uint16_t N_rb = 0; // nb of rbs of coreset per symbol
|
||||
uint16_t rb_start = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int t = 0; t < 8; t++) {
|
||||
if (coreset->frequencyDomainResources.buf[i] >> (7 - t) & 1) {
|
||||
if (N_rb == 0) {
|
||||
rb_start = 48 * i + t * 6;
|
||||
}
|
||||
N_rb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdcch.rb_start = rb_start;
|
||||
pdcch.n_rb = N_rb *= 6; // each bit of frequencyDomainResources represents 6 PRBs
|
||||
get_coreset_rb_params(coreset, &pdcch.n_rb, &pdcch.rb_start);
|
||||
|
||||
return pdcch;
|
||||
}
|
||||
@@ -822,10 +808,15 @@ nfapi_nr_dl_dci_pdu_t *prepare_dci_pdu(nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_
|
||||
dci_pdu->ScramblingId = *scc->physCellId;
|
||||
dci_pdu->ScramblingRNTI = 0;
|
||||
}
|
||||
|
||||
uint16_t N_rb = 0;
|
||||
uint16_t rb_start = 0;
|
||||
get_coreset_rb_params(coreset, &N_rb, &rb_start);
|
||||
|
||||
dci_pdu->beta_PDCCH_1_0 = 0;
|
||||
dci_pdu->powerControlOffsetSS = 1;
|
||||
dci_pdu->precodingAndBeamforming.num_prgs = 0;
|
||||
dci_pdu->precodingAndBeamforming.prg_size = 0;
|
||||
dci_pdu->precodingAndBeamforming.num_prgs = 1;
|
||||
dci_pdu->precodingAndBeamforming.prg_size = N_rb;
|
||||
dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1;
|
||||
dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0;
|
||||
dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index;
|
||||
@@ -1249,9 +1240,9 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t *pucch_pdu,
|
||||
pucch_pdu->prb_size=1;
|
||||
}
|
||||
// Beamforming
|
||||
pucch_pdu->beamforming.num_prgs = 0;
|
||||
pucch_pdu->beamforming.prg_size = 0; // pucch_pdu->prb_size;
|
||||
pucch_pdu->beamforming.dig_bf_interface = 0;
|
||||
pucch_pdu->beamforming.num_prgs = 1;
|
||||
pucch_pdu->beamforming.prg_size = pucch_pdu->prb_size;
|
||||
pucch_pdu->beamforming.dig_bf_interface = 1;
|
||||
pucch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index;
|
||||
}
|
||||
|
||||
@@ -3346,8 +3337,10 @@ int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx)
|
||||
|
||||
// TODO this is a placeholder for a possibly more complex function
|
||||
// for now the fapi beam index is the number of SSBs transmitted before ssb_index i
|
||||
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac)
|
||||
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *config, gNB_MAC_INST *mac)
|
||||
{
|
||||
if (mac->beam_info.beam_mode == NO_BEAM_MODE)
|
||||
return;
|
||||
int len = 0;
|
||||
uint8_t* buf = NULL;
|
||||
switch (scc->ssb_PositionsInBurst->present) {
|
||||
@@ -3366,11 +3359,13 @@ void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST
|
||||
default :
|
||||
AssertFatal(false, "Invalid configuration\n");
|
||||
}
|
||||
int fapi_index = 0;
|
||||
int index = 0;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if ((buf[i / 8] >> (7 - i % 8)) & 0x1)
|
||||
mac->fapi_beam_index[i] = fapi_index++;
|
||||
else
|
||||
if ((buf[i / 8] >> (7 - i % 8)) & 0x1) {
|
||||
int fapi_index = mac->beam_info.beam_mode == LOPHY_BEAM_IDX ? config->bw_list[index] : index;
|
||||
mac->fapi_beam_index[i] = fapi_index;
|
||||
index++;
|
||||
} else
|
||||
mac->fapi_beam_index[i] = -1;
|
||||
}
|
||||
}
|
||||
@@ -3382,8 +3377,8 @@ static inline int get_beam_index(const NR_beam_info_t *beam_info, int frame, int
|
||||
|
||||
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame)
|
||||
{
|
||||
// if no beam allocation for analog beamforming we always return beam index 0 (no multiple beams)
|
||||
if (!beam_info->beam_allocation)
|
||||
// if no beam allocation for time domain beamforming we always return beam index 0 (no multiple beams)
|
||||
if (beam_info->beam_mode == NO_BEAM_MODE)
|
||||
return (NR_beam_alloc_t) {.new_beam = false, .idx = 0};
|
||||
|
||||
const int index = get_beam_index(beam_info, frame, slot, slots_per_frame);
|
||||
@@ -3417,7 +3412,7 @@ void reset_beam_status(NR_beam_info_t *beam_info, int frame, int slot, int beam_
|
||||
void beam_selection_procedures(gNB_MAC_INST *mac, NR_UE_info_t *UE)
|
||||
{
|
||||
// do not perform beam procedures if there is no beam information
|
||||
if (!mac->beam_info.beam_allocation)
|
||||
if (!mac->beam_info.beam_mode == NO_BEAM_MODE)
|
||||
return;
|
||||
RSRP_report_t *rsrp_report = &UE->UE_sched_ctrl.CSI_report.ssb_rsrp_report;
|
||||
// simple beam switching algorithm -> we select beam with highest RSRP from CSI report
|
||||
@@ -3725,3 +3720,24 @@ void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool
|
||||
sched_ctrl->pdcch_cl_adjust = max(0, sched_ctrl->pdcch_cl_adjust - 0.01);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Get CORESET resource block parameters from frequency domain resources bitmap.
|
||||
/// @param coreset Pointer to the CORESET configuratio
|
||||
/// @param n_rb Output parameter for total # of RBs in the CORESET
|
||||
/// @param rb_start Output parameter for the starting resource block index of the CORESET
|
||||
void get_coreset_rb_params(const NR_ControlResourceSet_t *coreset, uint16_t *n_rb, uint16_t *rb_start)
|
||||
{
|
||||
*n_rb = 0;
|
||||
*rb_start = 0;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int t = 0; t < 8; t++) {
|
||||
if ((coreset->frequencyDomainResources.buf[i] >> (7 - t)) & 1) {
|
||||
if (*n_rb == 0) {
|
||||
*rb_start = 48 * i + t * 6;
|
||||
}
|
||||
*n_rb += 6; // Each bit represents 6 RBs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,7 +465,7 @@ static void nr_configure_srs(gNB_MAC_INST *nrmac,
|
||||
if (srs_resource_set->usage == NR_SRS_ResourceSet__usage_beamManagement) {
|
||||
srs_pdu->beamforming.trp_scheme = 0;
|
||||
srs_pdu->beamforming.num_prgs = m_SRS[srs_pdu->config_index];
|
||||
srs_pdu->beamforming.prg_size = 1;
|
||||
srs_pdu->beamforming.prg_size = srs_pdu->srs_parameters_v4.srs_bandwidth_size;
|
||||
}
|
||||
srs_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index;
|
||||
NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, slots_per_frame);
|
||||
|
||||
@@ -2311,8 +2311,9 @@ nfapi_nr_pusch_pdu_t *prepare_pusch_pdu(nfapi_nr_ul_tti_request_t *future_ul_tti
|
||||
pusch_pdu->pusch_data.tb_size = sched_pusch->tb_size;
|
||||
pusch_pdu->pusch_data.num_cb = 0; // CBG not supported
|
||||
// Beamforming
|
||||
pusch_pdu->beamforming.num_prgs = 0;
|
||||
pusch_pdu->beamforming.prg_size = 0; // bwp_size;
|
||||
pusch_pdu->beamforming.num_prgs = 1;
|
||||
//LOG_E(NR_MAC, "PUSCH PDU BWPSize: %d", pusch_pdu->bwp_size);
|
||||
pusch_pdu->beamforming.prg_size = pusch_pdu->bwp_size;
|
||||
pusch_pdu->beamforming.dig_bf_interface = 1;
|
||||
pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index;
|
||||
/* TRANSFORM PRECODING --------------------------------------------------------*/
|
||||
|
||||
@@ -451,7 +451,7 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
|
||||
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, gNB_MAC_INST *mac);
|
||||
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);
|
||||
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);
|
||||
@@ -491,6 +491,7 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid);
|
||||
|
||||
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti);
|
||||
void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool feedback_not_detected);
|
||||
void get_coreset_rb_params(const NR_ControlResourceSet_t *coreset, uint16_t *n_rb, uint16_t *rb_start);
|
||||
|
||||
void prepare_du_configuration_update(gNB_MAC_INST *mac,
|
||||
f1ap_served_cell_info_t *info,
|
||||
|
||||
@@ -787,12 +787,19 @@ typedef struct {
|
||||
uid_allocator_t uid_allocator;
|
||||
} NR_UEs_t;
|
||||
|
||||
typedef enum {
|
||||
NO_BEAM_MODE,
|
||||
PRECONFIGURED_BEAM_IDX,
|
||||
LOPHY_BEAM_IDX,
|
||||
} nr_beam_mode_t;
|
||||
|
||||
typedef struct {
|
||||
/// list of allocated beams per period
|
||||
int **beam_allocation;
|
||||
int beam_duration; // in slots
|
||||
int beams_per_period;
|
||||
int beam_allocation_size;
|
||||
nr_beam_mode_t beam_mode;
|
||||
} NR_beam_info_t;
|
||||
|
||||
#define UE_iterator(BaSe, VaR) NR_UE_info_t ** VaR##pptr=BaSe, *VaR; while ((VaR=*(VaR##pptr++)))
|
||||
|
||||
@@ -259,7 +259,14 @@ static bool is_tdd_ul_symbol(const struct xran_frame_config *frame_conf, int slo
|
||||
* slot is not UL). */
|
||||
static bool is_tdd_dl_guard_slot(const struct xran_frame_config *frame_conf, int slot)
|
||||
{
|
||||
return !is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1);
|
||||
return !is_tdd_ul_symbol(frame_conf, slot, 0);
|
||||
}
|
||||
|
||||
/** @brief Check if current slot is UL or guard/mixed without UL (i.e., current
|
||||
* slot is not UL). */
|
||||
static bool is_tdd_ul_guard_slot(const struct xran_frame_config *frame_conf, int slot)
|
||||
{
|
||||
return is_tdd_ul_symbol(frame_conf, slot, XRAN_NUM_OF_SYMBOL_PER_SLOT - 1);
|
||||
}
|
||||
|
||||
/** @details Read PRACH and PUSCH data from xran buffers. If
|
||||
@@ -279,7 +286,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
static int64_t old_tx_counter[XRAN_PORTS_NUM] = {0};
|
||||
struct xran_common_counters x_counters[XRAN_PORTS_NUM];
|
||||
static int outcnt = 0;
|
||||
#ifndef USE_POLLING
|
||||
#ifndef USE_POLLING
|
||||
// pull next even from oran_sync_fifo
|
||||
notifiedFIFO_elt_t *res = pullNotifiedFIFO(&oran_sync_fifo);
|
||||
|
||||
@@ -337,7 +344,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
|
||||
start_ptr = rx_data + (slot_size * slot_offset_rxdata);
|
||||
const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf;
|
||||
// skip processing this slot is TX (no RX in this slot)
|
||||
if (is_tdd_dl_guard_slot(frame_conf, *slot))
|
||||
if (!is_tdd_ul_guard_slot(frame_conf, *slot))
|
||||
continue;
|
||||
// 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++) {
|
||||
@@ -484,12 +491,73 @@ 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;
|
||||
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
|
||||
|
||||
// Handle CP UL packet here instead of at xran_fh_rx_read_slot() as oran_fh_if4p5_south_in() lags behind
|
||||
// oran_fh_if4p5_south_out() (which is invoked at the right time slot) by 4 slots.
|
||||
// Need to use --continuous-tx so that this routine will be triggered in RX slot.
|
||||
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_rx; ant_id++) {
|
||||
int first = 1; // The first UL symbol
|
||||
const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_rx_per_ru)->frame_conf;
|
||||
// skip processing this slot is TX (no RX in this slot)
|
||||
if (!is_tdd_ul_guard_slot(frame_conf, slot)) {
|
||||
continue;
|
||||
}
|
||||
// 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++) {
|
||||
/* the callback is for mixed and UL slots. In mixed, we have to
|
||||
* skip DL and guard symbols. */
|
||||
if (!is_tdd_ul_symbol(frame_conf, slot, sym_idx)) {
|
||||
continue;
|
||||
}
|
||||
oran_buf_list_t *bufs = get_xran_buffers(ant_id / nb_rx_per_ru);
|
||||
uint8_t *pPrbMapData = bufs->dstcp[ant_id % nb_rx_per_ru][tti % XRAN_N_FE_BUF_LEN].pBuffers->pData;
|
||||
struct xran_prb_map *pPrbMap = (struct xran_prb_map *)pPrbMapData;
|
||||
|
||||
struct xran_prb_elm *pRbElm = &pPrbMap->prbMap[0];
|
||||
|
||||
struct xran_prb_map *pRbMap = pPrbMap;
|
||||
uint32_t idxElm = 0;
|
||||
|
||||
LOG_D(HW, "pRbMap->nPrbElm %d\n", pRbMap->nPrbElm);
|
||||
for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
|
||||
LOG_D(HW,
|
||||
"prbMap[%d] : PRBstart %d nPRBs %d\n",
|
||||
idxElm,
|
||||
pRbMap->prbMap[idxElm].nRBStart,
|
||||
pRbMap->prbMap[idxElm].nRBSize);
|
||||
pRbElm = &pRbMap->prbMap[idxElm];
|
||||
if (first) {
|
||||
// ant_id / no of antenna per beam gives the beam_nb
|
||||
pRbElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_rx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT + sym_idx];
|
||||
// In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly.
|
||||
if (pRbElm->nBeamIndex == -1) {
|
||||
pRbElm->nBeamIndex = 32766;
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
const struct xran_frame_config *frame_conf = &get_xran_fh_config(ant_id / nb_tx_per_ru)->frame_conf;
|
||||
// skip processing this slot is TX (no TX in this slot)
|
||||
if (!is_tdd_dl_guard_slot(frame_conf, slot)) {
|
||||
continue;
|
||||
}
|
||||
// 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++) {
|
||||
/* the callback is for mixed and UL slots. In mixed, we have to
|
||||
* skip UL and guard symbols. */
|
||||
if (is_tdd_ul_symbol(frame_conf, slot, sym_idx)) {
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
@@ -512,6 +580,14 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
for (idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++) {
|
||||
struct xran_section_desc *p_sec_desc = NULL;
|
||||
p_prbMapElm = &pRbMap->prbMap[idxElm];
|
||||
if (sym_idx == 0) {
|
||||
// ant_id / no of antenna per beam gives the beam_nb
|
||||
p_prbMapElm->nBeamIndex = ru->beam_id[ant_id / (ru->nb_tx / ru->num_beams_period)][slot * XRAN_NUM_OF_SYMBOL_PER_SLOT];
|
||||
// In phy-f-1.0/fhi_lib/lib/api/xran_pkt_cp.h, beamId:15 is of 15bit. -1 set extension bit ef:1 to 1 mistakenly.
|
||||
if (p_prbMapElm->nBeamIndex == -1)
|
||||
p_prbMapElm->nBeamIndex = 32767;
|
||||
}
|
||||
|
||||
// assumes one fragment per symbol
|
||||
#ifdef E_RELEASE
|
||||
p_sec_desc = p_prbMapElm->p_sec_desc[sym_id][0];
|
||||
|
||||
@@ -920,7 +920,7 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
|
||||
fh_config->dpdk_port = ru_idx; // DPDK port number used for FH
|
||||
fh_config->sector_id = 0; // Band sector ID for FH; not used in xran
|
||||
fh_config->nCC = 1; // number of Component carriers supported on FH; M-plane info
|
||||
fh_config->neAxc = RTE_MAX(oai0->num_distributed_ru * oai0->tx_num_channels / num_rus, oai0->num_distributed_ru * oai0->rx_num_channels / num_rus); // number of eAxc supported on one CC = max(PDSCH, PUSCH)
|
||||
fh_config->neAxc = RTE_MAX(oai0->tx_num_channels / num_rus, oai0->rx_num_channels / num_rus); // number of eAxc supported on one CC = max(PDSCH, PUSCH)
|
||||
fh_config->neAxcUl = 0; // number of eAxc supported on one CC for UL direction = PUSCH; used only if XRAN_CATEGORY_B
|
||||
fh_config->nAntElmTRx = 0; // number of antenna elements for TX and RX = SRS; used only if XRAN_CATEGORY_B
|
||||
fh_config->nDLFftSize = 0; // DL FFT size; not used in xran
|
||||
|
||||
@@ -335,6 +335,7 @@ static void oran_allocate_buffers(void *handle,
|
||||
struct xran_prb_map dlPmMixed = {0};
|
||||
struct xran_prb_map ulPmMixed = {0};
|
||||
uint32_t idx = 0;
|
||||
|
||||
if (fh_config->frame_conf.nFrameDuplexType == XRAN_TDD) {
|
||||
oran_mixed_slot_t info = get_mixed_slot_info(&fh_config->frame_conf);
|
||||
dlPmMixed = get_xran_prb_map(fh_config, XRAN_DIR_DL, 0, info.num_dlsym);
|
||||
|
||||
@@ -214,11 +214,15 @@ void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
|
||||
{
|
||||
ru_info_t ru_info;
|
||||
ru_info.nb_rx = ru->nb_rx * ru->num_beams_period;
|
||||
ru_info.nb_tx = ru->nb_rx * ru->num_beams_period;
|
||||
ru_info.rxdataF = ru->common.rxdataF;
|
||||
ru_info.beam_id = ru->common.beam_id;
|
||||
ru_info.num_beams_period = ru->num_beams_period;
|
||||
ru_info.prach_buf = ru->prach_rxsigF[0]; // index: [prach_oca][ant_id]
|
||||
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
int f, sl;
|
||||
int f = *frame;
|
||||
int sl = *slot;
|
||||
LOG_D(HW, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]);
|
||||
start_meas(&ru->rx_fhaul);
|
||||
int ret = xran_fh_rx_read_slot(&ru_info, &f, &sl);
|
||||
@@ -267,8 +271,12 @@ void oran_fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
start_meas(&ru->tx_fhaul);
|
||||
ru_info_t ru_info;
|
||||
ru_info.nb_rx = ru->nb_rx * ru->num_beams_period;
|
||||
ru_info.nb_tx = ru->nb_tx * ru->num_beams_period;
|
||||
ru_info.txdataF_BF = ru->common.txdataF_BF;
|
||||
ru_info.beam_id = ru->common.beam_id;
|
||||
ru_info.num_beams_period = ru->num_beams_period;
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -41,6 +41,14 @@ typedef struct ru_info_s {
|
||||
int nb_tx;
|
||||
int32_t **txdataF_BF;
|
||||
|
||||
/// \brief Anaglogue beam ID for each OFDM symbol (used when beamforming not done in RU)
|
||||
/// - first index: concurrent beam
|
||||
/// - second index: beam_id [0.. symbols_per_frame]
|
||||
int32_t **beam_id;
|
||||
|
||||
/// number of concurrent analog beams in period
|
||||
int num_beams_period;
|
||||
|
||||
// Needed for Prach
|
||||
int16_t **prach_buf;
|
||||
} ru_info_t;
|
||||
|
||||
Reference in New Issue
Block a user