Merge remote-tracking branch 'origin/Mult_TDD_Pattern' into integration_2025_w05 (!2799)
Changes to support multiple TDD patterns - Updated the configuration changes for 2 Patterns - Update the TDD table configuration for NFAPI - Added the tdd bitmap for the period - Adapted the bitmap for UL/DL for the multi TDD pattern - Updated the RACH procedure for multi TDD pattern - Updated DL and UL scheduler for multi TDD pattern
This commit is contained in:
@@ -66,7 +66,7 @@ gNBs =
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 98;
|
||||
prach_ConfigurationIndex = 154;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
@@ -133,11 +133,21 @@ gNBs =
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
# ext: 8=ms3, 9=ms4
|
||||
dl_UL_TransmissionPeriodicity = 8;
|
||||
nrofDownlinkSlots = 3;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
# pattern2
|
||||
pattern2: {
|
||||
dl_UL_TransmissionPeriodicity2 = 4;
|
||||
nrofDownlinkSlots2 = 4;
|
||||
nrofDownlinkSymbols2 = 0;
|
||||
nrofUplinkSlots2 = 0;
|
||||
nrofUplinkSymbols2 = 0;
|
||||
};
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
|
||||
-->
|
||||
<testCaseList>
|
||||
<htmlTabRef>TEST-SA-FR1-SC-FDMA-B200</htmlTabRef>
|
||||
<htmlTabName>40 MHz TDD SA with SC-FDMA</htmlTabName>
|
||||
<htmlTabRef>TEST-SA-FR1-SC-PATTERN2-FDMA-B200</htmlTabRef>
|
||||
<htmlTabName>40 MHz TDD (pattern2) SA with SC-FDMA</htmlTabName>
|
||||
<htmlTabIcon>tasks</htmlTabIcon>
|
||||
<TestCaseRequestedList>
|
||||
300000
|
||||
@@ -101,7 +101,7 @@
|
||||
</testCase>
|
||||
<testCase id="230101">
|
||||
<class>Deploy_Object</class>
|
||||
<desc>Deploy gNB (TDD/Band78/40MHz/B200) with SC-FDMA in a container</desc>
|
||||
<desc>Deploy gNB (TDD/pattern2/Band78/40MHz/B200) with SC-FDMA in a container</desc>
|
||||
<yaml_path>ci-scripts/yaml_files/sa_sc_b200_gnb</yaml_path>
|
||||
<eNB_instance>0</eNB_instance>
|
||||
<eNB_serverId>0</eNB_serverId>
|
||||
|
||||
@@ -704,9 +704,12 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn)
|
||||
return frequency;
|
||||
}
|
||||
|
||||
int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols)
|
||||
/**
|
||||
* @brief Get the slot index within the period
|
||||
*/
|
||||
int get_slot_idx_in_period(const int slot, const frame_structure_t *fs)
|
||||
{
|
||||
return (nrofDownlinkSlots + (nrofDownlinkSymbols != 0 && nrofUplinkSymbols == 0));
|
||||
return slot % fs->numb_slots_period;
|
||||
}
|
||||
|
||||
int get_dmrs_port(int nl, uint16_t dmrs_ports)
|
||||
|
||||
@@ -122,6 +122,29 @@ typedef enum frequency_range_e {
|
||||
FR2
|
||||
} frequency_range_t;
|
||||
|
||||
#define MAX_NUM_SLOTS_ALLOWED 80 // up to numerology 3 (120 KHz SCS) is supported
|
||||
enum slot_type { TDD_NR_DOWNLINK_SLOT, TDD_NR_UPLINK_SLOT, TDD_NR_MIXED_SLOT };
|
||||
|
||||
typedef struct tdd_bitmap {
|
||||
enum slot_type slot_type;
|
||||
uint8_t num_dl_symbols;
|
||||
uint8_t num_ul_symbols;
|
||||
} tdd_bitmap_t;
|
||||
|
||||
typedef struct tdd_period_config_s {
|
||||
tdd_bitmap_t tdd_slot_bitmap[MAX_NUM_SLOTS_ALLOWED];
|
||||
uint8_t num_dl_slots;
|
||||
uint8_t num_ul_slots;
|
||||
} tdd_period_config_t;
|
||||
|
||||
typedef struct frame_structure_s {
|
||||
tdd_period_config_t period_cfg;
|
||||
int8_t numb_slots_frame;
|
||||
int8_t numb_slots_period;
|
||||
int8_t numb_period_frame;
|
||||
bool is_tdd;
|
||||
} frame_structure_t;
|
||||
|
||||
typedef struct {
|
||||
/// Time shift in number of samples estimated based on DMRS-PDSCH/PUSCH
|
||||
int est_delay;
|
||||
@@ -219,7 +242,6 @@ void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out);
|
||||
uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn);
|
||||
uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw);
|
||||
|
||||
int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols);
|
||||
int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs);
|
||||
int get_SLIV(uint8_t S, uint8_t L);
|
||||
void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset);
|
||||
@@ -265,6 +287,8 @@ int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_
|
||||
unsigned short get_m_srs(int c_srs, int b_srs);
|
||||
unsigned short get_N_b_srs(int c_srs, int b_srs);
|
||||
|
||||
int get_slot_idx_in_period(const int slot, const frame_structure_t *fs);
|
||||
|
||||
#define CEILIDIV(a,b) ((a+b-1)/b)
|
||||
#define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
|
||||
|
||||
|
||||
+3
-1
@@ -24,7 +24,9 @@
|
||||
|
||||
The following features are valid for the gNB and the 5G-NR UE.
|
||||
|
||||
* Static TDD, FDD
|
||||
* Static TDD
|
||||
- Multi TDD pattern supported refer [TDD Configuration](NR_SA_Multi_TDD_Pattern.md)
|
||||
* Static FDD
|
||||
* Normal CP
|
||||
* Subcarrier spacings: 15 and 30kHz (FR1), 120kHz (FR2)
|
||||
* Bandwidths: 10, 20, 40, 60, 80, 100MHz
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
@@ -240,3 +240,115 @@ here, *also they pertain to the DU*, i.e., the scheduler.
|
||||
options are 2, 4, 6, 8, 10, 12, 32; **32 is a Rel-17 features**)
|
||||
* `num_ulharq` (default 16): as `num_dlharq` for UL (other valid option is 32;
|
||||
**32 is i Rel-17 feature**)
|
||||
|
||||
## ServingCellConfigCommon parameters
|
||||
|
||||
The `gNBs` configuration section has a big structure `servingCellConfigCommon`
|
||||
that has an influence on the overall behavior of MAC and L1. As the name says,
|
||||
this structure is a flat representation of the ServingCellConfigCommon
|
||||
structure, specified by 3GPP. Describing all of these parameters would be too
|
||||
exhaustive; more information about the individual fields can be found in 3GPP
|
||||
TS 38.331, section 6.3.2 "Radio resource control information elements".
|
||||
|
||||
Below is a description of some of these parameters.
|
||||
|
||||
### Frequency configuration
|
||||
|
||||
There are many parameters, such as `absoluteFrequencySSB`, etc., that have an
|
||||
impact on the frequency used by the gNB. For more information, please check the
|
||||
[corresponding document](../gNB_frequency_setup.md).
|
||||
|
||||
### TDD pattern configuration
|
||||
|
||||
The TDD configuration parameters allow to use one or two TDD patterns.
|
||||
|
||||
#### Single TDD pattern
|
||||
|
||||
Configure the TDD pattern through these options:
|
||||
- `dl_UL_TransmissionPeriodicity`: Refers to the UL/DL slots periodicity for
|
||||
the TDD pattern. See below for valid numbers.
|
||||
- `nrofDownlinkSlots`: Refers to the number of consecutive DL slots in the TDD
|
||||
pattern. The number of DL slots depends on the TDD period.
|
||||
- `nrofDownlinkSymbols`: Indicates the number of consecutive DL symbols within
|
||||
the special slot that follows the downlink slots in the TDD pattern. The
|
||||
special slot is needed only to switch from DL to UL. The maximum number of
|
||||
symbols in this slot is 14.
|
||||
- `nrofUplinkSlots`: Refers to the number of consecutive UL slots in the TDD
|
||||
pattern, depending on the desired TDD period.
|
||||
- `nrofUplinkSymbols`: Indicates the number of consecutive UL symbols within
|
||||
the special slot that follows the downlink slots in the TDD pattern. The sum
|
||||
of downlink and uplink symbols should not exceed 14.
|
||||
- `prach_ConfigurationIndex`: index for PRACH according to tables 6.3.3.2-2 to
|
||||
6.3.3.2-4 in TS 38.211.
|
||||
|
||||
As an example, the below figure shows a single TDD pattern, consisting of 3 DL
|
||||
slots, 1 mixed slots (with 10 DL, 2 guard, 2 UL symbols), and 1 UL slot.
|
||||
|
||||

