Compare commits

...

23 Commits

Author SHA1 Message Date
Mario Joa-Ng
6014f65602 Revert "support multiple beam using multiple c-plane sections, one for each beam"
This reverts commit 1e4f8742786ab33a505dce44f81e56826f730863.
2025-08-14 21:57:52 +02:00
Mario Joa-Ng
5722b09095 fix the bug where xran lib always set beam_id to 0 2025-08-13 18:38:30 +02:00
Mario Joa-Ng
1c3f7d41f8 remove debugging trace. 2025-08-13 17:19:02 +02:00
Mario Joa-Ng
08e8eecef8 Handle CP UL packet at xran_fx_tx_send_slot() instead of xran_fh_rx_read_slot() as the latter lags behind the former by 4 slots. 2025-08-13 17:18:50 +02:00
Mario Joa-Ng
5f81e85ff9 need to set beam_id for UPLINK_SLOT. 2025-08-13 17:18:05 +02:00
Mario Joa-Ng
cd7e09ab9c set beam_id to -1 instead of 0. 2025-08-13 17:08:11 +02:00
Mario Joa-Ng
7be2077ca5 Set beam_idx to 32767. 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. 2025-08-05 10:55:15 -04:00
Mario Joa-Ng
fd7cee2c5c each stream uses beam_idx -1 (aka unassigned) at first 2025-08-05 10:55:15 -04:00
Mario Joa-Ng
0425f4bb7b set nBeamIndex to ru->beam_id indexed by slot. 2025-08-05 10:55:15 -04:00
Mario Joa-Ng
62c2885039 Revert "handle per-sysmbol c-plane message"
This reverts commit d4714ff4bca0e6152d721eabe57eef53ee666a1b.
2025-08-05 10:47:26 -04:00
Mario Joa-Ng
f3ea944d30 set set nBeamIndex on RU_port according to beam allocation 2025-08-05 10:47:26 -04:00
Mario Joa-Ng
419c52e9fc handle per-sysmbol c-plane message 2025-08-05 10:47:26 -04:00
Mario Joa-Ng
366e706e47 fix a minor bug in mapping beam to antenna port. 2025-08-05 10:47:26 -04:00
Mario Joa-Ng
84e91d831c set nBeamIndex on RU_port according to beam allocation 2025-08-05 10:47:26 -04:00
Mario Joa-Ng
788d1cbc1c Fix the bug in calculating fh_config->neAxc where num_beams_period is multiplified twice. 2025-08-05 10:47:26 -04:00
Mario Joa-Ng
867c01e896 support multiple beam using multiple c-plane sections, one for each beam 2025-08-05 10:47:26 -04:00
francescomani
af7baede1b minor refactoring in nfapi_nr_interface_scf 2025-08-04 19:29:06 +02:00
francescomani
247e3ccd4c renaming analog to time domain beamforming (for consistency with ORAN specifications) 2025-08-04 19:28:49 +02:00
Gabriele Gemmi
5661e639f3 compute prgsize from number of RA RB 2025-08-02 21:30:56 +00:00
Gabriele Gemmi
8c7bc93e9c Removed TRP-scheme byte from UL BF PDU to Interop with Aerial 25-1 2025-08-01 11:13:07 +02:00
Gabriele Gemmi
407a049ac9 Compute DCI prgsize from Coreset 2025-08-01 11:13:07 +02:00
Gabriele Gemmi
e564b0dc69 Configuration of FAPI Beamforming PDU for Aerial PBBF 2025-08-01 11:13:07 +02:00
francescomani
9d98aee083 add option to directly send the beam index to L1 via FAPI without look-up table (for 7.2 split) 2025-08-01 11:13:02 +02:00
42 changed files with 2171 additions and 236 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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:

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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++) {

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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;

View File

@@ -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;

View File

@@ -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));

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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++)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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
}
}
}
}

View File

@@ -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);

View File

@@ -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 --------------------------------------------------------*/

View File

@@ -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,

View File

@@ -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++)))

View File

@@ -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];

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;