|
||||
|
||||
To configure this pattern in the configuration file, use
|
||||
|
||||
```plaintext
|
||||
#dl_UL_TransmissionPeriodicity 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10, 8=ms3, 9=ms4
|
||||
|
||||
dl_UL_TransmissionPeriodicity = 5;
|
||||
nrofDownlinkSlots = 3;
|
||||
nrofDownlinkSymbols = 10;
|
||||
nrofUplinkSlots = 1;
|
||||
nrofUplinkSymbols = 2;
|
||||
```
|
||||
|
||||
The `dl_UL_TransmissionPeriodicity` is set to `5` (2.5ms). The above figure
|
||||
shows two TDD periods over 5ms. The 10 ms frame period must be strictly
|
||||
divisible by the sum of the TDD pattern periods.
|
||||
|
||||
#### Two TDD patterns
|
||||
|
||||
An optional `pattern2` structure is used to signal a TDD pattern 2.
|
||||
In this case, the TDD pattern may have two extended values of 3 ms and 4 ms.
|
||||
These values are standardized as `dl-UL-TransmissionPeriodicity-v1530`. For the
|
||||
sake of simplicity of the gNB configuration file, we have extended the set of
|
||||
`dl-UL-TransmissionPeriodicity` values to support the new TDD periods, as
|
||||
explained in the table below. However, these values will later be encoded as
|
||||
`dl-UL-TransmissionPeriodicity-v1530` to match the specifications.
|
||||
|
||||
| `dl_UL_TransmissionPeriodicity` | TDD period |
|
||||
|---------------------------------|------------|
|
||||
| 0 | 0.5 ms |
|
||||
| 1 | 0.625 ms |
|
||||
| 2 | 1 ms |
|
||||
| 3 | 1.25 ms |
|
||||
| 4 | 2 ms |
|
||||
| 5 | 2.5 ms |
|
||||
| 6 | 5 ms |
|
||||
| 7 | 10 ms |
|
||||
| 8 | 3 ms |
|
||||
| 9 | 4 ms |
|
||||
|
||||
The 10 ms frame period must be strictly divisible by the sum of the TDD pattern
|
||||
periods. For example, the 3 ms TDD pattern should be used with a second TDD
|
||||
pattern of 2 ms. Additionally, the 4 ms TDD pattern should be used with a
|
||||
second TDD pattern of 1 ms.
|
||||
|
||||
As an example, this configuration might be used, where the first TDD pattern is
|
||||
followed by a second, consisting of 4 DL slots.
|
||||
```
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
# ext: 8=ms3, 9=ms4
|
||||
dl_UL_TransmissionPeriodicity = 8;
|
||||
nrofDownlinkSlots = 3;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
# pattern2
|
||||
pattern2: {
|
||||
dl_UL_TransmissionPeriodicity2 = 4;
|
||||
nrofDownlinkSlots2 = 4;
|
||||
nrofDownlinkSymbols2 = 0;
|
||||
nrofUplinkSlots2 = 0;
|
||||
nrofUplinkSymbols2 = 0;
|
||||
};
|
||||
```
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#define NFAPI_MAX_NUM_CB 8
|
||||
#define NFAPI_MAX_NUM_PRGS 1
|
||||
#define NFAPI_MAX_NUM_BG_IF 1
|
||||
#define NFAPI_MAX_NUM_PERIODS 8
|
||||
|
||||
// Extension to the generic structures for single tlv values
|
||||
|
||||
@@ -436,7 +437,10 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
nfapi_uint8_tlv_t tdd_period;//DL UL Transmission Periodicity. Value:0: ms0p5 1: ms0p625 2: ms1 3: ms1p25 4: ms2 5: ms2p5 6: ms5 7: ms10 8: ms3 9: ms4
|
||||
/**DL UL Transmission Periodicity: for multiple TDD pattern,
|
||||
* the value corresponds to the sum periodicity (3GPP TS 38.213, 11.1)
|
||||
* Values: 0:ms0p5 1:ms0p625 2:ms1 3:ms1p25 4:ms2 5:ms2p5 6:ms5 7:ms10 8:ms20 */
|
||||
nfapi_uint8_tlv_t tdd_period;
|
||||
nfapi_nr_max_tdd_periodicity_t* max_tdd_periodicity_list;
|
||||
|
||||
} nfapi_nr_tdd_table_t;
|
||||
|
||||
@@ -669,10 +669,6 @@ void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen)
|
||||
{
|
||||
nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id);
|
||||
|
||||
#if 0 // emulate set_config TLV reception (hard-code)
|
||||
int tdd_return = set_tdd_config_nr(&req, 1, 7, 6, 2, 4);
|
||||
#endif
|
||||
|
||||
if(phy)
|
||||
{
|
||||
if(phy->state != NFAPI_PNF_PHY_RUNNING)
|
||||
|
||||
@@ -44,108 +44,112 @@
|
||||
#define NR_TST_PHY_PRINTF(...)
|
||||
#endif
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* NAME : set_tdd_configuration
|
||||
*
|
||||
* PARAMETERS : pointer to frame configuration
|
||||
*
|
||||
* OUTPUT: table of uplink symbol for each slot for 2 frames
|
||||
*
|
||||
* RETURN : nb_periods_per_frame if tdd has been properly configurated
|
||||
* -1 tdd configuration can not be done
|
||||
*
|
||||
* DESCRIPTION : generate bit map for uplink symbol for each slot for several frames
|
||||
* see TS 38.213 11.1 Slot configuration
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg,
|
||||
int mu,
|
||||
int nrofDownlinkSlots,
|
||||
int nrofDownlinkSymbols,
|
||||
int nrofUplinkSlots,
|
||||
int nrofUplinkSymbols)
|
||||
/** @brief This function processes TDD dedicated configuration for NR
|
||||
* by processing the tdd_slot_bitmap and period_cfg, and
|
||||
* allocates memory and fills max_num_of_symbol_per_slot_list
|
||||
* in the nfapi config request (cfg)
|
||||
* @ref see TS 38.213 11.1 Slot configuration
|
||||
* @param cfg NR config request structure pointer
|
||||
* @param fs TDD configuration pointer
|
||||
* @returns void
|
||||
*/
|
||||
void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs)
|
||||
{
|
||||
AssertFatal(fs != NULL, "frame_structure must be non-NULL");
|
||||
|
||||
int slot_number = 0;
|
||||
int nb_periods_per_frame = get_nb_periods_per_frame(cfg->tdd_table.tdd_period.value);
|
||||
int nb_slots_to_set = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
int nb_slots_to_set = fs->numb_slots_frame;
|
||||
int slot_index = 0;
|
||||
tdd_period_config_t *pc = &fs->period_cfg;
|
||||
tdd_bitmap_t *tdd_slot_bitmap = pc->tdd_slot_bitmap;
|
||||
|
||||
int nb_slots_per_period = ((1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) / nb_periods_per_frame;
|
||||
|
||||
if ((nrofDownlinkSymbols + nrofUplinkSymbols) == 0)
|
||||
AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots),
|
||||
"set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, "
|
||||
"nrofUplinkSlots %d, nb_slots_per_period %d \n",
|
||||
nrofDownlinkSlots,
|
||||
nrofUplinkSlots,
|
||||
nb_slots_per_period);
|
||||
else {
|
||||
AssertFatal(nrofDownlinkSymbols + nrofUplinkSymbols < 14,
|
||||
"illegal symbol configuration DL %d, UL %d\n",
|
||||
nrofDownlinkSymbols,
|
||||
nrofUplinkSymbols);
|
||||
AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots + 1),
|
||||
"set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, "
|
||||
"nrofUplinkSlots %d, nrofMixed slots 1, nb_slots_per_period %d \n",
|
||||
nrofDownlinkSlots,
|
||||
nrofUplinkSlots,
|
||||
nb_slots_per_period);
|
||||
}
|
||||
|
||||
cfg->tdd_table.max_tdd_periodicity_list = calloc(nb_slots_to_set, sizeof(nfapi_nr_max_tdd_periodicity_t));
|
||||
LOG_I(NR_PHY,
|
||||
"Set TDD Period Configuration: %d periods per frame, %d slots to be configured (%d DL, %d UL)\n",
|
||||
fs->numb_period_frame,
|
||||
nb_slots_to_set,
|
||||
pc->num_dl_slots,
|
||||
pc->num_ul_slots);
|
||||
|
||||
// Allocate memory formax_num_of_symbol_per_slot_list items
|
||||
cfg->tdd_table.max_tdd_periodicity_list = calloc_or_fail(nb_slots_to_set, sizeof(nfapi_nr_max_tdd_periodicity_t));
|
||||
for (int slot = 0; slot < nb_slots_to_set; slot++) {
|
||||
nfapi_nr_max_tdd_periodicity_t *p_list = &cfg->tdd_table.max_tdd_periodicity_list[slot];
|
||||
p_list->max_num_of_symbol_per_slot_list =
|
||||
calloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list));
|
||||
calloc_or_fail(NR_NUMBER_OF_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list));
|
||||
for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) {
|
||||
// for each symbol, assign the TLV tag for usage when packing
|
||||
p_list->max_num_of_symbol_per_slot_list[sym].slot_config.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through all periods to be configured
|
||||
while (slot_number != nb_slots_to_set) {
|
||||
if (nrofDownlinkSlots != 0) {
|
||||
for (int sym = 0; sym < nrofDownlinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) {
|
||||
cfg->tdd_table.max_tdd_periodicity_list[slot_number]
|
||||
.max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT]
|
||||
.slot_config.value = 0;
|
||||
|
||||
if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0)
|
||||
slot_index = get_slot_idx_in_period(slot_number, fs);
|
||||
/* Fill max_tdd_periodicity_list */
|
||||
nfapi_nr_max_tdd_periodicity_t *list = &cfg->tdd_table.max_tdd_periodicity_list[slot_number];
|
||||
// FULL DOWNLINK SLOTS
|
||||
if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_DOWNLINK_SLOT) {
|
||||
for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) {
|
||||
list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 0;
|
||||
if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) {
|
||||
slot_number++;
|
||||
list += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nrofDownlinkSymbols != 0 || nrofUplinkSymbols != 0) {
|
||||
for (int sym = 0; sym < nrofDownlinkSymbols; sym++) {
|
||||
cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 0;
|
||||
// FLEXIBLE SLOTS
|
||||
if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_MIXED_SLOT) {
|
||||
int nrofDLSymbolsInSlot = tdd_slot_bitmap[slot_index].num_dl_symbols;
|
||||
int nrofULSymbolsInSlot = tdd_slot_bitmap[slot_index].num_ul_symbols;
|
||||
AssertFatal(nrofDLSymbolsInSlot + nrofULSymbolsInSlot < NR_NUMBER_OF_SYMBOLS_PER_SLOT,
|
||||
"illegal symbol configuration DL %d, UL %d\n",
|
||||
nrofDLSymbolsInSlot,
|
||||
nrofULSymbolsInSlot);
|
||||
// DL Symbols
|
||||
for (int sym = 0; sym < nrofDLSymbolsInSlot; sym++) {
|
||||
list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 0;
|
||||
}
|
||||
|
||||
for (int sym = nrofDownlinkSymbols; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; sym++) {
|
||||
cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 2;
|
||||
// Flexible Symbols
|
||||
for (int sym = nrofDLSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym++) {
|
||||
list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 2;
|
||||
}
|
||||
|
||||
for (int sym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) {
|
||||
cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 1;
|
||||
// UL Symbols
|
||||
for (int sym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) {
|
||||
list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 1;
|
||||
}
|
||||
|
||||
slot_number++;
|
||||
list += 1;
|
||||
}
|
||||
|
||||
if (nrofUplinkSlots != 0) {
|
||||
for (int sym = 0; sym < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) {
|
||||
cfg->tdd_table.max_tdd_periodicity_list[slot_number]
|
||||
.max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT]
|
||||
.slot_config.value = 1;
|
||||
|
||||
if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0)
|
||||
// FULL UPLINK SLOTS
|
||||
if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_UPLINK_SLOT) {
|
||||
for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) {
|
||||
list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 1;
|
||||
if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) {
|
||||
slot_number++;
|
||||
list += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (nb_periods_per_frame);
|
||||
// Dump 1 period on the output
|
||||
for (int s = 0; s < fs->numb_slots_period; s++) {
|
||||
if (tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT) {
|
||||
char flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT + 1];
|
||||
memset(flexi_slot, 0, sizeof(flexi_slot));
|
||||
for (int symb = 0; symb < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symb++) {
|
||||
uint8_t val = cfg->tdd_table.max_tdd_periodicity_list[s].max_num_of_symbol_per_slot_list[symb].slot_config.value;
|
||||
char *symb_type_s[] = {"D", "U", "F"};
|
||||
flexi_slot[symb] = *symb_type_s[val];
|
||||
}
|
||||
flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = '\0';
|
||||
LOG_I(NR_PHY, "TDD period configuration: slot %d is FLEXIBLE: %s\n", s, flexi_slot);
|
||||
} else {
|
||||
LOG_I(NR_PHY,
|
||||
"TDD period configuration: slot %d is %s\n",
|
||||
s,
|
||||
tdd_slot_bitmap[s].slot_type == TDD_NR_DOWNLINK_SLOT ? "DOWNLINK" : "UPLINK");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@@ -389,3 +393,48 @@ void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms) {
|
||||
}
|
||||
}
|
||||
|
||||
void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu)
|
||||
{
|
||||
frame_structure_t fs = {.is_tdd = true};
|
||||
fs.numb_slots_frame = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
fs.numb_period_frame = get_nb_periods_per_frame(gNB->gNB_config.tdd_table.tdd_period.value);
|
||||
fs.numb_slots_period = fs.numb_slots_frame / fs.numb_period_frame;
|
||||
tdd_period_config_t *pc = &fs.period_cfg;
|
||||
// Set DL/UL slots
|
||||
switch (mu)
|
||||
{
|
||||
case 0:
|
||||
pc->num_dl_slots = 3;
|
||||
pc->num_ul_slots = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
pc->num_dl_slots = 7;
|
||||
pc->num_ul_slots = 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pc->num_dl_slots = 27;
|
||||
pc->num_ul_slots = 12;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < pc->num_dl_slots; i++) {
|
||||
pc->tdd_slot_bitmap[i].slot_type = TDD_NR_DOWNLINK_SLOT;
|
||||
pc->tdd_slot_bitmap[i].num_dl_symbols = 0;
|
||||
pc->tdd_slot_bitmap[i].num_ul_symbols = 0;
|
||||
}
|
||||
for (int i = pc->num_dl_slots; i < fs.numb_slots_period - pc->num_ul_slots; i++) {
|
||||
pc->tdd_slot_bitmap[i].slot_type = TDD_NR_MIXED_SLOT;
|
||||
pc->tdd_slot_bitmap[i].num_dl_symbols = 6;
|
||||
pc->tdd_slot_bitmap[i].num_ul_symbols = 4;
|
||||
}
|
||||
for (int i = pc->num_ul_slots; i < fs.numb_slots_period; i++) {
|
||||
pc->tdd_slot_bitmap[i].slot_type = TDD_NR_UPLINK_SLOT;
|
||||
pc->tdd_slot_bitmap[i].num_dl_symbols = 0;
|
||||
pc->tdd_slot_bitmap[i].num_ul_symbols = 0;
|
||||
}
|
||||
set_tdd_config_nr(&gNB->gNB_config, &fs);
|
||||
}
|
||||
|
||||
@@ -36,18 +36,16 @@
|
||||
|
||||
/*************** FUNCTIONS *****************************************/
|
||||
|
||||
/** \brief This function processes tdd dedicated configuration for nr
|
||||
* @param frame_parms NR DL Frame parameters
|
||||
* @param dl_UL_TransmissionPeriodicity periodicity
|
||||
* @param nrofDownlinkSlots number of downlink slots
|
||||
* @param nrofDownlinkSymbols number of downlink symbols
|
||||
* @param nrofUplinkSlots number of uplink slots
|
||||
* @param nrofUplinkSymbols number of uplink symbols
|
||||
@returns 0 if tdd dedicated configuration has been properly set or -1 on error with message */
|
||||
|
||||
int set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, int mu,
|
||||
int nrofDownlinkSlots, int nrofDownlinkSymbols,
|
||||
int nrofUplinkSlots, int nrofUplinkSymbols);
|
||||
/** @brief This function processes TDD dedicated configuration for NR
|
||||
* by processing the tdd_slot_bitmap and period_cfg, and
|
||||
* allocates memory and fills max_num_of_symbol_per_slot_list
|
||||
* in the nfapi config request (cfg)
|
||||
* @param cfg NR config request structure pointer
|
||||
* @param fs frame structure pointer
|
||||
* @returns nb_periods_per_frame if TDD has been properly configurated
|
||||
* -1 tdd configuration can not be done
|
||||
*/
|
||||
void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs);
|
||||
|
||||
/** \brief This function adds a slot configuration to current dedicated configuration for nr
|
||||
* @param frame_parms NR DL Frame parameters
|
||||
@@ -92,5 +90,7 @@ void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
|
||||
|
||||
int get_next_downlink_slot(PHY_VARS_gNB *gNB, nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot);
|
||||
|
||||
void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu);
|
||||
|
||||
#endif /* PHY_FRAME_CONFIG_NR_H */
|
||||
|
||||
|
||||
@@ -388,8 +388,9 @@ int main(int argc, char **argv)
|
||||
frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL;
|
||||
crcTableInit();
|
||||
nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell,SSB_positions);
|
||||
gNB->gNB_config.tdd_table.tdd_period.value = 6;
|
||||
set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4);
|
||||
// TDD configuration
|
||||
gNB->gNB_config.tdd_table.tdd_period.value = 6;
|
||||
do_tdd_config_sim(gNB, mu);
|
||||
phy_init_nr_gNB(gNB);
|
||||
//init_eNB_afterRU();
|
||||
frame_length_complex_samples = frame_parms->samples_per_subframe;
|
||||
|
||||
@@ -189,7 +189,7 @@ void nr_dlsim_preprocessor(module_id_t module_id,
|
||||
/* the following might override the table that is mandated by RRC
|
||||
* configuration */
|
||||
current_BWP->mcsTableIdx = g_mcsTableIdx;
|
||||
sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], scc, slot);
|
||||
sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], slot);
|
||||
AssertFatal(sched_pdsch->time_domain_allocation >= 0,"Unable to find PDSCH time domain allocation in list\n");
|
||||
|
||||
sched_pdsch->tda_info = get_dl_tda_info(current_BWP,
|
||||
|
||||
@@ -448,13 +448,10 @@ int main(int argc, char **argv)
|
||||
frame_parms->freq_range = mu<2 ? FR1 : FR2;
|
||||
|
||||
nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions);
|
||||
// TDD configuration
|
||||
gNB->gNB_config.tdd_table.tdd_period.value = 6;
|
||||
if (mu == 0)
|
||||
set_tdd_config_nr(&gNB->gNB_config, mu, 3, 6, 1, 4);
|
||||
else if (mu == 1)
|
||||
set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4);
|
||||
else if (mu == 3)
|
||||
set_tdd_config_nr(&gNB->gNB_config, mu, 27, 6, 12, 4);
|
||||
do_tdd_config_sim(gNB, mu);
|
||||
|
||||
phy_init_nr_gNB(gNB);
|
||||
frame_parms->ssb_start_subcarrier = 12 * gNB->gNB_config.ssb_table.ssb_offset_point_a.value + ssb_subcarrier_offset;
|
||||
initFloatingCoresTpool(ssb_scan_threads, &nrUE_params.Tpool, false, "UE-tpool");
|
||||
|
||||
@@ -568,7 +568,10 @@ int main(int argc, char **argv){
|
||||
|
||||
memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config));
|
||||
RC.nb_nr_L1_inst=1;
|
||||
set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4);
|
||||
// TDD configuration
|
||||
gNB->gNB_config.tdd_table.tdd_period.value = 6;
|
||||
do_tdd_config_sim(gNB, mu);
|
||||
|
||||
phy_init_nr_gNB(gNB);
|
||||
nr_phy_init_RU(ru);
|
||||
|
||||
|
||||
@@ -433,8 +433,10 @@ int main(int argc, char **argv)
|
||||
cfg->carrier_config.num_tx_ant.value = n_tx;
|
||||
cfg->carrier_config.num_rx_ant.value = n_rx;
|
||||
nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);
|
||||
// TDD configuration
|
||||
gNB->gNB_config.tdd_table.tdd_period.value = 6;
|
||||
set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4);
|
||||
do_tdd_config_sim(gNB, mu);
|
||||
|
||||
phy_init_nr_gNB(gNB);
|
||||
/* RU handles rxdataF, and gNB just has a pointer. Here, we don't have an RU,
|
||||
* so we need to allocate that memory as well. */
|
||||
|
||||
@@ -406,8 +406,10 @@ int main(int argc, char **argv)
|
||||
gNB->frame_parms.nb_antennas_rx = n_rx;
|
||||
|
||||
nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions);
|
||||
// TDD configuration
|
||||
gNB->gNB_config.tdd_table.tdd_period.value = 6;
|
||||
set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4);
|
||||
do_tdd_config_sim(gNB, mu);
|
||||
|
||||
phy_init_nr_gNB(gNB);
|
||||
|
||||
//configure UE
|
||||
|
||||
@@ -60,11 +60,11 @@ bool read_mac_sm(void* data)
|
||||
rd->dl_aggr_tbs = UE->mac_stats.dl.total_bytes;
|
||||
rd->ul_aggr_tbs = UE->mac_stats.ul.total_bytes;
|
||||
|
||||
if (is_xlsch_in_slot(RC.nrmac[mod_id]->dlsch_slot_bitmap[rd->slot / 64], rd->slot)) {
|
||||
if (is_dl_slot(rd->slot, &RC.nrmac[mod_id]->frame_structure)) {
|
||||
rd->dl_curr_tbs = UE->mac_stats.dl.current_bytes;
|
||||
rd->dl_sched_rb = UE->mac_stats.dl.current_rbs;
|
||||
}
|
||||
if (is_xlsch_in_slot(RC.nrmac[mod_id]->ulsch_slot_bitmap[rd->slot / 64], rd->slot)) {
|
||||
if (is_ul_slot(rd->slot, &RC.nrmac[mod_id]->frame_structure)) {
|
||||
rd->ul_curr_tbs = UE->mac_stats.ul.current_bytes;
|
||||
rd->ul_sched_rb = sched_ctrl->sched_pusch.rbSize;
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@
|
||||
#define GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS "nrofDownlinkSymbols"
|
||||
#define GNB_CONFIG_STRING_NROFUPLINKSLOTS "nrofUplinkSlots"
|
||||
#define GNB_CONFIG_STRING_NROFUPLINKSYMBOLS "nrofUplinkSymbols"
|
||||
#define GNB_CONFIG_STRING_PATTERN2 "pattern2"
|
||||
#define GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2 "dl_UL_TransmissionPeriodicity2"
|
||||
#define GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2 "nrofDownlinkSlots2"
|
||||
#define GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2 "nrofDownlinkSymbols2"
|
||||
@@ -247,11 +248,6 @@
|
||||
{GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols,.defint64val=6,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFUPLINKSLOTS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,.defint64val=2,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFUPLINKSYMBOLS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols,.defint64val=4,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity,.defintval=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots,.defint64val=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols,.defint64val=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFUPLINKSLOTS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSlots,.defint64val=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSymbols,.defint64val=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,.i64ptr=&scc->ss_PBCH_BlockPower,.defint64val=20,TYPE_INT64,0}, \
|
||||
{GNB_CONFIG_STRING_CELLSPECIFICKOFFSET,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17,.defint64val=0,TYPE_INT64,0}, \
|
||||
{GNB_CONFIG_STRING_EPHEMERIS_POSITION_X,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionX_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \
|
||||
@@ -263,6 +259,15 @@
|
||||
{GNB_CONFIG_STRING_TA_COMMON,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ta_Info_r17->ta_Common_r17,.defint64val=-1,TYPE_INT64,0}, \
|
||||
{GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,.defintval=-1,TYPE_INT64,0}}
|
||||
|
||||
#define SCC_PATTERN2_STRING_CONFIG "pattern2"
|
||||
|
||||
#define SCC_PATTERN2_PARAMS_DESC(pattern2) { \
|
||||
{GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2, NULL,0,.i64ptr=&pattern2.dl_UL_TransmissionPeriodicity,.defint64val=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2, NULL,0,.i64ptr=&pattern2.nrofDownlinkSlots,.defint64val=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2, NULL,0,.i64ptr=&pattern2.nrofDownlinkSymbols,.defint64val=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFUPLINKSLOTS2,NULL, 0,.i64ptr=&pattern2.nrofUplinkSlots,.defint64val=-1,TYPE_INT64,0},\
|
||||
{GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2,NULL, 0,.i64ptr=&pattern2.nrofUplinkSymbols,.defint64val=-1,TYPE_INT64,0}}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* Serving Cell Config Dedicated configuration parameters */
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -113,7 +113,10 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc)
|
||||
scc->ssb_periodicityServingCell = calloc_or_fail(1, sizeof(*scc->ssb_periodicityServingCell));
|
||||
scc->ssbSubcarrierSpacing = calloc_or_fail(1, sizeof(*scc->ssbSubcarrierSpacing));
|
||||
scc->tdd_UL_DL_ConfigurationCommon = calloc_or_fail(1, sizeof(*scc->tdd_UL_DL_ConfigurationCommon));
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern2 = calloc_or_fail(1, sizeof(*scc->tdd_UL_DL_ConfigurationCommon->pattern2));
|
||||
struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon;
|
||||
tdd->pattern1.ext1 = calloc_or_fail(1, sizeof(*tdd->pattern1.ext1));
|
||||
tdd->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 =
|
||||
calloc_or_fail(1, sizeof(*tdd->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530));
|
||||
scc->downlinkConfigCommon = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon));
|
||||
scc->downlinkConfigCommon->frequencyInfoDL = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon->frequencyInfoDL));
|
||||
scc->downlinkConfigCommon->initialDownlinkBWP = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon->initialDownlinkBWP));
|
||||
@@ -357,15 +360,52 @@ void fill_scc_sim(NR_ServingCellConfigCommon_t *scc, uint64_t *ssb_bitmap, int N
|
||||
p1->nrofUplinkSymbols = 4;
|
||||
|
||||
struct NR_TDD_UL_DL_Pattern *p2 = tdd_UL_DL_ConfigurationCommon->pattern2;
|
||||
p2->dl_UL_TransmissionPeriodicity = 321;
|
||||
p2->nrofDownlinkSlots = -1;
|
||||
p2->nrofDownlinkSymbols = -1;
|
||||
p2->nrofUplinkSlots = -1;
|
||||
p2->nrofUplinkSymbols = -1;
|
||||
if (p2) {
|
||||
p2->dl_UL_TransmissionPeriodicity = 321;
|
||||
p2->nrofDownlinkSlots = -1;
|
||||
p2->nrofDownlinkSymbols = -1;
|
||||
p2->nrofUplinkSlots = -1;
|
||||
p2->nrofUplinkSymbols = -1;
|
||||
}
|
||||
|
||||
scc->ss_PBCH_BlockPower = 20;
|
||||
}
|
||||
|
||||
static void fix_tdd_pattern(NR_ServingCellConfigCommon_t *scc)
|
||||
{
|
||||
NR_TDD_UL_DL_Pattern_t *pattern1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
|
||||
int pattern_ext = pattern1->dl_UL_TransmissionPeriodicity - 8;
|
||||
// Check if the pattern1 extension is configured and set the value accordingly
|
||||
if (pattern_ext >= 0) {
|
||||
pattern1->ext1 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern__ext1));
|
||||
pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530 =
|
||||
calloc_or_fail(1, sizeof(*pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530));
|
||||
*pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530 = pattern_ext;
|
||||
pattern1->dl_UL_TransmissionPeriodicity = 5;
|
||||
} else {
|
||||
pattern1->ext1 = NULL;
|
||||
}
|
||||
struct NR_TDD_UL_DL_Pattern *pattern2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2;
|
||||
if (pattern2 != NULL) {
|
||||
/* The pattern2 is not configured free the memory these shall not be encoded with default values in SIB1 */
|
||||
if (pattern2->dl_UL_TransmissionPeriodicity == -1) {
|
||||
free(pattern2);
|
||||
pattern2 = NULL;
|
||||
} else {
|
||||
// Check if the pattern2 extension is configured and set the value accordingly
|
||||
pattern_ext = pattern2->dl_UL_TransmissionPeriodicity - 8;
|
||||
if (pattern_ext >= 0) {
|
||||
pattern2->ext1 = calloc_or_fail(1, sizeof(*pattern2->ext1));
|
||||
pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 =
|
||||
CALLOC(1, sizeof(*pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530));
|
||||
*pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 = pattern_ext;
|
||||
pattern2->dl_UL_TransmissionPeriodicity = 5;
|
||||
} else {
|
||||
pattern2->ext1 = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap)
|
||||
{
|
||||
@@ -436,11 +476,7 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap)
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, scc->tdd_UL_DL_ConfigurationCommon);
|
||||
scc->tdd_UL_DL_ConfigurationCommon = NULL;
|
||||
} else { // TDD
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity > 320 ) {
|
||||
free(scc->tdd_UL_DL_ConfigurationCommon->pattern2);
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern2 = NULL;
|
||||
}
|
||||
|
||||
fix_tdd_pattern(scc);
|
||||
}
|
||||
|
||||
if ((int)*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing == -1) {
|
||||
@@ -982,6 +1018,16 @@ void RCconfig_NR_L1(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true when pattern2 is filled in
|
||||
*/
|
||||
bool is_pattern2_config(paramdef_t *param)
|
||||
{
|
||||
if (param == NULL || param->i64ptr == NULL || *(param->i64ptr) == -1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME)
|
||||
{
|
||||
NR_ServingCellConfigCommon_t *scc = calloc_or_fail(1, sizeof(*scc));
|
||||
@@ -1002,6 +1048,33 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf
|
||||
sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0);
|
||||
config_get(cfg, SCCsParams, sizeofArray(SCCsParams), aprefix);
|
||||
config_get(cfg, MsgASCCsParams, sizeofArray(MsgASCCsParams), aprefix);
|
||||
// NR_TDD-UL-DL-ConfigCommon pattern2 (optional IE)
|
||||
// fetch params
|
||||
struct NR_TDD_UL_DL_Pattern p2;
|
||||
paramdef_t pattern2Params[] = SCC_PATTERN2_PARAMS_DESC(p2);
|
||||
char aprefix[MAX_OPTNAME_SIZE * 2 + 8];
|
||||
sprintf(aprefix, "%s.[%i].%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0, SCC_PATTERN2_STRING_CONFIG);
|
||||
config_get(config_get_if(), pattern2Params, sizeofArray(pattern2Params), aprefix);
|
||||
// check validity
|
||||
bool is_pattern2 = false;
|
||||
for (int i = 0; i < sizeofArray(pattern2Params); i++) {
|
||||
is_pattern2 |= is_pattern2_config(pattern2Params);
|
||||
}
|
||||
|
||||
if (is_pattern2) {
|
||||
LOG_I(GNB_APP, "tdd->pattern2 present\n");
|
||||
// allocate memory
|
||||
struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon;
|
||||
tdd->pattern2 = calloc_or_fail(1, sizeof(*tdd->pattern2));
|
||||
tdd->pattern2->ext1 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern__ext1));
|
||||
tdd->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 = calloc_or_fail(1, sizeof(*tdd->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530));
|
||||
// fill in scc
|
||||
*scc->tdd_UL_DL_ConfigurationCommon->pattern2 = p2;
|
||||
AssertFatal(p2.nrofUplinkSlots ^ scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,
|
||||
"UL slots in pattern1 (%ld) and pattern2 (%ld) are mutually exclusive (e.g. DDDFUU DDDD, DDDD DDDFUU)\n",
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,
|
||||
p2.nrofUplinkSlots);
|
||||
}
|
||||
struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
|
||||
LOG_I(RRC,
|
||||
"Read in ServingCellConfigCommon (PhysCellId %d, ABSFREQSSB %d, DLBand %d, ABSFREQPOINTA %d, DLBW "
|
||||
|
||||
@@ -279,6 +279,257 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort
|
||||
return mat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the TDD period, including bitmap, in the frame structure
|
||||
*
|
||||
* This function sets the TDD period configuration for DL, UL, and mixed slots in
|
||||
* the specified frame structure instance, according to the given pattern, and
|
||||
* updates the bitmap.
|
||||
*
|
||||
* @param pattern NR_TDD_UL_DL_Pattern_t configuration containing TDD slots and symbols configuration
|
||||
* @param fs frame_structure_t pointer
|
||||
* @param curr_total_slot current position in the slot bitmap to start from
|
||||
*
|
||||
* @return Number of slots in the configured TDD period
|
||||
*/
|
||||
static uint8_t set_tdd_bmap_period(NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_config_t *pc, int8_t curr_total_slot)
|
||||
{
|
||||
int8_t n_dl_slot = pattern->nrofDownlinkSlots;
|
||||
int8_t n_ul_slot = pattern->nrofUplinkSlots;
|
||||
int8_t n_dl_symbols = pattern->nrofDownlinkSymbols;
|
||||
int8_t n_ul_symbols = pattern->nrofUplinkSymbols;
|
||||
|
||||
// Total slots in the period: if DL/UL symbols are present, is mixed slot
|
||||
const bool has_mixed_slot = (n_ul_symbols + n_dl_symbols) > 0;
|
||||
int8_t total_slot = has_mixed_slot ? n_dl_slot + n_ul_slot + 1 : n_dl_slot + n_ul_slot;
|
||||
|
||||
/** Update TDD period configuration:
|
||||
* mixed slots with DL symbols are counted as DL slots
|
||||
* mixed slots with UL symbols are counted as UL slots */
|
||||
pc->num_dl_slots += (n_dl_slot + (n_dl_symbols > 0));
|
||||
pc->num_ul_slots += (n_ul_slot + (n_ul_symbols > 0));
|
||||
|
||||
// Populate the slot bitmap for each slot in the TDD period
|
||||
for (int i = 0; i < total_slot; i++) {
|
||||
tdd_bitmap_t *bitmap = &pc->tdd_slot_bitmap[i + curr_total_slot];
|
||||
if (i < n_dl_slot)
|
||||
bitmap->slot_type = TDD_NR_DOWNLINK_SLOT;
|
||||
else if ((i == n_dl_slot) && has_mixed_slot) {
|
||||
bitmap->slot_type = TDD_NR_MIXED_SLOT;
|
||||
bitmap->num_dl_symbols = n_dl_symbols;
|
||||
bitmap->num_ul_symbols = n_ul_symbols;
|
||||
} else if (n_ul_slot)
|
||||
bitmap->slot_type = TDD_NR_UPLINK_SLOT;
|
||||
}
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"Set TDD configuration period to: %d DL slots, %d UL slots, %d slots per period (NR_TDD_UL_DL_Pattern is %d DL slots, %d "
|
||||
"UL slots, %d DL symbols, %d UL symbols)\n",
|
||||
pc->num_dl_slots,
|
||||
pc->num_ul_slots,
|
||||
total_slot,
|
||||
n_dl_slot,
|
||||
n_ul_slot,
|
||||
n_dl_symbols,
|
||||
n_ul_symbols);
|
||||
|
||||
return total_slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures TDD patterns (1 or 2) in the frame structure
|
||||
*
|
||||
* This function sets up the TDD configuration in the frame structure by applying
|
||||
* DL and UL patterns as defined in NR_TDD_UL_DL_ConfigCommon.
|
||||
* It handles both TDD pattern1 and pattern2.
|
||||
*
|
||||
* @param tdd NR_TDD_UL_DL_ConfigCommon_t pointer containing pattern1 and pattern2
|
||||
* @param fs Pointer to the frame structure to update with the configured TDD patterns.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void config_tdd_patterns(NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structure_t *fs)
|
||||
{
|
||||
int num_of_patterns = 1;
|
||||
uint8_t nb_slots_p2 = 0;
|
||||
// Reset num dl/ul slots
|
||||
tdd_period_config_t *pc = &fs->period_cfg;
|
||||
pc->num_dl_slots = 0;
|
||||
pc->num_ul_slots = 0;
|
||||
// Pattern1
|
||||
uint8_t nb_slots_p1 = set_tdd_bmap_period(&tdd->pattern1, pc, 0);
|
||||
// Pattern2
|
||||
if (tdd->pattern2) {
|
||||
num_of_patterns++;
|
||||
nb_slots_p2 = set_tdd_bmap_period(tdd->pattern2, pc, nb_slots_p1);
|
||||
}
|
||||
LOG_I(NR_MAC,
|
||||
"Configured %d TDD patterns (total slots: pattern1 = %d, pattern2 = %d)\n",
|
||||
num_of_patterns,
|
||||
nb_slots_p1,
|
||||
nb_slots_p2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the first UL slot index in period
|
||||
* @param fs frame structure
|
||||
* @param mixed indicates whether to include in the count also mixed slot with UL symbols or only full UL slot
|
||||
* @return slot index
|
||||
*/
|
||||
int get_first_ul_slot(const frame_structure_t *fs, bool mixed)
|
||||
{
|
||||
DevAssert(fs);
|
||||
|
||||
if (fs->is_tdd) {
|
||||
for (int i = 0; i < fs->numb_slots_period; i++) {
|
||||
if ((mixed && is_ul_slot(i, fs)) || fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // FDD
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of DL slots per period (full DL slots + mixed slots with DL symbols)
|
||||
*/
|
||||
int get_dl_slots_per_period(const frame_structure_t *fs)
|
||||
{
|
||||
return fs->is_tdd ? fs->period_cfg.num_dl_slots : fs->numb_slots_frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of UL slots per period (full UL slots + mixed slots with UL symbols)
|
||||
*/
|
||||
int get_ul_slots_per_period(const frame_structure_t *fs)
|
||||
{
|
||||
return fs->is_tdd ? fs->period_cfg.num_ul_slots : fs->numb_slots_frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of full UL slots per period
|
||||
* @param fs Pointer to the frame structure
|
||||
* @return Number of full UL slots
|
||||
*/
|
||||
int get_full_ul_slots_per_period(const frame_structure_t *fs)
|
||||
{
|
||||
DevAssert(fs);
|
||||
|
||||
if (!fs->is_tdd)
|
||||
return fs->numb_slots_frame;
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < fs->numb_slots_period; i++)
|
||||
if (fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT)
|
||||
count++;
|
||||
|
||||
LOG_D(NR_MAC, "Full UL slots in TDD period: %d\n", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of full DL slots per period
|
||||
* @param fs Pointer to the frame structure
|
||||
* @return Number of full DL slots
|
||||
*/
|
||||
int get_full_dl_slots_per_period(const frame_structure_t *fs)
|
||||
{
|
||||
DevAssert(fs);
|
||||
|
||||
if (!fs->is_tdd)
|
||||
return fs->numb_slots_frame;
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < fs->numb_slots_period; i++)
|
||||
if (fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_DOWNLINK_SLOT)
|
||||
count++;
|
||||
|
||||
LOG_D(NR_MAC, "Full DL slots in TDD period: %d\n", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of UL slots per frame
|
||||
*/
|
||||
int get_ul_slots_per_frame(const frame_structure_t *fs)
|
||||
{
|
||||
return fs->is_tdd ? fs->numb_period_frame * get_ul_slots_per_period(fs) : fs->numb_slots_frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the nth UL slot offset for UE index idx in a TDD period using the frame structure bitmap
|
||||
* @param fs frame structure
|
||||
* @param idx UE index
|
||||
* @param count_mixed indicates whether counting mixed slot with UL symbols (e.g. for SRS) or only full UL slots
|
||||
* @return slot index offset
|
||||
*/
|
||||
int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed)
|
||||
{
|
||||
DevAssert(fs);
|
||||
|
||||
// FDD
|
||||
if (!fs->is_tdd)
|
||||
return idx;
|
||||
|
||||
// UL slots indexes in period
|
||||
int ul_slot_idxs[fs->numb_slots_period];
|
||||
int ul_slot_count = 0;
|
||||
|
||||
/* Populate the indices of UL slots in the TDD period from the bitmap
|
||||
count also mixed slots with UL symbols if flag count_mixed is present */
|
||||
for (int i = 0; i < fs->numb_slots_period; i++) {
|
||||
if ((count_mixed && is_ul_slot(i, fs)) || fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) {
|
||||
ul_slot_idxs[ul_slot_count++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute slot index offset
|
||||
int period_idx = idx / ul_slot_count; // wrap up the count of complete TDD periods spanned by the index
|
||||
int ul_slot_idx_in_period = idx % ul_slot_count; // wrap up the UL slot index within the current TDD period
|
||||
|
||||
return ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_period;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the frame structure and the NFAPI config request
|
||||
* depending on the duplex mode. If TDD, does the TDD patterns
|
||||
* and TDD periods configuration.
|
||||
*
|
||||
* @param mu numerology
|
||||
* @param scc pointer to scc
|
||||
* @param cfg pointer to NFAPI config request
|
||||
* @param fs pointer to the frame structure to update
|
||||
*
|
||||
* @return Number of periods in frame
|
||||
*/
|
||||
static int config_frame_structure(int mu,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
nfapi_nr_config_request_scf_t *cfg,
|
||||
frame_structure_t *fs)
|
||||
{
|
||||
fs->numb_slots_frame = nr_slots_per_frame[mu];
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD) {
|
||||
cfg->tdd_table.tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG;
|
||||
cfg->num_tlv++;
|
||||
cfg->tdd_table.tdd_period.value = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon);
|
||||
LOG_D(NR_MAC, "Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period.value);
|
||||
fs->numb_period_frame = get_nb_periods_per_frame(cfg->tdd_table.tdd_period.value);
|
||||
fs->numb_slots_period = fs->numb_slots_frame / fs->numb_period_frame;
|
||||
fs->is_tdd = true;
|
||||
config_tdd_patterns(scc->tdd_UL_DL_ConfigurationCommon, fs);
|
||||
set_tdd_config_nr(cfg, fs);
|
||||
} else { // FDD
|
||||
fs->is_tdd = false;
|
||||
fs->numb_period_frame = 1;
|
||||
fs->numb_slots_period = nr_slots_per_frame[mu];
|
||||
}
|
||||
AssertFatal(fs->numb_period_frame > 0, "Frame configuration cannot be configured!\n");
|
||||
return fs->numb_period_frame;
|
||||
}
|
||||
|
||||
static void config_common(gNB_MAC_INST *nrmac,
|
||||
const nr_mac_config_t *config,
|
||||
NR_ServingCellConfigCommon_t *scc)
|
||||
@@ -317,10 +568,10 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
}
|
||||
}
|
||||
struct NR_FrequencyInfoUL *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL;
|
||||
int scs = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
frequency_range = *frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1;
|
||||
bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
frequency_range,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
|
||||
bw_index =
|
||||
get_supported_band_index(scs, frequency_range, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
|
||||
cfg->carrier_config.uplink_bandwidth.value = get_supported_bw_mhz(frequency_range, bw_index);
|
||||
cfg->carrier_config.uplink_bandwidth.tl.tag = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; // temporary
|
||||
cfg->num_tlv++;
|
||||
@@ -339,7 +590,7 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
cfg->num_tlv++;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (i == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) {
|
||||
if (i == scs) {
|
||||
cfg->carrier_config.ul_grid_size[i].value = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
cfg->carrier_config.ul_k0[i].value = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier;
|
||||
cfg->carrier_config.ul_grid_size[i].tl.tag = NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG;
|
||||
@@ -438,21 +689,15 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
prach_fd_occasion->k1.value =
|
||||
NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE)
|
||||
+ rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart
|
||||
+ (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing)
|
||||
* i);
|
||||
+ (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i);
|
||||
if (IS_SA_MODE(get_softmodem_params())) {
|
||||
prach_fd_occasion->k1.value =
|
||||
NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE)
|
||||
+ rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart
|
||||
+ (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing)
|
||||
* i);
|
||||
+ (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i);
|
||||
} else {
|
||||
prach_fd_occasion->k1.value = rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart
|
||||
+ (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing)
|
||||
* i);
|
||||
+ (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i);
|
||||
}
|
||||
prach_fd_occasion->k1.tl.tag = NFAPI_NR_CONFIG_K1_TAG;
|
||||
cfg->num_tlv++;
|
||||
@@ -572,28 +817,9 @@ static void config_common(gNB_MAC_INST *nrmac,
|
||||
cfg->num_tlv++;
|
||||
cfg->num_tlv++;
|
||||
|
||||
// TDD Table Configuration
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD) {
|
||||
cfg->tdd_table.tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG;
|
||||
cfg->num_tlv++;
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 == NULL) {
|
||||
cfg->tdd_table.tdd_period.value = scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity;
|
||||
} else {
|
||||
AssertFatal(scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL,
|
||||
"In %s: scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n",
|
||||
__FUNCTION__);
|
||||
cfg->tdd_table.tdd_period.value = *scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530;
|
||||
}
|
||||
LOG_D(NR_MAC, "Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period.value);
|
||||
int periods_per_frame = set_tdd_config_nr(cfg,
|
||||
frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing,
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots,
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols,
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,
|
||||
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols);
|
||||
|
||||
AssertFatal(periods_per_frame > 0, "TDD configuration cannot be configured\n");
|
||||
}
|
||||
// Frame structure configuration
|
||||
uint8_t mu = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
||||
config_frame_structure(mu, scc, cfg, &nrmac->frame_structure);
|
||||
|
||||
int nb_tx = config->nb_bfw[0]; // number of tx antennas
|
||||
int nb_beams = config->nb_bfw[1]; // number of beams
|
||||
@@ -691,31 +917,6 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
|
||||
|
||||
find_SSB_and_RO_available(nrmac);
|
||||
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
|
||||
int nr_slots_period = n;
|
||||
int nr_dl_slots = n;
|
||||
int nr_ulstart_slot = 0;
|
||||
if (tdd) {
|
||||
nr_dl_slots = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0);
|
||||
nr_ulstart_slot = get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols);
|
||||
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
} else {
|
||||
// if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration
|
||||
AssertFatal(nrmac->common_channels[0].frame_type == FDD,"Dynamic TDD not handled yet\n");
|
||||
}
|
||||
|
||||
for (int slot = 0; slot < n; ++slot) {
|
||||
nrmac->dlsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) < nr_dl_slots) << (slot % 64);
|
||||
nrmac->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64);
|
||||
|
||||
LOG_D(NR_MAC,
|
||||
"slot %d DL %d UL %d\n",
|
||||
slot,
|
||||
(nrmac->dlsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0,
|
||||
(nrmac->ulsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0);
|
||||
}
|
||||
|
||||
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
|
||||
NR_SCHED_LOCK(&nrmac->sched_lock);
|
||||
for (int n = 0; n < NR_NB_RA_PROC_MAX; n++) {
|
||||
|
||||
@@ -122,8 +122,49 @@ void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int
|
||||
}
|
||||
}
|
||||
|
||||
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) {
|
||||
return (bitmap >> (slot % 64)) & 0x01;
|
||||
/**
|
||||
* @brief Returns true for:
|
||||
* (1) FDD
|
||||
* (2) Mixed slot with UL symbols
|
||||
* (3) Full UL slot
|
||||
*/
|
||||
bool is_ul_slot(const slot_t slot, const frame_structure_t *fs)
|
||||
{
|
||||
if (!fs->is_tdd)
|
||||
return true;
|
||||
const tdd_period_config_t *pc = &fs->period_cfg;
|
||||
slot_t s = get_slot_idx_in_period(slot, fs);
|
||||
return ((is_mixed_slot(s, fs) && pc->tdd_slot_bitmap[s].num_ul_symbols)
|
||||
|| (pc->tdd_slot_bitmap[s].slot_type == TDD_NR_UPLINK_SLOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true for:
|
||||
* (1) FDD
|
||||
* (2) Mixed slot with DL symbols
|
||||
* (3) Full DL slot
|
||||
*/
|
||||
bool is_dl_slot(const slot_t slot, const frame_structure_t *fs)
|
||||
{
|
||||
if (!fs->is_tdd)
|
||||
return true;
|
||||
const tdd_period_config_t *pc = &fs->period_cfg;
|
||||
slot_t s = get_slot_idx_in_period(slot, fs);
|
||||
return ((is_mixed_slot(s, fs) && pc->tdd_slot_bitmap[s].num_dl_symbols)
|
||||
|| (pc->tdd_slot_bitmap[s].slot_type == TDD_NR_DOWNLINK_SLOT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true for:
|
||||
* (1) Mixed slot with DL and/or UL symbols
|
||||
*/
|
||||
bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs)
|
||||
{
|
||||
if (!fs->is_tdd)
|
||||
return false;
|
||||
slot_t s = get_slot_idx_in_period(slot, fs);
|
||||
const tdd_period_config_t *pc = &fs->period_cfg;
|
||||
return pc->tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT;
|
||||
}
|
||||
|
||||
/* the structure nfapi_nr_ul_tti_request_t is very big, let's copy only what is necessary */
|
||||
|
||||
@@ -276,7 +276,7 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon,
|
||||
|
||||
UL_tti_req->SFN = msgA_pusch_frame;
|
||||
UL_tti_req->Slot = msgA_pusch_slot;
|
||||
AssertFatal(is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[msgA_pusch_slot / 64], msgA_pusch_slot),
|
||||
AssertFatal(is_ul_slot(msgA_pusch_slot, &nr_mac->frame_structure),
|
||||
"Slot %d is not an Uplink slot, invalid msgA_PUSCH_TimeDomainOffset_r16 %ld\n",
|
||||
msgA_pusch_slot,
|
||||
msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16);
|
||||
@@ -374,7 +374,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
|
||||
nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index];
|
||||
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
|
||||
|
||||
if (is_nr_UL_slot(scc->tdd_UL_DL_ConfigurationCommon, slotP, cc->frame_type)) {
|
||||
if (is_ul_slot(slotP, &RC.nrmac[module_idP]->frame_structure)) {
|
||||
const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric;
|
||||
uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
|
||||
uint8_t N_dur, N_t_slot, start_symbol = 0, N_RA_slot;
|
||||
@@ -785,7 +785,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
const int sched_frame = (frame + (slot + K2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER;
|
||||
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
|
||||
|
||||
if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) {
|
||||
if (is_ul_slot(sched_slot, &nr_mac->frame_structure)) {
|
||||
const int n_slots_frame = nr_slots_per_frame[mu];
|
||||
NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, n_slots_frame);
|
||||
if (beam_ul.idx < 0)
|
||||
@@ -950,47 +950,44 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP,
|
||||
ra->ra_state = nrRA_WAIT_Msg3;
|
||||
ra->Msg3_frame = sched_frame;
|
||||
ra->Msg3_slot = sched_slot;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_feasible_msg3_tda(frame_type_t frame_type,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc,
|
||||
int mu_delta,
|
||||
uint64_t ulsch_slot_bitmap[3],
|
||||
const NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list,
|
||||
int slots_per_frame,
|
||||
int frame,
|
||||
int slot,
|
||||
NR_RA_t *ra,
|
||||
NR_beam_info_t *beam_info,
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd)
|
||||
const frame_structure_t *fs)
|
||||
{
|
||||
DevAssert(tda_list != NULL);
|
||||
|
||||
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
|
||||
int tdd_period_slot = tdd ? slots_per_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : slots_per_frame;
|
||||
int slots_per_frame = fs->numb_slots_frame;
|
||||
for (int i = 0; i < tda_list->list.count; i++) {
|
||||
// check if it is UL
|
||||
long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset;
|
||||
int abs_slot = slot + k2 + mu_delta;
|
||||
int temp_frame = (frame + (abs_slot / slots_per_frame)) & 1023;
|
||||
int temp_slot = abs_slot % slots_per_frame; // msg3 slot according to 8.3 in 38.213
|
||||
if ((frame_type == TDD) && !is_xlsch_in_slot(ulsch_slot_bitmap[temp_slot / 64], temp_slot))
|
||||
if (fs->is_tdd && !is_ul_slot(temp_slot, fs))
|
||||
continue;
|
||||
|
||||
const tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap;
|
||||
int s = get_slot_idx_in_period(temp_slot, fs);
|
||||
// check if enough symbols in case of mixed slot
|
||||
bool is_mixed = false;
|
||||
if (frame_type == TDD) {
|
||||
bool has_mixed = tdd->nrofUplinkSymbols != 0 || tdd->nrofDownlinkSymbols != 0;
|
||||
is_mixed = has_mixed && ((temp_slot % tdd_period_slot) == tdd->nrofDownlinkSlots);
|
||||
}
|
||||
bool is_mixed = is_mixed_slot(s, fs);
|
||||
// if the mixed slot has not enough symbols, skip
|
||||
if (is_mixed && tdd->nrofUplinkSymbols < 3)
|
||||
if (is_mixed && tdd_slot_bitmap[s].num_ul_symbols < 3)
|
||||
continue;
|
||||
|
||||
uint16_t slot_mask = is_mixed ? SL_to_bitmap(14 - tdd->nrofUplinkSymbols, tdd->nrofUplinkSymbols) : 0x3fff;
|
||||
uint16_t slot_mask =
|
||||
is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - tdd_slot_bitmap[s].num_ul_symbols,
|
||||
tdd_slot_bitmap[s].num_ul_symbols)
|
||||
: 0x3fff;
|
||||
long startSymbolAndLength = tda_list->list.array[i]->startSymbolAndLength;
|
||||
int start, nr;
|
||||
SLIV2SL(startSymbolAndLength, &start, &nr);
|
||||
@@ -1385,7 +1382,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
|
||||
|
||||
// no DL -> cannot send Msg2
|
||||
if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) {
|
||||
if (!is_dl_slot(slotP, &nr_mac->frame_structure)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1413,18 +1410,14 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
return;
|
||||
|
||||
const NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP;
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
bool ret = get_feasible_msg3_tda(cc->frame_type,
|
||||
scc,
|
||||
bool ret = get_feasible_msg3_tda(scc,
|
||||
DELTA[ul_bwp->scs],
|
||||
nr_mac->ulsch_slot_bitmap,
|
||||
ul_bwp->tdaList_Common,
|
||||
nr_slots_per_frame[ul_bwp->scs],
|
||||
frameP,
|
||||
slotP,
|
||||
ra,
|
||||
&nr_mac->beam_info,
|
||||
tdd);
|
||||
&nr_mac->frame_structure);
|
||||
if (!ret || ra->Msg3_tda_id > 15) {
|
||||
LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", ra->rnti, frameP, slotP);
|
||||
reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam);
|
||||
@@ -1453,7 +1446,7 @@ static void nr_generate_Msg2(module_id_t module_idP,
|
||||
AssertFatal(coreset, "Coreset cannot be null for RA-Msg2\n");
|
||||
const int coresetid = coreset->controlResourceSetId;
|
||||
// Calculate number of symbols
|
||||
int time_domain_assignment = get_dl_tda(nr_mac, scc, slotP);
|
||||
int time_domain_assignment = get_dl_tda(nr_mac, slotP);
|
||||
int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1;
|
||||
NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp,
|
||||
ss->searchSpaceType->present,
|
||||
@@ -1949,8 +1942,8 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP,
|
||||
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
|
||||
NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP;
|
||||
|
||||
// if it is a DL slot, if the RA is in MSG4 state
|
||||
if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) {
|
||||
// if it is a DL slot, if the RA is in MSG4 state
|
||||
if (is_dl_slot(slotP, &nr_mac->frame_structure)) {
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_SearchSpace_t *ss = ra->ra_ss;
|
||||
const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4";
|
||||
@@ -2029,7 +2022,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP,
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t time_domain_assignment = get_dl_tda(nr_mac, scc, slotP);
|
||||
uint8_t time_domain_assignment = get_dl_tda(nr_mac, slotP);
|
||||
int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1;
|
||||
NR_tda_info_t msg4_tda = get_dl_tda_info(dl_bwp,
|
||||
ss->searchSpaceType->present,
|
||||
|
||||
@@ -52,20 +52,22 @@
|
||||
#define WORD 32
|
||||
//#define SIZE_OF_POINTER sizeof (void *)
|
||||
|
||||
int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot)
|
||||
int get_dl_tda(const gNB_MAC_INST *nrmac, int slot)
|
||||
{
|
||||
/* we assume that this function is mutex-protected from outside */
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||
const frame_structure_t *fs = &nrmac->frame_structure;
|
||||
|
||||
// Use special TDA in case of CSI-RS
|
||||
if(nrmac->UE_info.sched_csirs > 0)
|
||||
if (nrmac->UE_info.sched_csirs > 0)
|
||||
return 1;
|
||||
|
||||
if (tdd && tdd->nrofDownlinkSymbols > 1) { // if there is a mixed slot where we can transmit DL
|
||||
const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1;
|
||||
if ((slot % nr_slots_period) == tdd->nrofDownlinkSlots)
|
||||
if (fs->is_tdd) {
|
||||
int s = get_slot_idx_in_period(slot, fs);
|
||||
// if there is a mixed slot where we can transmit DL
|
||||
const tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap;
|
||||
if (tdd_slot_bitmap[s].num_dl_symbols > 1 && is_mixed_slot(s, fs)) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0; // if FDD or not mixed slot in TDD, for now use default TDA
|
||||
}
|
||||
@@ -447,7 +449,7 @@ static bool allocate_dl_retransmission(module_id_t module_id,
|
||||
int pm_index = (curInfo->nrOfLayers < retInfo->nrOfLayers) ? curInfo->pm_index : retInfo->pm_index;
|
||||
|
||||
const int coresetid = sched_ctrl->coreset->controlResourceSetId;
|
||||
const int tda = get_dl_tda(nr_mac, scc, slot);
|
||||
const int tda = get_dl_tda(nr_mac, slot);
|
||||
AssertFatal(tda >= 0,"Unable to find PDSCH time domain allocation in list\n");
|
||||
|
||||
/* Check first whether the old TDA can be reused
|
||||
@@ -761,7 +763,7 @@ static void pf_dl(module_id_t module_id,
|
||||
sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head;
|
||||
|
||||
/* MCS has been set above */
|
||||
sched_pdsch->time_domain_allocation = get_dl_tda(mac, scc, slot);
|
||||
sched_pdsch->time_domain_allocation = get_dl_tda(mac, slot);
|
||||
AssertFatal(sched_pdsch->time_domain_allocation>=0,"Unable to find PDSCH time domain allocation in list\n");
|
||||
|
||||
const int coresetid = sched_ctrl->coreset->controlResourceSetId;
|
||||
@@ -955,7 +957,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY,
|
||||
"this function should be called with the scheduler mutex locked\n");
|
||||
|
||||
if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot))
|
||||
if (!is_dl_slot(slot, &gNB_mac->frame_structure))
|
||||
return;
|
||||
|
||||
/* PREPROCESSOR */
|
||||
|
||||
@@ -40,6 +40,14 @@
|
||||
// #define UL_HARQ_PRINT
|
||||
// #define ENABLE_MAC_PAYLOAD_DEBUG 1
|
||||
|
||||
/* This function checks whether the given Dl/UL slot is set
|
||||
in the input bitmap, which is a mask indicating in which
|
||||
slot to transmit (among those available in the TDD configuration) */
|
||||
static bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot)
|
||||
{
|
||||
return (bitmap >> (slot % 64)) & 0x01;
|
||||
}
|
||||
|
||||
uint32_t target_dl_mcs = 9;
|
||||
uint32_t target_dl_Nl = 1;
|
||||
uint32_t target_dl_bw = 50;
|
||||
@@ -64,7 +72,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
|
||||
return;
|
||||
}
|
||||
|
||||
const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot);
|
||||
const int tda = get_dl_tda(RC.nrmac[module_id], slot);
|
||||
NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp,
|
||||
sched_ctrl->search_space->searchSpaceType->present,
|
||||
tda,
|
||||
@@ -242,7 +250,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
|
||||
sched_ctrl->coreset->controlResourceSetId,
|
||||
sched_ctrl->search_space->searchSpaceType->present,
|
||||
TYPE_C_RNTI_);
|
||||
const int temp_tda = get_ul_tda(nr_mac, scc, frame, slot);
|
||||
const int temp_tda = get_ul_tda(nr_mac, frame, slot);
|
||||
if (temp_tda < 0)
|
||||
return false;
|
||||
AssertFatal(temp_tda < tdaList->list.count,
|
||||
@@ -252,7 +260,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_
|
||||
int K2 = get_K2(tdaList, temp_tda, mu, scc);
|
||||
const int sched_frame = (frame + (slot + K2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER;
|
||||
const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
|
||||
const int tda = get_ul_tda(nr_mac, scc, sched_frame, sched_slot);
|
||||
const int tda = get_ul_tda(nr_mac, sched_frame, sched_slot);
|
||||
if (tda < 0)
|
||||
return false;
|
||||
AssertFatal(tda < tdaList->list.count,
|
||||
|
||||
@@ -2160,6 +2160,31 @@ int get_ulbw_tbslbrm(int scc_bwpsize, const NR_ServingCellConfig_t *servingCellC
|
||||
return bw;
|
||||
}
|
||||
|
||||
static void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl,
|
||||
const NR_UE_UL_BWP_t *ul_bwp,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const frame_structure_t *fs)
|
||||
{
|
||||
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
const int n_ul_slots_period = get_ul_slots_per_period(fs);
|
||||
|
||||
// PUCCH list size is given by the number of UL slots in the PUCCH period
|
||||
// the length PUCCH period is determined by max_fb_time since we may need to prepare PUCCH for ACK/NACK max_fb_time slots ahead
|
||||
const int list_size = n_ul_slots_period << (int)ceil(log2((ul_bwp->max_fb_time + NTN_gNB_Koffset) / fs->numb_slots_period + 1));
|
||||
|
||||
if (!sched_ctrl->sched_pucch) {
|
||||
sched_ctrl->sched_pucch = calloc_or_fail(list_size, sizeof(*sched_ctrl->sched_pucch));
|
||||
sched_ctrl->sched_pucch_size = list_size;
|
||||
} else if (list_size > sched_ctrl->sched_pucch_size) {
|
||||
sched_ctrl->sched_pucch = realloc(sched_ctrl->sched_pucch, list_size * sizeof(*sched_ctrl->sched_pucch));
|
||||
for (int i = sched_ctrl->sched_pucch_size; i < list_size; i++) {
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[i];
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
sched_ctrl->sched_pucch_size = list_size;
|
||||
}
|
||||
}
|
||||
|
||||
// main function to configure parameters of current BWP
|
||||
void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
@@ -2405,7 +2430,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
NR_UL_DCI_FORMAT_0_0;
|
||||
|
||||
set_max_fb_time(UL_BWP, DL_BWP);
|
||||
set_sched_pucch_list(sched_ctrl, UL_BWP, scc);
|
||||
set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure);
|
||||
}
|
||||
|
||||
if(ra) {
|
||||
@@ -2537,32 +2562,6 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
|
||||
return (UE);
|
||||
}
|
||||
|
||||
void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl,
|
||||
const NR_UE_UL_BWP_t *ul_bwp,
|
||||
const NR_ServingCellConfigCommon_t *scc)
|
||||
{
|
||||
const int NTN_gNB_Koffset = get_NTN_Koffset(scc);
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
|
||||
const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame;
|
||||
// PUCCH list size is given by the number of UL slots in the PUCCH period
|
||||
// the length PUCCH period is determined by max_fb_time since we may need to prepare PUCCH for ACK/NACK max_fb_time slots ahead
|
||||
const int list_size = n_ul_slots_period << (int)ceil(log2((ul_bwp->max_fb_time + NTN_gNB_Koffset) / nr_slots_period + 1));
|
||||
if(!sched_ctrl->sched_pucch) {
|
||||
sched_ctrl->sched_pucch = calloc(list_size, sizeof(*sched_ctrl->sched_pucch));
|
||||
sched_ctrl->sched_pucch_size = list_size;
|
||||
}
|
||||
else if (list_size > sched_ctrl->sched_pucch_size) {
|
||||
sched_ctrl->sched_pucch = realloc(sched_ctrl->sched_pucch, list_size * sizeof(*sched_ctrl->sched_pucch));
|
||||
for(int i=sched_ctrl->sched_pucch_size; i<list_size; i++){
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[i];
|
||||
memset(curr_pucch, 0, sizeof(*curr_pucch));
|
||||
}
|
||||
sched_ctrl->sched_pucch_size = list_size;
|
||||
}
|
||||
}
|
||||
|
||||
void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl)
|
||||
{
|
||||
free(sched_ctrl->sched_pucch);
|
||||
|
||||
@@ -133,23 +133,35 @@ static const int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = {
|
||||
-30 // 10 - 15
|
||||
};
|
||||
|
||||
static int get_pucch_index(int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_pucch_size)
|
||||
static int get_pucch_index(int frame, int slot, const frame_structure_t *fs, int sched_pucch_size)
|
||||
{
|
||||
// PUCCH structures are indexed by slot in the PUCCH period determined by sched_pucch_size number of UL slots
|
||||
// this functions return the index to the structure for slot passed to the function
|
||||
const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0;
|
||||
const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame;
|
||||
const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
const int n_ul_slots_frame = n_slots_frame / nr_slots_period * n_ul_slots_period;
|
||||
const int n_ul_slots_period = get_ul_slots_per_period(fs);
|
||||
const int n_ul_slots_frame = get_ul_slots_per_frame(fs);
|
||||
// (frame * n_ul_slots_frame) adds up the number of UL slots in the previous frames
|
||||
const int frame_start = frame * n_ul_slots_frame;
|
||||
// ((slot / nr_slots_period) * n_ul_slots_period) adds up the number of UL slots in the previous TDD periods of this frame
|
||||
const int ul_period_start = (slot / nr_slots_period) * n_ul_slots_period;
|
||||
const int ul_period_start = (slot / fs->numb_slots_period) * n_ul_slots_period;
|
||||
// ((slot % nr_slots_period) - first_ul_slot_period) gives the progressive number of the slot in this TDD period
|
||||
const int ul_period_slot = (slot % nr_slots_period) - first_ul_slot_period;
|
||||
int ul_period_slot = -1;
|
||||
for (int i = 0; i <= slot % fs->numb_slots_period; i++) {
|
||||
if (is_ul_slot(i, fs)) {
|
||||
ul_period_slot++;
|
||||
}
|
||||
}
|
||||
LOG_D(NR_MAC,
|
||||
"PUCCH frame/slot: request %4d.%2d:frame_start %d,ul_period_start %d, ul_period_slot %d pucch_index %d pucch_size %d "
|
||||
"scheduling PUCCH\n",
|
||||
frame,
|
||||
slot,
|
||||
frame_start,
|
||||
ul_period_start,
|
||||
ul_period_slot,
|
||||
((frame_start + ul_period_start + ul_period_slot) % sched_pucch_size),
|
||||
sched_pucch_size);
|
||||
// the sum gives the index of current UL slot in the frame which is normalized wrt sched_pucch_size
|
||||
return (frame_start + ul_period_start + ul_period_slot) % sched_pucch_size;
|
||||
|
||||
}
|
||||
|
||||
void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP)
|
||||
@@ -157,17 +169,12 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP)
|
||||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||||
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
|
||||
|
||||
if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slotP / 64], slotP))
|
||||
if (!is_ul_slot(slotP, &nrmac->frame_structure))
|
||||
return;
|
||||
|
||||
UE_iterator(nrmac->UE_info.list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
|
||||
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[0].ServingCellConfigCommon;
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||
const int pucch_index = get_pucch_index(frameP, slotP, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
|
||||
const int pucch_index = get_pucch_index(frameP, slotP, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
|
||||
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index];
|
||||
if (!curr_pucch->active)
|
||||
continue;
|
||||
@@ -236,7 +243,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, sub_frame_t slot)
|
||||
if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0)
|
||||
continue;
|
||||
|
||||
AssertFatal(is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[sched_slot / 64], sched_slot), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot);
|
||||
AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot);
|
||||
LOG_D(NR_MAC, "CSI reporting in frame %d slot %d CSI report ID %ld\n", sched_frame, sched_slot, csirep->reportConfigId);
|
||||
|
||||
const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
|
||||
@@ -248,9 +255,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, sub_frame_t slot)
|
||||
AssertFatal(res_index < n,
|
||||
"CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource);
|
||||
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||
const int pucch_index = get_pucch_index(sched_frame, sched_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
|
||||
const int pucch_index = get_pucch_index(sched_frame, sched_slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
|
||||
AssertFatal(curr_pucch->active == false, "CSI structure is scheduled in advance. It should be free!\n");
|
||||
curr_pucch->r_pucch = -1;
|
||||
@@ -998,10 +1003,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
const int minfbtime = mac->radio_config.minRXTXTIME + NTN_gNB_Koffset;
|
||||
const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
AssertFatal(tdd || mac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||
const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0;
|
||||
const frame_structure_t *fs = &mac->frame_structure;
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
|
||||
@@ -1022,11 +1024,14 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac,
|
||||
continue;
|
||||
const int pucch_slot = (slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) % n_slots_frame;
|
||||
// check if the slot is UL
|
||||
if(pucch_slot%nr_slots_period < first_ul_slot_period)
|
||||
continue;
|
||||
if (fs->is_tdd) {
|
||||
int mod_slot = pucch_slot % fs->numb_slots_period;
|
||||
if (!is_ul_slot(mod_slot, fs))
|
||||
continue;
|
||||
}
|
||||
const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER;
|
||||
// we store PUCCH resources according to slot, TDD configuration and size of the vector containing PUCCH structures
|
||||
const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
|
||||
const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, &mac->frame_structure, sched_ctrl->sched_pucch_size);
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
|
||||
if (curr_pucch->active &&
|
||||
curr_pucch->frame == pucch_frame &&
|
||||
@@ -1125,7 +1130,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
|
||||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||||
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
|
||||
|
||||
if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot))
|
||||
if (!is_ul_slot(slot, &nrmac->frame_structure))
|
||||
return;
|
||||
const int CC_id = 0;
|
||||
UE_iterator(nrmac->UE_info.list, UE) {
|
||||
@@ -1164,10 +1169,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
|
||||
}
|
||||
AssertFatal(idx > -1, "SR resource not found among PUCCH resources");
|
||||
|
||||
const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
AssertFatal(tdd || nrmac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||
const int pucch_index = get_pucch_index(SFN, slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size);
|
||||
const int pucch_index = get_pucch_index(SFN, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
|
||||
NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index];
|
||||
|
||||
if (curr_pucch->active && curr_pucch->frame == SFN && curr_pucch->ul_slot == slot && curr_pucch->resource_indicator == idx)
|
||||
|
||||
@@ -40,19 +40,21 @@
|
||||
|
||||
//#define SRS_IND_DEBUG
|
||||
|
||||
int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot)
|
||||
int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot)
|
||||
{
|
||||
/* we assume that this function is mutex-protected from outside */
|
||||
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
|
||||
|
||||
/* there is a mixed slot only when in TDD */
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n");
|
||||
frame_structure_t *fs = &nrmac->frame_structure;
|
||||
|
||||
if (tdd && tdd->nrofUplinkSymbols > 1) { // if there is uplink symbols in mixed slot
|
||||
const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1;
|
||||
if ((slot % nr_slots_period) == tdd->nrofDownlinkSlots)
|
||||
if (fs->is_tdd) {
|
||||
// if there is uplink symbols in mixed slot
|
||||
int s = get_slot_idx_in_period(slot, fs);
|
||||
tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap;
|
||||
if ((tdd_slot_bitmap[s].num_ul_symbols > 1) && is_mixed_slot(s, fs)) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid slots with the SRS
|
||||
@@ -1519,25 +1521,21 @@ long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList,
|
||||
return 3 + NTN_gNB_Koffset;
|
||||
}
|
||||
|
||||
static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc, int CC_id, NR_UE_info_t* UE, frame_t frame, sub_frame_t slot, uint32_t ulsch_max_frame_inactivity)
|
||||
static bool nr_UE_is_to_be_scheduled(const frame_structure_t *fs,
|
||||
NR_UE_info_t *UE,
|
||||
frame_t frame,
|
||||
sub_frame_t slot,
|
||||
uint32_t ulsch_max_frame_inactivity)
|
||||
{
|
||||
const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
|
||||
const int n = fs->numb_slots_frame;
|
||||
const int now = frame * n + slot;
|
||||
|
||||
const NR_UE_sched_ctrl_t *sched_ctrl =&UE->UE_sched_ctrl;
|
||||
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd =
|
||||
scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
int num_slots_per_period;
|
||||
int last_ul_slot;
|
||||
if (tdd) { // Force the default transmission in a full slot as early as possible in the UL portion of TDD period (last_ul_slot)
|
||||
num_slots_per_period = n / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
|
||||
last_ul_slot = 1 + tdd->nrofDownlinkSlots;
|
||||
} else {
|
||||
num_slots_per_period = n;
|
||||
last_ul_slot = sched_ctrl->last_ul_slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the default transmission in a full slot as early
|
||||
* as possible in the UL portion of TDD period (last_ul_slot) */
|
||||
int num_slots_per_period = fs->numb_slots_period;
|
||||
int last_ul_slot = fs->is_tdd ? get_first_ul_slot(fs, false) : sched_ctrl->last_ul_slot;
|
||||
const int last_ul_sched = sched_ctrl->last_ul_frame * n + last_ul_slot;
|
||||
const int diff = (now - last_ul_sched + 1024 * n) % (1024 * n);
|
||||
/* UE is to be scheduled if
|
||||
@@ -1856,7 +1854,7 @@ static void pf_ul(module_id_t module_id,
|
||||
LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n", UE->rnti, sched_pusch->ul_harq_pid);
|
||||
if (sched_pusch->ul_harq_pid >= 0) {
|
||||
/* Allocate retransmission*/
|
||||
const int tda = get_ul_tda(nrmac, scc, sched_frame, sched_slot);
|
||||
const int tda = get_ul_tda(nrmac, sched_frame, sched_slot);
|
||||
bool r = allocate_ul_retransmission(nrmac,
|
||||
frame,
|
||||
slot,
|
||||
@@ -1893,7 +1891,11 @@ static void pf_ul(module_id_t module_id,
|
||||
|
||||
const int B = max(0, sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes);
|
||||
/* preprocessor computed sched_frame/sched_slot */
|
||||
const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_frame, sched_slot, nrmac->ulsch_max_frame_inactivity);
|
||||
const bool do_sched = nr_UE_is_to_be_scheduled(&nrmac->frame_structure,
|
||||
UE,
|
||||
sched_frame,
|
||||
sched_slot,
|
||||
nrmac->ulsch_max_frame_inactivity);
|
||||
|
||||
LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n", UE->rnti, do_sched ? "yes" : "no");
|
||||
if ((B == 0 && !do_sched) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) {
|
||||
@@ -1933,7 +1935,7 @@ static void pf_ul(module_id_t module_id,
|
||||
}
|
||||
|
||||
sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1;
|
||||
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, scc, sched_frame, sched_slot);
|
||||
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot);
|
||||
sched_pusch->tda_info = get_ul_tda_info(current_BWP,
|
||||
sched_ctrl->coreset->controlResourceSetId,
|
||||
sched_ctrl->search_space->searchSpaceType->present,
|
||||
@@ -2086,7 +2088,7 @@ static void pf_ul(module_id_t module_id,
|
||||
|
||||
|
||||
sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1;
|
||||
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, scc, sched_frame, sched_slot);
|
||||
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot);
|
||||
sched_pusch->tda_info = get_ul_tda_info(current_BWP,
|
||||
sched_ctrl->coreset->controlResourceSetId,
|
||||
sched_ctrl->search_space->searchSpaceType->present,
|
||||
@@ -2215,7 +2217,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_fram
|
||||
const int K2 = nr_mac->radio_config.minRXTXTIME + get_NTN_Koffset(scc);
|
||||
const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER;
|
||||
const int sched_slot = (slot + K2) % slots_frame;
|
||||
if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot))
|
||||
if (!is_ul_slot(sched_slot, &nr_mac->frame_structure))
|
||||
return false;
|
||||
|
||||
int num_beams = nr_mac->beam_info.beam_allocation ? nr_mac->beam_info.beams_per_period : 1;
|
||||
@@ -2274,7 +2276,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n
|
||||
|
||||
/* Uplink data ONLY can be scheduled when the current slot is downlink slot,
|
||||
* because we have to schedule the DCI0 first before schedule uplink data */
|
||||
if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slot / 64], slot)) {
|
||||
if (!is_dl_slot(slot, &nr_mac->frame_structure)) {
|
||||
LOG_D(NR_MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,14 @@ void set_cset_offset(uint16_t);
|
||||
void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers);
|
||||
int get_NTN_Koffset(const NR_ServingCellConfigCommon_t *scc);
|
||||
|
||||
int get_first_ul_slot(const frame_structure_t *fs, bool mixed);
|
||||
int get_ul_slots_per_period(const frame_structure_t *fs);
|
||||
int get_ul_slots_per_frame(const frame_structure_t *fs);
|
||||
int get_dl_slots_per_period(const frame_structure_t *fs);
|
||||
int get_full_ul_slots_per_period(const frame_structure_t *fs);
|
||||
int get_full_dl_slots_per_period(const frame_structure_t *fs);
|
||||
int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed);
|
||||
|
||||
void mac_top_init_gNB(ngran_node_t node_type,
|
||||
NR_ServingCellConfigCommon_t *scc,
|
||||
NR_ServingCellConfig_t *scd,
|
||||
@@ -344,7 +352,9 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
|
||||
|
||||
int binomial(int n, int k);
|
||||
|
||||
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot);
|
||||
bool is_ul_slot(const slot_t slot, const frame_structure_t *fs);
|
||||
bool is_dl_slot(const slot_t slot, const frame_structure_t *fs);
|
||||
bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs);
|
||||
|
||||
/* \brief Function to indicate a received SDU on ULSCH.
|
||||
@param Mod_id Instance ID of gNB
|
||||
@@ -406,13 +416,10 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx);
|
||||
|
||||
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format);
|
||||
|
||||
void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl,
|
||||
const NR_UE_UL_BWP_t *ul_bwp,
|
||||
const NR_ServingCellConfigCommon_t *scc);
|
||||
void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl);
|
||||
|
||||
int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot);
|
||||
int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot);
|
||||
int get_dl_tda(const gNB_MAC_INST *nrmac, int slot);
|
||||
int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot);
|
||||
|
||||
int get_cce_index(const gNB_MAC_INST *nrmac,
|
||||
const int CC_id,
|
||||
|
||||
@@ -905,13 +905,10 @@ typedef struct gNB_MAC_INST_s {
|
||||
|
||||
NR_beam_info_t beam_info;
|
||||
|
||||
/// bitmap of DLSCH slots, can hold up to 160 slots
|
||||
uint64_t dlsch_slot_bitmap[3];
|
||||
/// bitmap of ULSCH slots, can hold up to 160 slots
|
||||
uint64_t ulsch_slot_bitmap[3];
|
||||
|
||||
/// maximum number of slots before a UE will be scheduled ULSCH automatically
|
||||
uint32_t ulsch_max_frame_inactivity;
|
||||
/// instance of the frame structure configuration
|
||||
frame_structure_t frame_structure;
|
||||
|
||||
/// DL preprocessor for differentiated scheduling
|
||||
nr_pp_impl_dl pre_processor_dl;
|
||||
|
||||
+163
-75
@@ -49,7 +49,9 @@
|
||||
#include "constr_TYPE.h"
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "oai_asn1.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
|
||||
#include "openair3/UTILS/conversions.h"
|
||||
#include "uper_decoder.h"
|
||||
#include "uper_encoder.h"
|
||||
@@ -312,9 +314,13 @@ static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc)
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static int set_ideal_period(const int n_slots_period, const int n_ul_slots_period)
|
||||
static int set_ideal_period(bool is_csi)
|
||||
{
|
||||
return MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE (RSRP and RI-PMI-CQI)
|
||||
const frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
|
||||
const int nb_slots_per_period = fs->numb_slots_period;
|
||||
const int n_ul_slots_per_period = get_ul_slots_per_period(fs); // full UL + mixed with UL symbols
|
||||
// 2 reports per UE (RSRP and RI-PMI-CQI)
|
||||
return is_csi ? MAX_MOBILES_PER_GNB * 2 * nb_slots_per_period / n_ul_slots_per_period : nb_slots_per_period * MAX_MOBILES_PER_GNB;
|
||||
}
|
||||
|
||||
static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0,
|
||||
@@ -389,16 +395,6 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco
|
||||
nzpcsirs0->aperiodicTriggeringOffset = NULL;
|
||||
nzpcsirs0->trs_Info = NULL;
|
||||
asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpcsirs0);
|
||||
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = servingcellconfigcommon->tdd_UL_DL_ConfigurationCommon ?
|
||||
&servingcellconfigcommon->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
|
||||
const int n_slots_frame = slotsperframe[*servingcellconfigcommon->ssbSubcarrierSpacing];
|
||||
const int nb_slots_per_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity): n_slots_frame;
|
||||
const int nb_dl_slots_period = tdd ? tdd->nrofDownlinkSlots : n_slots_frame;
|
||||
const int n_ul_slots_period = tdd ? (tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0)) : n_slots_frame;
|
||||
const int ideal_period = set_ideal_period(nb_slots_per_period, n_ul_slots_period); // same periodicity as CSI measurement report
|
||||
|
||||
if(!csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)
|
||||
csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList));
|
||||
NR_NZP_CSI_RS_Resource_t *nzpcsi0 = calloc(1,sizeof(*nzpcsi0));
|
||||
@@ -447,7 +443,12 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco
|
||||
nzpcsi0->powerControlOffsetSS = calloc(1,sizeof(*nzpcsi0->powerControlOffsetSS));
|
||||
*nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0;
|
||||
nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId;
|
||||
set_csirs_periodicity(nzpcsi0, id, ideal_period, nb_slots_per_period, nb_dl_slots_period);
|
||||
|
||||
const int ideal_period = set_ideal_period(true); // same periodicity as CSI measurement report
|
||||
const frame_structure_t *fs = &(RC.nrmac[0]->frame_structure);
|
||||
const int nb_dl_slots_period = get_full_dl_slots_per_period(fs); // full DL slots
|
||||
set_csirs_periodicity(nzpcsi0, id, ideal_period, fs->numb_slots_period, nb_dl_slots_period);
|
||||
|
||||
nzpcsi0->qcl_InfoPeriodicCSI_RS = calloc(1,sizeof(*nzpcsi0->qcl_InfoPeriodicCSI_RS));
|
||||
*nzpcsi0->qcl_InfoPeriodicCSI_RS = 0;
|
||||
asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpcsi0);
|
||||
@@ -628,15 +629,12 @@ long rrc_get_max_nr_csrs(const int max_rbs, const long b_SRS) {
|
||||
static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(const NR_ServingCellConfigCommon_t *scc,
|
||||
const int uid)
|
||||
{
|
||||
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
|
||||
int offset = get_ul_slot_offset(fs, uid, false); // only full UL slots for SRS
|
||||
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing];
|
||||
const int ul_slots_period = tdd ? tdd->nrofUplinkSlots : n_slots_frame;
|
||||
const int n_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
const int first_full_ul_slot = n_slots_period - ul_slots_period;
|
||||
const int ideal_period = n_slots_period * MAX_MOBILES_PER_GNB;
|
||||
const int offset = first_full_ul_slot + (uid % ul_slots_period) + (n_slots_period * (uid / ul_slots_period));
|
||||
AssertFatal(offset < 2560, "Cannot allocate SRS configuration for uid %d, not enough resources\n", uid);
|
||||
const int ideal_period = set_ideal_period(false);
|
||||
|
||||
struct NR_SRS_Resource__resourceType__periodic *periodic_srs = calloc(1,sizeof(*periodic_srs));
|
||||
if (ideal_period < 5) {
|
||||
periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl4;
|
||||
@@ -907,7 +905,17 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc
|
||||
if(frame_type==TDD) {
|
||||
// TDD
|
||||
if(tdd_UL_DL_ConfigurationCommon) {
|
||||
int dl_symb = tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols;
|
||||
int dl_symb = 0;
|
||||
if (tdd_UL_DL_ConfigurationCommon->pattern2 && tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols)
|
||||
AssertFatal(tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols == tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols,
|
||||
"nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n",
|
||||
tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols,
|
||||
tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols);
|
||||
if (tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols != 0) {
|
||||
dl_symb = tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols;
|
||||
} else if (tdd_UL_DL_ConfigurationCommon->pattern2) {
|
||||
dl_symb = tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols;
|
||||
}
|
||||
if(dl_symb > 1) {
|
||||
// mixed slot TDA with TDA index 2
|
||||
struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation2 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
|
||||
@@ -919,6 +927,94 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc
|
||||
}
|
||||
}
|
||||
|
||||
const float tdd_ms_period_pattern[] = {0.5, 0.625, 1.0, 1.25, 2.0, 2.5, 5.0, 10.0};
|
||||
const float tdd_ms_period_ext[] = {3.0, 4.0};
|
||||
|
||||
/**
|
||||
* @brief Retrieves the periodicity in milliseconds for the given TDD pattern
|
||||
* depending on the presence of the extension
|
||||
* @param pattern Pointer to the NR_TDD_UL_DL_Pattern_t pattern structure
|
||||
* @return Periodicity value in milliseconds.
|
||||
*/
|
||||
static float get_tdd_periodicity(NR_TDD_UL_DL_Pattern_t *pattern) {
|
||||
if (!pattern->ext1) {
|
||||
LOG_D(NR_MAC, "Setting TDD configuration period to dl_UL_TransmissionPeriodicity %ld\n", pattern->dl_UL_TransmissionPeriodicity);
|
||||
return tdd_ms_period_pattern[pattern->dl_UL_TransmissionPeriodicity];
|
||||
} else {
|
||||
DevAssert(pattern->ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL);
|
||||
LOG_D(NR_MAC,
|
||||
"Setting TDD configuration period to dl_UL_TransmissionPeriodicity_v1530 %ld\n",
|
||||
*pattern->ext1->dl_UL_TransmissionPeriodicity_v1530);
|
||||
return tdd_ms_period_ext[*pattern->ext1->dl_UL_TransmissionPeriodicity_v1530];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines the TDD period index based on pattern periodicities
|
||||
* @note Not applicabile to pattern extension
|
||||
* @param tdd Pointer to the NR_TDD_UL_DL_ConfigCommon_t containing patterns
|
||||
* @return Index of the TDD period in tdd_ms_period_pattern
|
||||
*/
|
||||
int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd)
|
||||
{
|
||||
int tdd_period_idx = 0;
|
||||
float pattern1_ms = get_tdd_periodicity(&tdd->pattern1);
|
||||
float pattern2_ms = tdd->pattern2 ? get_tdd_periodicity(tdd->pattern2) : 0.0;
|
||||
bool found_match = false;
|
||||
// Find matching TDD period in the predefined list of periodicities
|
||||
for (int i = 0; i < NFAPI_MAX_NUM_PERIODS; i++) {
|
||||
if ((pattern1_ms + pattern2_ms) == tdd_ms_period_pattern[i]) {
|
||||
tdd_period_idx = i;
|
||||
LOG_I(NR_MAC,
|
||||
"TDD period index = %d, based on the sum of dl_UL_TransmissionPeriodicity "
|
||||
"from Pattern1 (%f ms) and Pattern2 (%f ms): Total = %f ms\n",
|
||||
tdd_period_idx,
|
||||
pattern1_ms,
|
||||
pattern2_ms,
|
||||
pattern1_ms + pattern2_ms);
|
||||
found_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Assert if no match was found
|
||||
AssertFatal(found_match, "The sum of pattern1_ms and pattern2_ms does not match any value in tdd_ms_period_pattern");
|
||||
return tdd_period_idx;
|
||||
}
|
||||
|
||||
static struct NR_PUSCH_TimeDomainResourceAllocation *set_TimeDomainResourceAllocation(const int k2, uint8_t index, int ul_symb)
|
||||
{
|
||||
struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAlloc = calloc_or_fail(1, sizeof(*puschTdrAlloc));
|
||||
puschTdrAlloc->k2 = calloc_or_fail(1, sizeof(*puschTdrAlloc->k2));
|
||||
*puschTdrAlloc->k2 = k2;
|
||||
puschTdrAlloc->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB;
|
||||
switch (index) {
|
||||
case 0:
|
||||
puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13);
|
||||
break;
|
||||
case 1:
|
||||
puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 12);
|
||||
break;
|
||||
case 2:
|
||||
// UL TDA index 2 for mixed slot (TDD)
|
||||
puschTdrAlloc->startSymbolAndLength =
|
||||
get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one
|
||||
break;
|
||||
case 3: {
|
||||
// UL TDA index 3 for msg3 in the mixed slot (TDD)
|
||||
int no_mix_slot = ul_symb < 3 ? 1 : 0; // we need at least 2 symbols for scheduling Msg3
|
||||
*puschTdrAlloc->k2 += no_mix_slot;
|
||||
if (no_mix_slot)
|
||||
puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13); // full allocation if there is no mixed slot
|
||||
else
|
||||
puschTdrAlloc->startSymbolAndLength =
|
||||
get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return puschTdrAlloc;
|
||||
}
|
||||
|
||||
void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay)
|
||||
{
|
||||
@@ -928,58 +1024,48 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay)
|
||||
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
|
||||
AssertFatal(tda->list.count == 0, "already have pusch_TimeDomainAllocationList members\n");
|
||||
|
||||
frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
|
||||
const int k2 = min_fb_delay;
|
||||
|
||||
uint8_t DELTA[4]= {2,3,4,6}; // Delta parameter for Msg3
|
||||
int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
|
||||
struct NR_SetupRelease_PUSCH_ConfigCommon *pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon;
|
||||
|
||||
// UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol
|
||||
struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation));
|
||||
pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long));
|
||||
*pusch_timedomainresourceallocation->k2 = k2;
|
||||
pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB;
|
||||
pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0, 13);
|
||||
asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation);
|
||||
asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 0, 0));
|
||||
|
||||
// UL TDA index 1 in case of SRS
|
||||
struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation1 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation));
|
||||
pusch_timedomainresourceallocation1->k2 = CALLOC(1,sizeof(long));
|
||||
*pusch_timedomainresourceallocation1->k2 = k2;
|
||||
pusch_timedomainresourceallocation1->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB;
|
||||
pusch_timedomainresourceallocation1->startSymbolAndLength = get_SLIV(0, 12);
|
||||
asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation1);
|
||||
asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 1, 0));
|
||||
|
||||
if(frame_type==TDD) {
|
||||
if(scc->tdd_UL_DL_ConfigurationCommon) {
|
||||
int ul_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols;
|
||||
if (ul_symb>1) {
|
||||
// UL TDA index 2 for mixed slot (TDD)
|
||||
pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation));
|
||||
pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long));
|
||||
*pusch_timedomainresourceallocation->k2 = k2;
|
||||
pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB;
|
||||
pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(14 - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one
|
||||
asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation);
|
||||
}
|
||||
// UL TDA index 3 for msg3 in the mixed slot (TDD)
|
||||
int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity);
|
||||
int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame;
|
||||
struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation_msg3 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation));
|
||||
pusch_timedomainresourceallocation_msg3->k2 = CALLOC(1,sizeof(long));
|
||||
int no_mix_slot = ul_symb < 3 ? 1 : 0; // we need at least 2 symbols for scheduling Msg3
|
||||
*pusch_timedomainresourceallocation_msg3->k2 = nb_slots_per_period - DELTA[mu] + no_mix_slot;
|
||||
if(*pusch_timedomainresourceallocation_msg3->k2 < min_fb_delay)
|
||||
*pusch_timedomainresourceallocation_msg3->k2 += nb_slots_per_period;
|
||||
AssertFatal(*pusch_timedomainresourceallocation_msg3->k2 < 33,"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n",
|
||||
*pusch_timedomainresourceallocation_msg3->k2);
|
||||
pusch_timedomainresourceallocation_msg3->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB;
|
||||
if(no_mix_slot)
|
||||
pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(0, 13); // full allocation if there is no mixed slot
|
||||
else
|
||||
pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(14 - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one
|
||||
asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3);
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon) {
|
||||
int ul_symb = 0;
|
||||
NR_TDD_UL_DL_Pattern_t *p1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
|
||||
NR_TDD_UL_DL_Pattern_t *p2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2;
|
||||
if (p2 && p2->nrofUplinkSymbols)
|
||||
AssertFatal(p2->nrofUplinkSymbols == p1->nrofUplinkSymbols,
|
||||
"nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n",
|
||||
p1->nrofUplinkSymbols,
|
||||
p2->nrofUplinkSymbols);
|
||||
if (p1->nrofUplinkSymbols) {
|
||||
ul_symb = p1->nrofUplinkSymbols;
|
||||
} else if (p2) {
|
||||
ul_symb = p1->nrofUplinkSymbols;
|
||||
}
|
||||
if (ul_symb>1) {
|
||||
// UL TDA index 2 for mixed slot (TDD)
|
||||
asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,
|
||||
set_TimeDomainResourceAllocation(k2, 2, ul_symb));
|
||||
}
|
||||
// UL TDA index 3 for msg3 in the mixed slot (TDD)
|
||||
int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon);
|
||||
int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx);
|
||||
int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame;
|
||||
int k2_msg3 = nb_slots_per_period - DELTA[mu];
|
||||
struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAllocMsg3 = set_TimeDomainResourceAllocation(k2_msg3, 3, ul_symb);
|
||||
if (*puschTdrAllocMsg3->k2 < min_fb_delay)
|
||||
*puschTdrAllocMsg3->k2 += nb_slots_per_period;
|
||||
AssertFatal(*puschTdrAllocMsg3->k2 < 33,
|
||||
"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n",
|
||||
*puschTdrAllocMsg3->k2);
|
||||
asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, puschTdrAllocMsg3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1118,10 +1204,10 @@ void set_pucch_power_config(NR_PUCCH_Config_t *pucch_Config, int do_csirs) {
|
||||
|
||||
static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig, const NR_ServingCellConfigCommon_t *scc, int scs)
|
||||
{
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
const frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
|
||||
int sr_slot = 1; // in FDD SR in slot 1
|
||||
if(tdd)
|
||||
sr_slot = get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols);
|
||||
if (fs->is_tdd)
|
||||
sr_slot = get_first_ul_slot(fs, true);
|
||||
|
||||
schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset));
|
||||
|
||||
@@ -1581,15 +1667,14 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc,
|
||||
int curr_bwp,
|
||||
bool is_rsrp)
|
||||
{
|
||||
const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
|
||||
const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing];
|
||||
const int n_ul_slots_period = tdd ? (tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0)) : n_slots_frame;
|
||||
const int n_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame;
|
||||
const int ideal_period = set_ideal_period(n_slots_period, n_ul_slots_period);
|
||||
const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0;
|
||||
const int ideal_period = set_ideal_period(true);
|
||||
const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp);
|
||||
const int idx = (uid * 2 / num_pucch2) + is_rsrp;
|
||||
const int offset = first_ul_slot_period + idx % n_ul_slots_period + (idx / n_ul_slots_period) * n_slots_period;
|
||||
|
||||
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
|
||||
int offset = get_ul_slot_offset(fs, idx, true);
|
||||
|
||||
LOG_D(NR_MAC, "set_csi_meas_periodicity: uid = %d, offset = %d, ideal_period = %d", uid, offset, ideal_period);
|
||||
AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n");
|
||||
|
||||
if (ideal_period < 5) {
|
||||
@@ -2499,7 +2584,10 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc,
|
||||
AssertFatal(ServCellCom->tdd_UL_DL_ConfigurationCommon != NULL, "out of memory\n");
|
||||
ServCellCom->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing = scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing;
|
||||
ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern1 = scc->tdd_UL_DL_ConfigurationCommon->pattern1;
|
||||
ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2;
|
||||
if (scc->tdd_UL_DL_ConfigurationCommon->pattern2) {
|
||||
ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern));
|
||||
*ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = *scc->tdd_UL_DL_ConfigurationCommon->pattern2;
|
||||
}
|
||||
}
|
||||
ServCellCom->ss_PBCH_BlockPower = scc->ss_PBCH_BlockPower;
|
||||
|
||||
|
||||
@@ -112,5 +112,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC
|
||||
int uid);
|
||||
|
||||
NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc);
|
||||
int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
Active_gNBs = ( "gNB-OAI" );
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
gNB_name = "gNB-OAI";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; sd = 1; }) });
|
||||
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
# spCellConfigCommon
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
# frequencyInfoDL
|
||||
# this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP)
|
||||
absoluteFrequencySSB = 641280;
|
||||
dl_frequencyBand = 78;
|
||||
# this is 3600 MHz
|
||||
dl_absoluteFrequencyPointA = 640008;
|
||||
# scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
# initialDownlinkBWP
|
||||
# genericParameters
|
||||
# this is RBstart=27,L=48 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
# pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 12;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
|
||||
# uplinkConfigCommon
|
||||
# frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
# scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
# initialUplinkBWP
|
||||
# genericParameters
|
||||
initialULBWPlocationAndBandwidth = 28875;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
# rach-ConfigCommon
|
||||
# rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 154;
|
||||
# prach_msg1_FDM
|
||||
# 0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 0;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
preambleReceivedTargetPower = -96;
|
||||
# preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
# powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 1;
|
||||
# ra_ReponseWindow
|
||||
# 1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 4;
|
||||
# ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
# 1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
# one (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14;
|
||||
# ra_ContentionResolutionTimer
|
||||
# (0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
# prach-RootSequenceIndex_PR
|
||||
# 1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 2;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precedence over the one derived from prach-ConfigIndex
|
||||
msg1_SubcarrierSpacing = 1;
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0;
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant = -90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
# tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
# ext: 8=ms3, 9=ms4
|
||||
dl_UL_TransmissionPeriodicity = 8;
|
||||
nrofDownlinkSlots = 3;
|
||||
nrofDownlinkSymbols = 6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4;
|
||||
|
||||
# pattern2
|
||||
pattern2: {
|
||||
dl_UL_TransmissionPeriodicity2 = 4;
|
||||
nrofDownlinkSlots2 = 4;
|
||||
nrofDownlinkSymbols2 = 0;
|
||||
nrofUplinkSlots2 = 0;
|
||||
nrofUplinkSymbols2 = 0;
|
||||
};
|
||||
|
||||
ssPBCH_BlockPower = -25;
|
||||
});
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
////////// AMF parameters:
|
||||
amf_ip_address = ({ ipv4 = "192.168.70.132"; });
|
||||
|
||||
NETWORK_INTERFACES: {
|
||||
GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129";
|
||||
GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
pusch_TargetSNRx10 = 150;
|
||||
pucch_TargetSNRx10 = 200;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 120;
|
||||
pucch0_dtx_threshold = 100;
|
||||
ofdm_offset_divisor = 8; # set this to UINT_MAX for offset 0
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "yes";
|
||||
nb_tx = 1;
|
||||
nb_rx = 1;
|
||||
att_tx = 12;
|
||||
att_rx = 12;
|
||||
bands = [78];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
clock_src = "internal";
|
||||
}
|
||||
);
|
||||
|
||||
rfsimulator :
|
||||
{
|
||||
serveraddr = "server";
|
||||
serverport = 4043;
|
||||
options = (); # ("saviq"); or/and "chanmod"
|
||||
modelname = "AWGN";
|
||||
IQfile = "/tmp/rfsimulator.iqs";
|
||||
};
|
||||
|
||||
security = {
|
||||
# preferred ciphering algorithms
|
||||
# the first one of the list that a UE supports is chosen
|
||||
# valid values: nea0, nea1, nea2, nea3
|
||||
ciphering_algorithms = ( "nea0" );
|
||||
|
||||
# preferred integrity algorithms
|
||||
# the first one of the list that a UE supports is chosen
|
||||
# valid values: nia0, nia1, nia2, nia3
|
||||
integrity_algorithms = ( "nia2", "nia0" );
|
||||
|
||||
# setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
|
||||
# what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
|
||||
drb_ciphering = "yes";
|
||||
drb_integrity = "no";
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level = "info";
|
||||
hw_log_level = "info";
|
||||
phy_log_level = "info";
|
||||
mac_log_level = "info";
|
||||
rlc_log_level = "info";
|
||||
pdcp_log_level = "info";
|
||||
rrc_log_level = "info";
|
||||
ngap_log_level = "info";
|
||||
f1ap_log_level = "info";
|
||||
};
|
||||
Reference in New Issue
Block a user