Initial NR-DCI refactor

Added NR DCI 1_1 size

Several DCI NR fixes
master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent dee2ec30cd
commit 49731ab5a1

@ -29,7 +29,7 @@ struct phy_cfg_nr_t {
srsran_sch_hl_cfg_nr_t pusch = {};
srsran_pucch_nr_hl_cfg_t pucch = {};
srsran_prach_cfg_t prach = {};
srsran_ue_dl_nr_pdcch_cfg_t pdcch = {};
srsran_pdcch_cfg_nr_t pdcch = {};
srsran_ue_dl_nr_harq_ack_cfg_t harq_ack = {};
srsran_csi_hl_cfg_t csi = {};
@ -52,7 +52,7 @@ struct phy_cfg_nr_t {
// physicalCellGroupConfig
// pdsch-HARQ-ACK-Codebook: dynamic (1)
harq_ack.pdsch_harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic;
harq_ack.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic;
// commonControlResourceSet
// controlResourceSetId: 1
@ -70,39 +70,6 @@ struct phy_cfg_nr_t {
}
pdcch.coreset_present[1] = true;
// SearchSpace
// searchSpaceId: 1
// controlResourceSetId: 1
// monitoringSlotPeriodicityAndOffset: sl1 (0)
// sl1: NULL
// monitoringSymbolsWithinSlot: 8000 [bit length 14, 2 LSB pad bits, 1000 0000 0000 00.. decimal value 8192]
// nrofCandidates
// aggregationLevel1: n0 (0)
// aggregationLevel2: n0 (0)
// aggregationLevel4: n1 (1)
// aggregationLevel8: n0 (0)
// aggregationLevel16: n0 (0)
// searchSpaceType: common (0)
// common
// dci-Format0-0-AndFormat1-0
srsran_search_space_t search_space1 = {};
search_space1.id = 1;
search_space1.coreset_id = 1;
search_space1.nof_candidates[0] = 1;
search_space1.nof_candidates[1] = 1;
search_space1.nof_candidates[2] = 1;
search_space1.nof_candidates[3] = 0;
search_space1.nof_candidates[4] = 0;
search_space1.type = srsran_search_space_type_common_3;
pdcch.search_space[1] = search_space1;
pdcch.search_space_present[1] = true;
// ra-SearchSpace: 1
pdcch.ra_rnti = 0x16; //< Supposed to be deduced from PRACH configuration
pdcch.ra_search_space = search_space1;
pdcch.ra_search_space.type = srsran_search_space_type_common_1;
pdcch.ra_search_space_present = true;
// spCellConfigDedicated
// initialDownlinkBWP
// pdcch-Config: setup (1)
@ -126,32 +93,6 @@ struct phy_cfg_nr_t {
}
pdcch.coreset_present[2] = true;
// searchSpacesToAddModList: 1 item
// Item 0
// SearchSpace
// searchSpaceId: 2
// controlResourceSetId: 2
// monitoringSlotPeriodicityAndOffset: sl1 (0)
// sl1: NULL
// monitoringSymbolsWithinSlot: 8000 [bit length 14, 2 LSB pad bits, 1000 0000 0000
// 00.. decimal value 8192] nrofCandidates
// aggregationLevel1: n0 (0)
// aggregationLevel2: n2 (2)
// aggregationLevel4: n1 (1)
// aggregationLevel8: n0 (0)
// aggregationLevel16: n0 (0)
// searchSpaceType: ue-Specific (1)
// ue-Specific
// dci-Formats: formats0-0-And-1-0 (0)
pdcch.search_space[2].id = 2;
pdcch.search_space[2].coreset_id = 2;
pdcch.search_space[2].nof_candidates[0] = 0;
pdcch.search_space[2].nof_candidates[1] = 2;
pdcch.search_space[2].nof_candidates[2] = 1;
pdcch.search_space[2].nof_candidates[3] = 0;
pdcch.search_space[2].nof_candidates[4] = 0;
pdcch.search_space[2].type = srsran_search_space_type_ue;
pdcch.search_space_present[2] = true;
// pdsch-Config: setup (1)
// setup
// dmrs-DownlinkForPDSCH-MappingTypeA: setup (1)
@ -956,6 +897,71 @@ struct phy_cfg_nr_t {
csi.reports[0].freq_cfg = SRSRAN_CSI_REPORT_FREQ_WIDEBAND;
csi.reports[0].cqi_table = SRSRAN_CSI_CQI_TABLE_2;
}
/**
* @param carrier
*/
srsran_dci_cfg_nr_t get_dci_cfg(const srsran_carrier_nr_t& carrier) const
{
srsran_dci_cfg_nr_t dci_cfg = {};
// Set bandwidths
dci_cfg.coreset0_bw = pdcch.coreset_present[0] ? srsran_coreset_get_bw(&pdcch.coreset[0]) : 0;
dci_cfg.bwp_dl_initial_bw = carrier.nof_prb;
dci_cfg.bwp_dl_active_bw = carrier.nof_prb;
dci_cfg.bwp_ul_initial_bw = carrier.nof_prb;
dci_cfg.bwp_ul_active_bw = carrier.nof_prb;
// Iterate over all SS to select monitoring options
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; i++) {
// Skip not configured SS
if (not pdcch.search_space_present[i]) {
continue;
}
// Iterate all configured formats
for (uint32_t j = 0; j < pdcch.search_space[i].nof_formats; j++) {
if (pdcch.search_space[i].type == srsran_search_space_type_common_3 &&
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) {
dci_cfg.monitor_common_0_0 = true;
} else if (pdcch.search_space[i].type == srsran_search_space_type_ue &&
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_0) {
dci_cfg.monitor_0_0_and_1_0 = true;
} else if (pdcch.search_space[i].type == srsran_search_space_type_ue &&
pdcch.search_space[i].formats[j] == srsran_dci_format_nr_0_1) {
dci_cfg.monitor_0_1_and_1_1 = true;
}
}
}
// Set PUSCH parameters
dci_cfg.enable_sul = false;
dci_cfg.enable_hopping = false;
// Set Format 0_1 and 1_1 parameters
dci_cfg.carrier_indicator_size = 0;
dci_cfg.harq_ack_codebok = harq_ack.harq_ack_codebook;
// Format 0_1 specific configuration (for PUSCH only)
dci_cfg.nof_ul_bwp = 1;
dci_cfg.nof_ul_time_res = (pusch.nof_dedicated_time_ra > 0)
? pusch.nof_dedicated_time_ra
: (pusch.nof_common_time_ra > 0) ? pusch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA;
dci_cfg.nof_srs = 1;
dci_cfg.nof_ul_layers = 1;
dci_cfg.nof_rb_groups = 1;
dci_cfg.pusch_alloc_type = pusch.alloc;
// Format 1_1 specific configuration (for PDSCH only)
dci_cfg.nof_dl_bwp = 1;
dci_cfg.pdsch_alloc_type = pdsch.alloc;
dci_cfg.nof_dl_time_res = (pdsch.nof_dedicated_time_ra > 0)
? pdsch.nof_dedicated_time_ra
: (pdsch.nof_common_time_ra > 0) ? pdsch.nof_common_time_ra : SRSRAN_MAX_NOF_TIME_RA;
dci_cfg.nof_aperiodic_zp = 0;
return dci_cfg;
};
};
} // namespace srsran

@ -113,7 +113,7 @@ extern "C" {
* @brief Maximum number of PDSCH time domain resource allocations. This is defined by TS 38.331 v15.10.0
* as maxNrofDL-Allocations
*/
#define SRSRAN_MAX_NOF_DL_ALLOCATION 16
#define SRSRAN_MAX_NOF_TIME_RA 16
/**
* @brief Maximum dl-DataToUL-ACK value. This is defined by TS 38.331 v15.10.1 in PUCCH-Config
@ -143,7 +143,7 @@ typedef enum SRSRAN_API {
typedef enum SRSRAN_API { srsran_sch_mapping_type_A = 0, srsran_sch_mapping_type_B } srsran_sch_mapping_type_t;
/**
* @brief Search spaces
* @brief Search Space (SS) type
* @remark Described in TS 38.213 V15.10.0 Section 10.1 UE procedure for determining physical downlink control channel
* assignment
*/
@ -209,7 +209,8 @@ typedef enum SRSRAN_API {
srsran_dci_format_nr_2_2, ///< @brief Transmission of TPC commands for PUCCH and PUSCH
srsran_dci_format_nr_2_3, ///< @brief Transmission of a group of TPC commands for SRS transmissions by one or more UEs
srsran_dci_format_nr_rar, ///< @brief Scheduling a transmission of PUSCH from RAR
srsran_dci_format_nr_cg ///< @brief Scheduling of PUSCH using a configured grant
srsran_dci_format_nr_cg, ///< @brief Scheduling of PUSCH using a configured grant
SRSRAN_DCI_FORMAT_NR_COUNT ///< @brief Number of DCI formats
} srsran_dci_format_nr_t;
/**
@ -232,7 +233,18 @@ typedef enum SRSRAN_API {
srsran_pdsch_harq_ack_codebook_none = 0,
srsran_pdsch_harq_ack_codebook_semi_static,
srsran_pdsch_harq_ack_codebook_dynamic,
} srsran_pdsch_harq_ack_codebook_t;
} srsran_harq_ack_codebook_t;
/**
* @brief PDSCH/PUSCH Resource allocation configuration
* @remark Described in TS 38.331 V15.10.0 PhysicalCellGroupConfig
*/
typedef enum SRSRAN_API {
srsran_resource_alloc_type0 = 0,
srsran_resource_alloc_type1,
srsran_resource_alloc_dynamic,
} srsran_resource_alloc_t;
/**
* @brief NR carrier parameters. It is a combination of fixed cell and bandwidth-part (BWP)
*/
@ -303,8 +315,10 @@ typedef struct SRSRAN_API {
typedef struct SRSRAN_API {
uint32_t id;
uint32_t coreset_id;
uint32_t duration; // in slots
srsran_search_space_type_t type;
uint32_t duration; ///< SS duration length in slots
srsran_search_space_type_t type; ///< Sets the SS type, common (multiple types) or UE specific
srsran_dci_format_nr_t formats[SRSRAN_DCI_FORMAT_NR_COUNT]; ///< Specifies the DCI formats that shall be searched
uint32_t nof_formats;
uint32_t nof_candidates[SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR];
} srsran_search_space_t;
@ -334,6 +348,13 @@ typedef struct SRSRAN_API {
*/
SRSRAN_API const char* srsran_rnti_type_str(srsran_rnti_type_t rnti_type);
/**
* @brief Get the RNTI type name for NR
* @param rnti_type RNTI type name
* @return Constant string with the RNTI type name
*/
SRSRAN_API const char* srsran_dci_format_nr_string(srsran_dci_format_nr_t format);
/**
* @brief Calculates the bandwidth of a given CORESET in physical resource blocks (PRB) . This function uses the
* frequency domain resources bit-map for counting the number of PRB.

@ -15,6 +15,7 @@
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/dft/ofdm.h"
#include "srsran/phy/phch/pdcch_cfg_nr.h"
#include "srsran/phy/phch/pdcch_nr.h"
#include "srsran/phy/phch/pdsch_nr.h"
@ -26,10 +27,10 @@ typedef struct SRSRAN_API {
} srsran_enb_dl_nr_args_t;
typedef struct SRSRAN_API {
uint32_t max_prb;
uint32_t nof_tx_antennas;
srsran_carrier_nr_t carrier;
srsran_coreset_t coreset;
uint32_t max_prb;
uint32_t nof_tx_antennas;
srsran_carrier_nr_t carrier;
srsran_pdcch_cfg_nr_t pdcch_cfg;
srsran_ofdm_t fft[SRSRAN_MAX_PORTS];
@ -37,6 +38,7 @@ typedef struct SRSRAN_API {
srsran_pdsch_nr_t pdsch;
srsran_dmrs_sch_t dmrs;
srsran_dci_nr_t dci; ///< Stores DCI configuration
srsran_pdcch_nr_t pdcch;
} srsran_enb_dl_nr_t;
@ -45,7 +47,9 @@ srsran_enb_dl_nr_init(srsran_enb_dl_nr_t* q, cf_t* output[SRSRAN_MAX_PORTS], con
SRSRAN_API int srsran_enb_dl_nr_set_carrier(srsran_enb_dl_nr_t* q, const srsran_carrier_nr_t* carrier);
SRSRAN_API int srsran_enb_dl_nr_set_coreset(srsran_enb_dl_nr_t* q, const srsran_coreset_t* coreset);
SRSRAN_API int srsran_enb_dl_nr_set_pdcch_config(srsran_enb_dl_nr_t* q,
const srsran_pdcch_cfg_nr_t* cfg,
const srsran_dci_cfg_nr_t* dci_cfg);
SRSRAN_API void srsran_enb_dl_nr_free(srsran_enb_dl_nr_t* q);

@ -17,24 +17,131 @@
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/phch/phch_cfg_nr.h"
/**
* @brief Maximum number of NR DCI sizes the UE shall search for a given serving cell
*/
#define SRSRAN_DCI_NR_MAX_NOF_SIZES 4
/**
* @brief DCI configuration given a serving cell
*/
typedef struct SRSRAN_API {
/// Bandwidth parameters
uint32_t coreset0_bw; ///< CORESET0 DL bandwidth, set to 0 if not present
uint32_t bwp_dl_initial_bw; ///< Initial DL BWP bandwidth
uint32_t bwp_dl_active_bw; ///< Active DL BWP bandwidth in PRB
uint32_t bwp_ul_initial_bw; ///< Initial UL BWP bandwidth
uint32_t bwp_ul_active_bw; ///< Active UL BWP bandwidth in PRB
/// Search space derived parameters
bool monitor_common_0_0; ///< Set to true if Format 0_0 is monitored in common SS
bool monitor_0_0_and_1_0; ///< Set to true if Format 0_0 is monitored in UE-specific SS
bool monitor_0_1_and_1_1; ///< Set to true if Formats 0_1 and 1_1 are monitored in UE-specific SS
/// PUSCH configuration derived parameters
bool enable_sul; ///< Set to true if supplementary uplink is configured
bool enable_hopping; ///< Set to true if frequency hopping is enabled
/// Common Formats 0_1 and 1_1
uint32_t carrier_indicator_size; ///< Defined in TS 38.213 clause 10.1
srsran_harq_ack_codebook_t harq_ack_codebok; ///< PDSCH HARQ-ACK codebook mode
uint32_t nof_rb_groups; ///< Defined in TS 38.214 clause 6.1.2.2.1
/// Format 0_1 specific configuration (for PUSCH only)
uint32_t nof_ul_bwp; ///< Number of UL BWPs excluding the initial UL BWP, mentioned in the TS as N_BWP_RRC
uint32_t nof_ul_time_res; ///< Number of dedicated PUSCH time domain resource assigment, set to 0 for default
uint32_t nof_srs; ///< Number of configured SRS resources
uint32_t nof_ul_layers; ///< Set to the maximum number of layers for PUSCH
uint32_t pusch_nof_cbg; ///< determined by maxCodeBlockGroupsPerTransportBlock for PUSCH
uint32_t report_trigger_size; ///< determined by reportTriggerSize
bool enable_transform_precoding; ///< Set to true if PUSCH transform precoding is enabled
bool dynamic_dual_harq_ack_codebook; ///< Set to true if HARQ-ACK codebook is set to dynamic with 2 sub-codebooks
bool pusch_tx_config_codebook; ///< Set to true if PUSCH txConfig is set to codebook
bool pusch_dmrs_type2; ///< Set to true if PUSCH DMRS are type 2
bool pusch_dmrs_double; ///< Set to true if PUSCH DMRS are 2 symbol long
bool pusch_ptrs; ///< Set to true if PT-RS are enabled for PUSCH transmission
bool pusch_dynamic_betas; ///< Set to true if beta offsets operation is not semi-static
srsran_resource_alloc_t pusch_alloc_type; ///< PUSCH resource allocation type
/// Format 1_1 specific configuration (for PDSCH only)
uint32_t nof_dl_bwp; ///< Number of DL BWPs excluding the initial UL BWP, mentioned in the TS as N_BWP_RRC
srsran_resource_alloc_t pdsch_alloc_type; ///< PDSCH resource allocation type, set to 0 for default
uint32_t nof_dl_time_res; ///< Number of dedicated PDSCH time domain resource assigment
uint32_t nof_aperiodic_zp; ///< Number of aperiodic ZP CSI-RS resource sets configured
bool pdsch_inter_prb_to_prb; ///< Set to true if interleaved VRB to PRB mapping is enabled
bool pdsch_rm_pattern1; ///< Set to true if rateMatchPatternGroup1 is configured
bool pdsch_rm_pattern2; ///< Set to true if rateMatchPatternGroup2 is configured
bool pdsch_2cw; ///< Set to true if maxNrofCodeWordsScheduledByDCI is set to 2 in any BWP
uint32_t pdsch_nof_cbg; ///< determined by maxCodeBlockGroupsPerTransportBlock for PDSCH
bool multiple_scell; ///< Set to true if configured with multiple serving cell
bool nof_dl_to_ul_ack; ///< Number of entries in the dl-DataToUL-ACK
bool pdsch_dmrs_type2; ///< Set to true if PDSCH DMRS are type 2
bool pdsch_dmrs_double; ///< Set to true if PDSCH DMRS are 2 symbol long
bool pdsch_tci; ///< Set to true if tci-PresentInDCI is enabled
bool pdsch_cbg_flush; ///< Set to true if codeBlockGroupFlushIndicator is true
bool pdsch_dynamic_bundling; ///< Set to true if prb-BundlingType is set to dynamicBundling
} srsran_dci_cfg_nr_t;
/**
* @brief NR-DCI object. Stores DCI configuration and pre-calculated DCI sizes
*/
typedef struct SRSRAN_API {
/// Configuration parameters
srsran_dci_cfg_nr_t cfg;
/// Formats 0_0 and 1_0 in common SS
uint32_t dci_0_0_and_1_0_common_size; ///< DCI format 0_0 and 1_0 in common SS size
uint32_t dci_0_0_common_trunc; ///< DCI format 0_0 in common SS truncation
uint32_t dci_0_0_common_padd; ///< DCI format 0_0 in common SS padding
/// Formats 0_0 and 1_0 in UE-specific SS
uint32_t dci_0_0_and_1_0_ue_size; ///< DCI format 0_0 and 1_0 in UE-specific SS size
uint32_t dci_0_0_ue_padd; ///< DCI format 0_0 in ue SS padding
uint32_t dci_1_0_ue_padd; ///< DCI format 1_0 in ue SS padding
/// Formats 0_1 and 1_0 (UE-specific SS only)
uint32_t dci_0_1_size; ///< DCI format 0_1 size
uint32_t dci_0_1_padd; ///< DCI format 0_1 padding
uint32_t dci_1_1_size; ///< DCI format 0_1 size
uint32_t dci_1_1_padd; ///< DCI format 1_1 padding
} srsran_dci_nr_t;
/**
* @brief Describes the NR DCI search context
*/
typedef struct SRSRAN_API {
srsran_dci_location_t location; ///< DCI location
srsran_search_space_type_t ss_type; ///< Search space type
uint32_t coreset_id; ///< CORESET identifier
srsran_rnti_type_t rnti_type; ///< RNTI type
srsran_dci_format_nr_t format; ///< DCI format
uint16_t rnti; ///< UE temporal RNTI
uint32_t coreset0_bw; ///< CORESET0 DL bandwidth, set to 0 if not present
uint32_t bwp_dl_initial_bw; ///< Initial DL/UL BWP bandwidth
uint32_t bwp_dl_active_bw; ///< Active DL/UL BWP bandwidth in PRB
uint32_t bwp_ul_initial_bw; ///< Initial UL BWP bandwidth
uint32_t bwp_ul_active_bw; ///< Active UL BWP bandwidth in PRB
bool monitor_common_0_0; ///< Set to true if Format 0_0 is monitored in common SS
bool enable_sul; ///< Set to true if supplementary uplink is configured
bool enable_hopping; ///< Set to true if frequency hopping is enabled
} srsran_dci_ctx_t;
/**
* @brief Describes any packed format NR DCI message
*/
typedef struct SRSRAN_API {
srsran_dci_location_t location;
srsran_search_space_type_t search_space;
uint32_t coreset_id;
uint8_t payload[50];
srsran_rnti_type_t rnti_type;
uint32_t nof_bits;
srsran_dci_format_nr_t format;
uint16_t rnti;
srsran_dci_ctx_t ctx; ///< DCI context
uint8_t payload[50];
uint32_t nof_bits;
} srsran_dci_msg_nr_t;
/**
* @brief Describes an unpacked DL NR DCI message
*/
typedef struct SRSRAN_API {
uint16_t rnti;
srsran_rnti_type_t rnti_type;
srsran_dci_format_nr_t format;
srsran_dci_location_t location;
srsran_search_space_type_t search_space;
uint32_t coreset_id;
srsran_dci_ctx_t ctx; ///< DCI search context
// Common fields
uint32_t freq_domain_assigment; ///< Frequency domain resource assignment
@ -62,14 +169,13 @@ typedef struct SRSRAN_API {
} srsran_dci_dl_nr_t;
/**
* @brief Describes an unpacked UL NR DCI message
* @remark NR RAR UL DCI Described in TS 38.213 Table 8.2-1: Random Access Response Grant Content field size
*/
typedef struct SRSRAN_API {
// Context information
uint16_t rnti;
srsran_rnti_type_t rnti_type;
srsran_dci_format_nr_t format;
srsran_dci_location_t location;
srsran_search_space_type_t search_space;
uint32_t coreset_id;
srsran_dci_ctx_t ctx; ///< Context information
// Common fields
uint32_t freq_domain_assigment; ///< Frequency domain resource assignment
@ -91,60 +197,93 @@ typedef struct SRSRAN_API {
// Random Access Response Grant
uint32_t csi_request;
// Other fields
uint32_t sul; ///< Supplementary Uplink flag
} srsran_dci_ul_nr_t;
/**
* @brief Indicates whether the provided DCI message format bit indicator belongs to DCI format 1_0 according according
* to the RNTI type. If invalid, the DCI message is likely to be format 0_0
* @param dci_msg Provides DCI format 1_0 message
* @return true if the DCI message is format 1_0, false otherwise
* @brief Set NR-DCI configuration for a given cell. This function will pre-compute the DCI sizes, padding, truncation
* and so on from a given DCI configuration.
* @remark Implemented according TS 38.212 section 7.3.1.0 DCI size alignment
* @param[in,out] dci DCI object
* @param[in] cfg NR-DCI configuration
* @return SRSLTE_SUCCESS if the configuration is valid, SRSLTE_ERROR code otherwise
*/
SRSRAN_API bool srsran_dci_nr_format_1_0_valid(const srsran_dci_msg_nr_t* dci_msg);
SRSRAN_API int srsran_dci_nr_set_cfg(srsran_dci_nr_t* dci, const srsran_dci_cfg_nr_t* cfg);
SRSRAN_API int srsran_dci_nr_pack(const srsran_carrier_nr_t* carrier,
const srsran_coreset_t* coreset,
const srsran_dci_dl_nr_t* dci,
srsran_dci_msg_nr_t* msg);
SRSRAN_API int srsran_dci_nr_format_0_0_sizeof(const srsran_carrier_nr_t* carrier,
const srsran_coreset_t* coreset,
srsran_rnti_type_t rnti_type);
/**
* @brief Calculates a DL NR-DCI size for a given SS type and format
* @attention Only DCI 0_0 and 1_0 can be in common search-space
* @param q NR DCI object
* @param ss_type Search Space type
* @param format NR DCI format
* @return The number of bis for the DCI message if configured, 0 otherwise
*/
SRSRAN_API uint32_t srsran_dci_nr_size(const srsran_dci_nr_t* q,
srsran_search_space_type_t ss_type,
srsran_dci_format_nr_t format);
SRSRAN_API int srsran_dci_nr_format_0_0_pack(const srsran_carrier_nr_t* carrier,
const srsran_coreset_t* coreset0,
const srsran_dci_ul_nr_t* dci,
srsran_dci_msg_nr_t* msg);
/**
* @brief Indicates whether the provided DCI message format bit indicator belongs to the a Dl DCI format (1_0 or 1_1)
* according according to the RNTI type. If invalid, the DCI message is likely to be an UL DCI
* @param dci Provides DCI format message
* @return true if the DCI message is for DL, false otherwise
*/
SRSRAN_API bool srsran_dci_nr_valid_direction(const srsran_dci_msg_nr_t* dci);
SRSRAN_API int srsran_dci_nr_format_0_0_unpack(const srsran_carrier_nr_t* carrier,
const srsran_coreset_t* coreset,
srsran_dci_msg_nr_t* msg,
srsran_dci_ul_nr_t* dci);
/**
* @brief Packs a DL NR DCI into a DCI message
* @param q NR DCI object with precomputed DCI parameters
* @param dci DL NR DCI to pack (serialize)
* @param[out] msg Resultant packed DCI message
* @return SRSLTE_SUCCESS if provided arguments are valid, SRSLTE_ERROR code otherwise
*/
SRSRAN_API int srsran_dci_nr_dl_pack(const srsran_dci_nr_t* q, const srsran_dci_dl_nr_t* dci, srsran_dci_msg_nr_t* msg);
/**
* @brief Unpacks DCI from Random Access Response Grant
* @remark Described in TS 38.213 Table 8.2-1: Random Access Response Grant Content field size
* @param msg
* @param dci
* @return SRSRAN_SUCCESS if unpacked correctly, SRSRAN_ERROR code otherwise
* @brief Unpacks an NR DCI message into a DL NR DCI
* @param q NR DCI object with precomputed DCI parameters
* @param msg DCI message to unpack (deserialize)
* @param[out] dci Resultant unpacked DL DCI
* @return SRSLTE_SUCCESS if provided arguments are valid, SRSLTE_ERROR code otherwise
*/
SRSRAN_API int srsran_dci_nr_rar_unpack(srsran_dci_msg_nr_t* msg, srsran_dci_ul_nr_t* dci);
SRSRAN_API int srsran_dci_nr_dl_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_dl_nr_t* dci);
SRSRAN_API int srsran_dci_nr_format_1_0_sizeof(const srsran_carrier_nr_t* carrier,
const srsran_coreset_t* coreset,
srsran_rnti_type_t rnti_type);
/**
* @brief Packs an UL NR DCI into a DCI message
* @param q NR DCI object with precomputed DCI parameters
* @param dci UL NR DCI to pack (serialize)
* @param[out] msg resultant DCI message
* @return SRSLTE_SUCCESS if provided arguments are valid, SRSLTE_ERROR code otherwise
*/
SRSRAN_API int srsran_dci_nr_ul_pack(const srsran_dci_nr_t* q, const srsran_dci_ul_nr_t* dci, srsran_dci_msg_nr_t* msg);
SRSRAN_API int srsran_dci_nr_format_1_0_pack(const srsran_carrier_nr_t* carrier,
const srsran_coreset_t* coreset,
const srsran_dci_dl_nr_t* dci,
srsran_dci_msg_nr_t* msg);
/**
* @brief Unpacks an NR DCI message into an UL NR DCI
* @param q NR DCI object with precomputed DCI parameters
* @param msg DCI message to unpack (deserialize)
* @param[out] dci Resultant unpacked UL DCI
* @return SRSLTE_SUCCESS if provided arguments are valid, SRSLTE_ERROR code otherwise
*/
SRSRAN_API int srsran_dci_nr_ul_unpack(const srsran_dci_nr_t* q, srsran_dci_msg_nr_t* msg, srsran_dci_ul_nr_t* dci);
SRSRAN_API int srsran_dci_nr_format_1_0_unpack(const srsran_carrier_nr_t* carrier,
const srsran_coreset_t* coreset,
srsran_dci_msg_nr_t* msg,
srsran_dci_dl_nr_t* dci);
/**
* @brief Stringifies an DL NR DCI structure
* @param dci DL NR SCI structure to stringify
* @param[out] str Destination string
* @param str_len Destination string length
* @return The number of written characters
*/
SRSRAN_API int srsran_dci_dl_nr_to_str(const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len);
/**
* @brief Stringifies an UL NR DCI structure
* @param dci UL NR SCI structure to stringify
* @param[out] str Destination string
* @param str_len Destination string length
* @return The number of written characters
*/
SRSRAN_API int srsran_dci_ul_nr_to_str(const srsran_dci_ul_nr_t* dci, char* str, uint32_t str_len);
SRSRAN_API int srsran_dci_dl_nr_to_str(const srsran_dci_dl_nr_t* dci, char* str, uint32_t str_len);
#endif // SRSRAN_DCI_NR_H

@ -0,0 +1,44 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#ifndef SRSRAN_PDCCH_CFG_NR_H
#define SRSRAN_PDCCH_CFG_NR_H
#include "dci_nr.h"
/**
* Maximum number of CORESET
* @remark Defined in TS 38.331 by maxNrofControlResourceSets-1
*/
#define SRSRAN_UE_DL_NR_MAX_NOF_CORESET 12
/**
* Maximum number of Search spaces
* @remark Defined in TS 38.331 by maxNrofSearchSpaces-1
*/
#define SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE 40
/**
* @brief PDCCH configuration provided by upper layers
*/
typedef struct SRSRAN_API {
srsran_coreset_t coreset[SRSRAN_UE_DL_NR_MAX_NOF_CORESET]; ///< PDCCH Control resource sets (CORESET) collection
bool coreset_present[SRSRAN_UE_DL_NR_MAX_NOF_CORESET]; ///< CORESET present flags
srsran_search_space_t search_space[SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE];
bool search_space_present[SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE];
srsran_search_space_t ra_search_space;
bool ra_search_space_present;
} srsran_pdcch_cfg_nr_t;
#endif // SRSRAN_PDCCH_CFG_NR_H

@ -201,13 +201,14 @@ typedef struct SRSRAN_API {
bool present;
} dmrs_typeB;
srsran_sch_time_ra_t common_time_ra[SRSRAN_MAX_NOF_DL_ALLOCATION];
srsran_sch_time_ra_t common_time_ra[SRSRAN_MAX_NOF_TIME_RA];
uint32_t nof_common_time_ra;
srsran_sch_time_ra_t dedicated_time_ra[SRSRAN_MAX_NOF_DL_ALLOCATION];
srsran_sch_time_ra_t dedicated_time_ra[SRSRAN_MAX_NOF_TIME_RA];
uint32_t nof_dedicated_time_ra;
bool rbg_size_cfg_1; ///< RBG size configuration (1 or 2)
bool rbg_size_cfg_1; ///< RBG size configuration (1 or 2)
srsran_resource_alloc_t alloc;
srsran_sch_cfg_t sch_cfg; ///< Common shared channel parameters

@ -17,22 +17,11 @@
#include "srsran/phy/common/phy_common_nr.h"
#include "srsran/phy/dft/ofdm.h"
#include "srsran/phy/phch/dci_nr.h"
#include "srsran/phy/phch/pdcch_cfg_nr.h"
#include "srsran/phy/phch/pdcch_nr.h"
#include "srsran/phy/phch/pdsch_nr.h"
#include "srsran/phy/phch/uci_cfg_nr.h"
/**
* Maximum number of CORESET
* @remark Defined in TS 38.331 by maxNrofControlResourceSets-1
*/
#define SRSRAN_UE_DL_NR_MAX_NOF_CORESET 12
/**
* Maximum number of Search spaces
* @remark Defined in TS 38.331 by maxNrofSearchSpaces-1
*/
#define SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE 40
/**
* Maximum number of DCI messages to receive
*/
@ -47,18 +36,6 @@ typedef struct SRSRAN_API {
float pdcch_dmrs_epre_thr;
} srsran_ue_dl_nr_args_t;
typedef struct SRSRAN_API {
srsran_coreset_t coreset[SRSRAN_UE_DL_NR_MAX_NOF_CORESET]; ///< PDCCH Control resource sets (CORESET) collection
bool coreset_present[SRSRAN_UE_DL_NR_MAX_NOF_CORESET]; ///< CORESET present flags
srsran_search_space_t search_space[SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE];
bool search_space_present[SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE];
uint16_t ra_rnti; ///< Needs to be deduced from the PRACH configuration
srsran_search_space_t ra_search_space;
bool ra_search_space_present;
} srsran_ue_dl_nr_pdcch_cfg_t;
typedef struct {
uint32_t scell_idx; ///< Serving cell index
uint32_t v_dai_dl; ///< Downlink Assigment Index
@ -93,9 +70,9 @@ typedef struct {
} srsran_pdsch_ack_nr_t;
typedef struct SRSRAN_API {
bool harq_ack_spatial_bundling_pucch; ///< Param harq-ACK-SpatialBundlingPUCCH, set to true if provided
bool harq_ack_spatial_bundling_pusch; ///< Param harq-ACK-SpatialBundlingPUSCH, set to true if provided
srsran_pdsch_harq_ack_codebook_t pdsch_harq_ack_codebook; ///< pdsch-HARQ-ACK-Codebook configuration
bool harq_ack_spatial_bundling_pucch; ///< Param harq-ACK-SpatialBundlingPUCCH, set to true if provided
bool harq_ack_spatial_bundling_pusch; ///< Param harq-ACK-SpatialBundlingPUSCH, set to true if provided
srsran_harq_ack_codebook_t harq_ack_codebook; ///< pdsch-HARQ-ACK-Codebook configuration
bool max_cw_sched_dci_is_2; ///< Param maxNrofCodeWordsScheduledByDCI, set to true if present and equal to 2
uint32_t dl_data_to_ul_ack[SRSRAN_MAX_NOF_DL_DATA_TO_UL];
@ -103,11 +80,10 @@ typedef struct SRSRAN_API {
} srsran_ue_dl_nr_harq_ack_cfg_t;
typedef struct SRSRAN_API {
uint32_t coreset_id;
uint32_t ss_id;
srsran_dci_location_t location;
srsran_dci_ctx_t dci_ctx;
srsran_dmrs_pdcch_measure_t measure;
srsran_pdcch_nr_res_t result;
uint32_t nof_bits;
} srsran_ue_dl_nr_pdcch_info_t;
typedef struct SRSRAN_API {
@ -116,8 +92,8 @@ typedef struct SRSRAN_API {
float pdcch_dmrs_corr_thr;
float pdcch_dmrs_epre_thr;
srsran_carrier_nr_t carrier;
srsran_ue_dl_nr_pdcch_cfg_t cfg;
srsran_carrier_nr_t carrier;
srsran_pdcch_cfg_nr_t cfg;
srsran_ofdm_t fft[SRSRAN_MAX_PORTS];
@ -134,12 +110,15 @@ typedef struct SRSRAN_API {
srsran_ue_dl_nr_pdcch_info_t pdcch_info[SRSRAN_MAX_NOF_CANDIDATES_SLOT_NR];
uint32_t pdcch_info_count;
/// DCI packing/unpacking object
srsran_dci_nr_t dci;
/// Temporally stores Found DCI messages from all SS
srsran_dci_msg_nr_t dci_msg[SRSRAN_MAX_DCI_MSG_NR];
uint32_t dci_msg_count;
srsran_dci_msg_nr_t dl_dci_msg[SRSRAN_MAX_DCI_MSG_NR];
uint32_t dl_dci_msg_count;
srsran_dci_msg_nr_t pending_ul_dci_msg[SRSRAN_MAX_DCI_MSG_NR];
uint32_t pending_ul_dci_count;
srsran_dci_msg_nr_t ul_dci_msg[SRSRAN_MAX_DCI_MSG_NR];
uint32_t ul_dci_count;
} srsran_ue_dl_nr_t;
SRSRAN_API int
@ -147,7 +126,9 @@ srsran_ue_dl_nr_init(srsran_ue_dl_nr_t* q, cf_t* input[SRSRAN_MAX_PORTS], const
SRSRAN_API int srsran_ue_dl_nr_set_carrier(srsran_ue_dl_nr_t* q, const srsran_carrier_nr_t* carrier);
SRSRAN_API int srsran_ue_dl_nr_set_pdcch_config(srsran_ue_dl_nr_t* q, const srsran_ue_dl_nr_pdcch_cfg_t* cfg);
SRSRAN_API int srsran_ue_dl_nr_set_pdcch_config(srsran_ue_dl_nr_t* q,
const srsran_pdcch_cfg_nr_t* cfg,
const srsran_dci_cfg_nr_t* dci_cfg);
SRSRAN_API void srsran_ue_dl_nr_free(srsran_ue_dl_nr_t* q);

@ -268,13 +268,13 @@ bool make_phy_harq_ack_cfg(const phys_cell_group_cfg_s& phys_cell_group_cfg,
srsran_ue_dl_nr_harq_ack_cfg_t srsran_ue_dl_nr_harq_ack_cfg;
switch (phys_cell_group_cfg.pdsch_harq_ack_codebook) {
case phys_cell_group_cfg_s::pdsch_harq_ack_codebook_opts::dynamic_value:
srsran_ue_dl_nr_harq_ack_cfg.pdsch_harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic;
srsran_ue_dl_nr_harq_ack_cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_dynamic;
break;
case phys_cell_group_cfg_s::pdsch_harq_ack_codebook_opts::semi_static:
srsran_ue_dl_nr_harq_ack_cfg.pdsch_harq_ack_codebook = srsran_pdsch_harq_ack_codebook_semi_static;
srsran_ue_dl_nr_harq_ack_cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_semi_static;
break;
case phys_cell_group_cfg_s::pdsch_harq_ack_codebook_opts::nulltype:
srsran_ue_dl_nr_harq_ack_cfg.pdsch_harq_ack_codebook = srsran_pdsch_harq_ack_codebook_none;
srsran_ue_dl_nr_harq_ack_cfg.harq_ack_codebook = srsran_pdsch_harq_ack_codebook_none;
break;
default:
asn1::log_warning("Invalid option for pdsch_harq_ack_codebook %s",
@ -312,9 +312,51 @@ bool make_phy_search_space_cfg(const search_space_s& search_space, srsran_search
switch (search_space.search_space_type.type()) {
case search_space_s::search_space_type_c_::types_opts::options::common:
srsran_search_space.type = srsran_search_space_type_common_3;
// dci-Format0-0-AndFormat1-0
// If configured, the UE monitors the DCI formats 0_0 and 1_0 according to TS 38.213 [13], clause 10.1.
if (search_space.search_space_type.common().dci_format0_minus0_and_format1_minus0_present) {
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_0_0;
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_1_0;
}
// dci-Format2-0
// If configured, UE monitors the DCI format 2_0 according to TS 38.213 [13], clause 10.1, 11.1.1.
if (search_space.search_space_type.common().dci_format2_minus0_present) {
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_2_0;
}
// dci-Format2-1
// If configured, UE monitors the DCI format 2_1 according to TS 38.213 [13], clause 10.1, 11.2.
if (search_space.search_space_type.common().dci_format2_minus1_present) {
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_2_1;
}
// dci-Format2-2
// If configured, UE monitors the DCI format 2_2 according to TS 38.213 [13], clause 10.1, 11.3.
if (search_space.search_space_type.common().dci_format2_minus2_present) {
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_2_2;
}
// dci-Format2-3
// If configured, UE monitors the DCI format 2_3 according to TS 38.213 [13], clause 10.1, 11.4
if (search_space.search_space_type.common().dci_format2_minus3_present) {
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_2_3;
}
break;
case search_space_s::search_space_type_c_::types_opts::options::ue_specific:
srsran_search_space.type = srsran_search_space_type_ue;
switch (search_space.search_space_type.ue_specific().dci_formats.value) {
case search_space_s::search_space_type_c_::ue_specific_s_::dci_formats_e_::formats0_minus0_and_minus1_minus0:
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_0_0;
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_1_0;
break;
case search_space_s::search_space_type_c_::ue_specific_s_::dci_formats_e_::formats0_minus1_and_minus1_minus1:
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_0_1;
srsran_search_space.formats[srsran_search_space.nof_formats++] = srsran_dci_format_nr_1_1;
break;
}
break;
default:
asn1::log_warning("Invalid option for search_space_type %s", search_space.search_space_type.type().to_string());

@ -37,6 +37,36 @@ const char* srsran_rnti_type_str(srsran_rnti_type_t rnti_type)
return "unknown";
}
const char* srsran_dci_format_nr_string(srsran_dci_format_nr_t format)
{
switch (format) {
case srsran_dci_format_nr_0_0:
return "0_0";
case srsran_dci_format_nr_0_1:
return "0_1";
case srsran_dci_format_nr_1_0:
return "1_0";
case srsran_dci_format_nr_1_1:
return "1_1";
case srsran_dci_format_nr_2_0:
return "2_0";
case srsran_dci_format_nr_2_1:
return "2_1";
case srsran_dci_format_nr_2_2:
return "2_2";
case srsran_dci_format_nr_2_3:
return "2_3";
case srsran_dci_format_nr_rar:
return "RAR";
case srsran_dci_format_nr_cg:
return "CG";
default:
case SRSRAN_DCI_FORMAT_NR_COUNT:
break;
}
return "unknown";
}
uint32_t srsran_coreset_get_bw(const srsran_coreset_t* coreset)
{
uint32_t prb_count = 0;

@ -135,15 +135,21 @@ int srsran_enb_dl_nr_set_carrier(srsran_enb_dl_nr_t* q, const srsran_carrier_nr_
return SRSRAN_SUCCESS;
}
int srsran_enb_dl_nr_set_coreset(srsran_enb_dl_nr_t* q, const srsran_coreset_t* coreset)
int srsran_enb_dl_nr_set_pdcch_config(srsran_enb_dl_nr_t* q,
const srsran_pdcch_cfg_nr_t* cfg,
const srsran_dci_cfg_nr_t* dci_cfg)
{
if (q == NULL || coreset == NULL) {
if (q == NULL || cfg == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
q->coreset = *coreset;
q->pdcch_cfg = *cfg;
if (srsran_pdcch_nr_set_carrier(&q->pdcch, &q->carrier, &q->coreset) < SRSRAN_SUCCESS) {
if (srsran_pdcch_nr_set_carrier(&q->pdcch, &q->carrier, &q->pdcch_cfg.coreset[0]) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
if (srsran_dci_nr_set_cfg(&q->dci, dci_cfg) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
@ -182,15 +188,27 @@ int srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q,
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (dci_dl->ctx.coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET ||
!q->pdcch_cfg.coreset_present[dci_dl->ctx.coreset_id]) {
ERROR("Invalid CORESET ID %d", dci_dl->ctx.coreset_id);
return SRSRAN_ERROR;
}
srsran_coreset_t* coreset = &q->pdcch_cfg.coreset[dci_dl->ctx.coreset_id];
if (srsran_pdcch_nr_set_carrier(&q->pdcch, &q->carrier, coreset) < SRSRAN_SUCCESS) {
ERROR("Error setting PDCCH carrier/CORESET");
return SRSRAN_ERROR;
}
// Put DMRS
if (srsran_dmrs_pdcch_put(&q->carrier, &q->coreset, slot_cfg, &dci_dl->location, q->sf_symbols[0]) < SRSRAN_SUCCESS) {
if (srsran_dmrs_pdcch_put(&q->carrier, coreset, slot_cfg, &dci_dl->ctx.location, q->sf_symbols[0]) < SRSRAN_SUCCESS) {
ERROR("Error putting PDCCH DMRS");
return SRSRAN_ERROR;
}
// Pack DCI
srsran_dci_msg_nr_t dci_msg = {};
if (srsran_dci_nr_pack(&q->carrier, &q->coreset, dci_dl, &dci_msg) < SRSRAN_SUCCESS) {
if (srsran_dci_nr_dl_pack(&q->dci, dci_dl, &dci_msg) < SRSRAN_SUCCESS) {
ERROR("Error packing DL DCI");
return SRSRAN_ERROR;
}
@ -201,7 +219,7 @@ int srsran_enb_dl_nr_pdcch_put(srsran_enb_dl_nr_t* q,
return SRSRAN_ERROR;
}
INFO("DCI DL NR: L=%d; ncce=%d;", dci_dl->location.L, dci_dl->location.ncce);
INFO("DCI DL NR: L=%d; ncce=%d;", dci_dl->ctx.location.L, dci_dl->ctx.location.ncce);
return SRSRAN_SUCCESS;
}

File diff suppressed because it is too large Load Diff

@ -324,11 +324,11 @@ static uint32_t pdcch_nr_cp(const srsran_pdcch_nr_t* q,
static uint32_t pdcch_nr_c_init(const srsran_pdcch_nr_t* q, const srsran_dci_msg_nr_t* dci_msg)
{
uint32_t n_id = (dci_msg->search_space == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present)
uint32_t n_id = (dci_msg->ctx.ss_type == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present)
? q->coreset.dmrs_scrambling_id
: q->carrier.id;
uint32_t n_rnti = (dci_msg->search_space == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present)
? dci_msg->rnti
uint32_t n_rnti = (dci_msg->ctx.ss_type == srsran_search_space_type_ue && q->coreset.dmrs_scrambling_id_present)
? dci_msg->ctx.rnti
: 0U;
return ((n_rnti << 16U) + n_id) & 0x7fffffffU;
}
@ -345,10 +345,10 @@ int srsran_pdcch_nr_encode(srsran_pdcch_nr_t* q, const srsran_dci_msg_nr_t* dci_
}
// Calculate...
q->K = dci_msg->nof_bits + 24U; // Payload size including CRC
q->M = (1U << dci_msg->location.L) * (SRSRAN_NRE - 3U) * 6U; // Number of RE
q->E = q->M * 2; // Number of Rate-Matched bits
uint32_t cinit = pdcch_nr_c_init(q, dci_msg); // Pseudo-random sequence initiation
q->K = dci_msg->nof_bits + 24U; // Payload size including CRC
q->M = (1U << dci_msg->ctx.location.L) * (SRSRAN_NRE - 3U) * 6U; // Number of RE
q->E = q->M * 2; // Number of Rate-Matched bits
uint32_t cinit = pdcch_nr_c_init(q, dci_msg); // Pseudo-random sequence initiation
// Get polar code
if (srsran_polar_code_get(&q->code, q->K, q->E, 9U) < SRSRAN_SUCCESS) {
@ -371,7 +371,7 @@ int srsran_pdcch_nr_encode(srsran_pdcch_nr_t* q, const srsran_dci_msg_nr_t* dci_
// Unpack RNTI
uint8_t unpacked_rnti[16] = {};
uint8_t* ptr = unpacked_rnti;
srsran_bit_unpack(dci_msg->rnti, &ptr, 16);
srsran_bit_unpack(dci_msg->ctx.rnti, &ptr, 16);
// Scramble CRC with RNTI
srsran_vec_xor_bbb(unpacked_rnti, &c[q->K - 16], &c[q->K - 16], 16);
@ -412,7 +412,7 @@ int srsran_pdcch_nr_encode(srsran_pdcch_nr_t* q, const srsran_dci_msg_nr_t* dci_
srsran_mod_modulate(&q->modem_table, q->f, q->symbols, q->E);
// Put symbols in grid
uint32_t m = pdcch_nr_cp(q, &dci_msg->location, slot_symbols, q->symbols, true);
uint32_t m = pdcch_nr_cp(q, &dci_msg->ctx.location, slot_symbols, q->symbols, true);
if (q->M != m) {
ERROR("Unmatch number of RE (%d != %d)", m, q->M);
return SRSRAN_ERROR;
@ -449,9 +449,9 @@ int srsran_pdcch_nr_decode(srsran_pdcch_nr_t* q,
}
// Calculate...
q->K = dci_msg->nof_bits + 24U; // Payload size including CRC
q->M = (1U << dci_msg->location.L) * (SRSRAN_NRE - 3U) * 6U; // Number of RE
q->E = q->M * 2; // Number of Rate-Matched bits
q->K = dci_msg->nof_bits + 24U; // Payload size including CRC
q->M = (1U << dci_msg->ctx.location.L) * (SRSRAN_NRE - 3U) * 6U; // Number of RE
q->E = q->M * 2; // Number of Rate-Matched bits
// Check number of estimates is correct
if (ce->nof_re != q->M) {
@ -466,7 +466,7 @@ int srsran_pdcch_nr_decode(srsran_pdcch_nr_t* q,
PDCCH_INFO_RX("K=%d; E=%d; M=%d; n=%d;", q->K, q->E, q->M, q->code.n);
// Get symbols from grid
uint32_t m = pdcch_nr_cp(q, &dci_msg->location, slot_symbols, q->symbols, false);
uint32_t m = pdcch_nr_cp(q, &dci_msg->ctx.location, slot_symbols, q->symbols, false);
if (q->M != m) {
ERROR("Unmatch number of RE (%d != %d)", m, q->M);
return SRSRAN_ERROR;
@ -546,7 +546,7 @@ int srsran_pdcch_nr_decode(srsran_pdcch_nr_t* q,
// Unpack RNTI
uint8_t unpacked_rnti[16] = {};
uint8_t* ptr = unpacked_rnti;
srsran_bit_unpack(dci_msg->rnti, &ptr, 16);
srsran_bit_unpack(dci_msg->ctx.rnti, &ptr, 16);
// De-Scramble CRC with RNTI
srsran_vec_xor_bbb(unpacked_rnti, &c[q->K - 16], &c[q->K - 16], 16);

@ -62,7 +62,7 @@ int srsran_ra_dl_nr_time_default_A(uint32_t m, srsran_dmrs_sch_typeA_pos_t dmrs_
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (m >= SRSRAN_MAX_NOF_DL_ALLOCATION) {
if (m >= SRSRAN_MAX_NOF_TIME_RA) {
ERROR("m (%d) is out-of-range", m);
return SRSRAN_ERROR_INVALID_INPUTS;
}
@ -89,10 +89,10 @@ int srsran_ra_dl_nr_time_default_A(uint32_t m, srsran_dmrs_sch_typeA_pos_t dmrs_
srsran_sch_mapping_type_B};
grant->mapping = pdsch_mapping_lut[m];
static uint32_t S_pos2[SRSRAN_MAX_NOF_DL_ALLOCATION] = {2, 2, 2, 2, 2, 9, 4, 5, 5, 9, 12, 1, 1, 2, 4, 8};
static uint32_t L_pos2[SRSRAN_MAX_NOF_DL_ALLOCATION] = {12, 10, 9, 7, 5, 4, 4, 7, 2, 2, 2, 13, 6, 4, 7, 4};
static uint32_t S_pos3[SRSRAN_MAX_NOF_DL_ALLOCATION] = {3, 3, 3, 3, 3, 10, 6, 5, 5, 9, 12, 1, 1, 2, 4, 8};
static uint32_t L_pos3[SRSRAN_MAX_NOF_DL_ALLOCATION] = {11, 9, 8, 6, 4, 4, 4, 7, 2, 2, 2, 13, 6, 4, 7, 4};
static uint32_t S_pos2[SRSRAN_MAX_NOF_TIME_RA] = {2, 2, 2, 2, 2, 9, 4, 5, 5, 9, 12, 1, 1, 2, 4, 8};
static uint32_t L_pos2[SRSRAN_MAX_NOF_TIME_RA] = {12, 10, 9, 7, 5, 4, 4, 7, 2, 2, 2, 13, 6, 4, 7, 4};
static uint32_t S_pos3[SRSRAN_MAX_NOF_TIME_RA] = {3, 3, 3, 3, 3, 10, 6, 5, 5, 9, 12, 1, 1, 2, 4, 8};
static uint32_t L_pos3[SRSRAN_MAX_NOF_TIME_RA] = {11, 9, 8, 6, 4, 4, 4, 7, 2, 2, 2, 13, 6, 4, 7, 4};
// Select start symbol (S) and length (L)
switch (dmrs_typeA_pos) {
@ -132,7 +132,7 @@ int srsran_ra_dl_nr_time(const srsran_sch_hl_cfg_nr_t* cfg,
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (m >= SRSRAN_MAX_NOF_DL_ALLOCATION) {
if (m >= SRSRAN_MAX_NOF_TIME_RA) {
ERROR("m (%d) is out-of-range", m);
return SRSRAN_ERROR_INVALID_INPUTS;
}
@ -177,7 +177,7 @@ int srsran_ra_dl_nr_time(const srsran_sch_hl_cfg_nr_t* cfg,
srsran_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant);
}
} else {
ERROR("Unhandled case");
ERROR("Unhandled case %s, ss_type=%d", srsran_rnti_type_str(rnti_type), ss_type);
}
// Validate S and L parameters
@ -264,7 +264,7 @@ int srsran_ra_dl_nr_freq(const srsran_carrier_nr_t* carrier,
}
// RA scheme
if (dci_dl->format == srsran_dci_format_nr_1_0) {
if (dci_dl->ctx.format == srsran_dci_format_nr_1_0) {
// when the scheduling grant is received with DCI format 1_0 , then downlink resource allocation type 1 is used.
return ra_helper_freq_type1(carrier->nof_prb, dci_dl->freq_domain_assigment, grant);
}

@ -653,9 +653,9 @@ int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrier,
{
// 5.2.1.1 Resource allocation in time domain
if (srsran_ra_dl_nr_time(pdsch_hl_cfg,
dci_dl->rnti_type,
dci_dl->search_space,
dci_dl->coreset_id,
dci_dl->ctx.rnti_type,
dci_dl->ctx.ss_type,
dci_dl->ctx.coreset_id,
dci_dl->time_domain_assigment,
pdsch_grant) < SRSRAN_SUCCESS) {
ERROR("Error computing time domain resource allocation");
@ -672,9 +672,9 @@ int srsran_ra_dl_dci_to_grant_nr(const srsran_carrier_nr_t* carrier,
// ...
pdsch_grant->nof_layers = 1;
pdsch_grant->dci_format = dci_dl->format;
pdsch_grant->rnti = dci_dl->rnti;
pdsch_grant->rnti_type = dci_dl->rnti_type;
pdsch_grant->dci_format = dci_dl->ctx.format;
pdsch_grant->rnti = dci_dl->ctx.rnti;
pdsch_grant->rnti_type = dci_dl->ctx.rnti_type;
pdsch_grant->tb[0].rv = dci_dl->rv;
// 5.1.4 PDSCH resource mapping
@ -705,7 +705,8 @@ ra_ul_dmrs(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, srsran_sch_grant_nr_t* pu
? pusch_hl_cfg->dmrs_typeA.present
: pusch_hl_cfg->dmrs_typeB.present;
if (pusch_grant->dci_format == srsran_dci_format_nr_0_0 || !dedicated_dmrs_present) {
if (pusch_grant->dci_format == srsran_dci_format_nr_0_0 || pusch_grant->dci_format == srsran_dci_format_nr_rar ||
!dedicated_dmrs_present) {
if (pusch_grant->mapping == srsran_sch_mapping_type_A) {
// Absent default values are defined is TS 38.331 - DMRS-DownlinkConfig
cfg->dmrs.additional_pos = srsran_dmrs_sch_add_pos_2;
@ -734,13 +735,13 @@ ra_ul_dmrs(const srsran_sch_hl_cfg_nr_t* pusch_hl_cfg, srsran_sch_grant_nr_t* pu
}
// Set number of DMRS CDM groups without data
if (pusch_grant->dci_format == srsran_dci_format_nr_0_0) {
if (pusch_grant->dci_format == srsran_dci_format_nr_0_0 || pusch_grant->dci_format == srsran_dci_format_nr_rar) {
if (srsran_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(cfg, pusch_grant) < SRSRAN_SUCCESS) {
ERROR("Error loading number of DMRS CDM groups");
return SRSRAN_ERROR;
}
} else {
ERROR("Invalid case");
ERROR("DCI format not implemented %s", srsran_dci_format_nr_string(pusch_grant->dci_format));
return SRSRAN_ERROR;
}
@ -761,9 +762,9 @@ int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrier,
{
// 5.2.1.1 Resource allocation in time domain
if (srsran_ra_ul_nr_time(pusch_hl_cfg,
dci_ul->rnti_type,
dci_ul->search_space,
dci_ul->coreset_id,
dci_ul->ctx.rnti_type,
dci_ul->ctx.ss_type,
dci_ul->ctx.coreset_id,
dci_ul->time_domain_assigment,
pusch_grant) < SRSRAN_SUCCESS) {
ERROR("Error computing time domain resource allocation");
@ -780,9 +781,9 @@ int srsran_ra_ul_dci_to_grant_nr(const srsran_carrier_nr_t* carrier,
// ...
pusch_grant->nof_layers = 1;
pusch_grant->dci_format = dci_ul->format;
pusch_grant->rnti = dci_ul->rnti;
pusch_grant->rnti_type = dci_ul->rnti_type;
pusch_grant->dci_format = dci_ul->ctx.format;
pusch_grant->rnti = dci_ul->ctx.rnti;
pusch_grant->rnti_type = dci_ul->ctx.rnti_type;
// 5.1.6.2 DM-RS reception procedure
if (ra_ul_dmrs(pusch_hl_cfg, pusch_grant, pusch_cfg) < SRSRAN_SUCCESS) {

@ -132,7 +132,7 @@ int srsran_ra_ul_nr_time(const srsran_sch_hl_cfg_nr_t* cfg,
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (m >= SRSRAN_MAX_NOF_DL_ALLOCATION) {
if (m >= SRSRAN_MAX_NOF_TIME_RA) {
ERROR("m (%d) is out-of-range", m);
return SRSRAN_ERROR_INVALID_INPUTS;
}
@ -142,12 +142,12 @@ int srsran_ra_ul_nr_time(const srsran_sch_hl_cfg_nr_t* cfg,
// Row 1
if (cfg->nof_common_time_ra == 0) {
srsran_ra_ul_nr_pusch_time_resource_default_A(cfg->scs_cfg, m, grant);
} else if (m < SRSRAN_MAX_NOF_DL_ALLOCATION && m < cfg->nof_common_time_ra) {
} else if (m < SRSRAN_MAX_NOF_TIME_RA && m < cfg->nof_common_time_ra) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
} else {
ERROR("Time domain resource selection (m=%d) exceeds the maximum value (%d)",
m,
SRSRAN_MIN(cfg->nof_common_time_ra, SRSRAN_MAX_NOF_DL_ALLOCATION));
SRSRAN_MIN(cfg->nof_common_time_ra, SRSRAN_MAX_NOF_TIME_RA));
}
} else if ((rnti_type == srsran_rnti_type_c || rnti_type == srsran_rnti_type_mcs_c ||
rnti_type == srsran_rnti_type_tc || rnti_type == srsran_rnti_type_cs) &&
@ -155,7 +155,7 @@ int srsran_ra_ul_nr_time(const srsran_sch_hl_cfg_nr_t* cfg,
// Row 2
if (cfg->nof_common_time_ra == 0) {
srsran_ra_ul_nr_pusch_time_resource_default_A(cfg->scs_cfg, m, grant);
} else if (m < SRSRAN_MAX_NOF_DL_ALLOCATION) {
} else if (m < SRSRAN_MAX_NOF_TIME_RA) {
ra_ul_nr_time_hl(&cfg->common_time_ra[m], grant);
}
} else if ((rnti_type == srsran_rnti_type_c || rnti_type == srsran_rnti_type_mcs_c ||
@ -374,12 +374,12 @@ int srsran_ra_ul_nr_freq(const srsran_carrier_nr_t* carrier,
}
// RA scheme
if (dci_ul->format == srsran_dci_format_nr_0_0) {
if (dci_ul->ctx.format == srsran_dci_format_nr_0_0 || dci_ul->ctx.format == srsran_dci_format_nr_rar) {
// when the scheduling grant is received with DCI format 1_0 , then downlink resource allocation type 1 is used.
return ra_helper_freq_type1(carrier->nof_prb, dci_ul->freq_domain_assigment, grant);
}
ERROR("Only DCI Format 0_0 is supported");
ERROR("Unhandled DCI Format %s", srsran_dci_format_nr_string(dci_ul->ctx.format));
return SRSRAN_ERROR;
}

@ -616,6 +616,10 @@ endif(RF_FOUND)
# NR
########################################################################
add_executable(dci_nr_test dci_nr_test.c)
target_link_libraries(dci_nr_test srsran_phy)
add_nr_test(dci_nr_test dci_nr_test)
add_executable(pucch_nr_test pucch_nr_test.c)
target_link_libraries(pucch_nr_test srsran_phy)
add_nr_test(pucch_nr_test pucch_nr_test)

@ -0,0 +1,53 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsran/common/test_common.h"
#include "srsran/phy/phch/dci_nr.h"
static int test_52prb()
{
// Default configuration with all options disabled
srsran_dci_cfg_nr_t cfg = {};
// Set bandwidths
cfg.coreset0_bw = 0;
cfg.bwp_dl_initial_bw = 52;
cfg.bwp_dl_active_bw = 52;
cfg.bwp_ul_initial_bw = 52;
cfg.bwp_ul_active_bw = 52;
// Enable all monitoring
cfg.monitor_common_0_0 = true;
cfg.monitor_0_0_and_1_0 = true;
cfg.monitor_0_1_and_1_1 = true;
// Configure DCI
srsran_dci_nr_t dci = {};
TESTASSERT(srsran_dci_nr_set_cfg(&dci, &cfg) == SRSRAN_SUCCESS);
// Check DCI sizes
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_common_3, srsran_dci_format_nr_0_0) == 39);
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_common_3, srsran_dci_format_nr_1_0) == 39);
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_ue, srsran_dci_format_nr_0_0) == 39);
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_ue, srsran_dci_format_nr_1_0) == 39);
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_ue, srsran_dci_format_nr_0_1) == 28);
TESTASSERT(srsran_dci_nr_size(&dci, srsran_search_space_type_ue, srsran_dci_format_nr_1_1) == 26);
return SRSRAN_SUCCESS;
}
int main(int argc, char** argv)
{
TESTASSERT(test_52prb() == SRSRAN_SUCCESS);
return SRSRAN_SUCCESS;
}

@ -43,8 +43,8 @@ static int test(srsran_pdcch_nr_t* tx,
// Encode PDCCH
TESTASSERT(srsran_pdcch_nr_encode(tx, dci_msg_tx, grid) == SRSRAN_SUCCESS);
enc_time[dci_msg_tx->location.L].time_us += tx->meas_time_us;
enc_time[dci_msg_tx->location.L].count++;
enc_time[dci_msg_tx->ctx.location.L].time_us += tx->meas_time_us;
enc_time[dci_msg_tx->ctx.location.L].count++;
// Init Rx MSG
srsran_pdcch_nr_res_t res = {};
@ -54,8 +54,8 @@ static int test(srsran_pdcch_nr_t* tx,
// Decode PDCCH
TESTASSERT(srsran_pdcch_nr_decode(rx, grid, ce, &dci_msg_rx, &res) == SRSRAN_SUCCESS);
dec_time[dci_msg_tx->location.L].time_us += rx->meas_time_us;
dec_time[dci_msg_tx->location.L].count++;
dec_time[dci_msg_tx->ctx.location.L].time_us += rx->meas_time_us;
dec_time[dci_msg_tx->ctx.location.L].count++;
// Assert
TESTASSERT(res.evm < 0.01f);
@ -142,8 +142,27 @@ int main(int argc, char** argv)
}
for (coreset.duration = SRSRAN_CORESET_DURATION_MIN; coreset.duration <= SRSRAN_CORESET_DURATION_MAX;
coreset.duration++) {
srsran_search_space_t search_space = {};
search_space.type = srsran_search_space_type_ue;
srsran_search_space_t search_space = {};
search_space.type = srsran_search_space_type_ue;
search_space.formats[search_space.nof_formats++] = srsran_dci_format_nr_0_0;
search_space.formats[search_space.nof_formats++] = srsran_dci_format_nr_1_0;
srsran_dci_cfg_nr_t dci_cfg = {};
dci_cfg.coreset0_bw = 0;
dci_cfg.bwp_dl_initial_bw = carrier.nof_prb;
dci_cfg.bwp_dl_active_bw = carrier.nof_prb;
dci_cfg.bwp_ul_initial_bw = carrier.nof_prb;
dci_cfg.bwp_ul_active_bw = carrier.nof_prb;
dci_cfg.monitor_common_0_0 = true;
dci_cfg.monitor_0_0_and_1_0 = true;
dci_cfg.monitor_0_1_and_1_1 = true;
// Precompute DCI sizes
srsran_dci_nr_t dci = {};
if (srsran_dci_nr_set_cfg(&dci, &dci_cfg) < SRSRAN_SUCCESS) {
ERROR("Error setting DCI configuratio");
goto clean_exit;
}
if (srsran_pdcch_nr_set_carrier(&pdcch_tx, &carrier, &coreset) < SRSRAN_SUCCESS) {
ERROR("Error setting carrier");
@ -185,11 +204,11 @@ int main(int argc, char** argv)
for (uint32_t ncce_idx = 0; ncce_idx < n; ncce_idx++) {
// Init MSG
srsran_dci_msg_nr_t dci_msg = {};
dci_msg.format = srsran_dci_format_nr_1_0;
dci_msg.rnti_type = srsran_rnti_type_c;
dci_msg.location.L = aggregation_level;
dci_msg.location.ncce = dci_locations[ncce_idx];
dci_msg.nof_bits = srsran_dci_nr_format_1_0_sizeof(&carrier, &coreset, dci_msg.rnti_type);
dci_msg.ctx.format = srsran_dci_format_nr_1_0;
dci_msg.ctx.rnti_type = srsran_rnti_type_c;
dci_msg.ctx.location.L = aggregation_level;
dci_msg.ctx.location.ncce = dci_locations[ncce_idx];
dci_msg.nof_bits = srsran_dci_nr_size(&dci, search_space.type, srsran_dci_format_nr_1_0);
// Generate random payload
for (uint32_t i = 0; i < dci_msg.nof_bits; i++) {

@ -165,7 +165,9 @@ int srsran_ue_dl_nr_set_carrier(srsran_ue_dl_nr_t* q, const srsran_carrier_nr_t*
return SRSRAN_SUCCESS;
}
int srsran_ue_dl_nr_set_pdcch_config(srsran_ue_dl_nr_t* q, const srsran_ue_dl_nr_pdcch_cfg_t* cfg)
int srsran_ue_dl_nr_set_pdcch_config(srsran_ue_dl_nr_t* q,
const srsran_pdcch_cfg_nr_t* cfg,
const srsran_dci_cfg_nr_t* dci_cfg)
{
if (q == NULL || cfg == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
@ -176,13 +178,22 @@ int srsran_ue_dl_nr_set_pdcch_config(srsran_ue_dl_nr_t* q, const srsran_ue_dl_nr
// iterate over all possible CORESET and initialise/update the present ones
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; i++) {
if (cfg->coreset_present[i]) {
if (srsran_dmrs_pdcch_estimator_init(&q->dmrs_pdcch[i], &q->carrier, &cfg->coreset[i]) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
// Skip CORESET if not present
if (!cfg->coreset_present[i]) {
continue;
}
// Initialise estimator for the CORESET
if (srsran_dmrs_pdcch_estimator_init(&q->dmrs_pdcch[i], &q->carrier, &cfg->coreset[i]) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
}
// Configure DCI sizes
if (srsran_dci_nr_set_cfg(&q->dci, dci_cfg) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
@ -220,28 +231,28 @@ static int ue_dl_nr_find_dci_ncce(srsran_ue_dl_nr_t* q,
return SRSRAN_ERROR;
}
SRSRAN_MEM_ZERO(pdcch_info, srsran_ue_dl_nr_pdcch_info_t, 1);
pdcch_info->coreset_id = dci_msg->coreset_id;
pdcch_info->ss_id = dci_msg->search_space;
pdcch_info->location = dci_msg->location;
pdcch_info->dci_ctx = dci_msg->ctx;
pdcch_info->nof_bits = dci_msg->nof_bits;
srsran_dmrs_pdcch_measure_t* m = &pdcch_info->measure;
// Measures the PDCCH transmission DMRS
if (srsran_dmrs_pdcch_get_measure(&q->dmrs_pdcch[coreset_id], &dci_msg->location, m) < SRSRAN_SUCCESS) {
ERROR("Error getting measure location L=%d, ncce=%d", dci_msg->location.L, dci_msg->location.ncce);
srsran_dci_location_t location = dci_msg->ctx.location;
if (srsran_dmrs_pdcch_get_measure(&q->dmrs_pdcch[coreset_id], &location, m) < SRSRAN_SUCCESS) {
ERROR("Error getting measure location L=%d, ncce=%d", location.L, location.ncce);
return SRSRAN_ERROR;
}
// If measured correlation is invalid, early return
if (!isnormal(m->norm_corr)) {
INFO("Discarded PDCCH candidate L=%d;ncce=%d; Invalid measurement;", dci_msg->location.L, dci_msg->location.ncce);
INFO("Discarded PDCCH candidate L=%d;ncce=%d; Invalid measurement;", location.L, location.ncce);
return SRSRAN_SUCCESS;
}
// Compare EPRE with threshold
if (m->epre_dBfs < q->pdcch_dmrs_epre_thr) {
INFO("Discarded PDCCH candidate L=%d;ncce=%d; EPRE is too weak (%.1f<%.1f);",
dci_msg->location.L,
dci_msg->location.ncce,
location.L,
location.ncce,
m->epre_dBfs,
q->pdcch_dmrs_epre_thr);
return SRSRAN_SUCCESS;
@ -250,8 +261,8 @@ static int ue_dl_nr_find_dci_ncce(srsran_ue_dl_nr_t* q,
// Compare DMRS correlation with threshold
if (m->norm_corr < q->pdcch_dmrs_corr_thr) {
INFO("Discarded PDCCH candidate L=%d;ncce=%d; Correlation is too low (%.1f<%.1f); EPRE=%+.2f; RSRP=%+.2f;",
dci_msg->location.L,
dci_msg->location.ncce,
location.L,
location.ncce,
m->norm_corr,
q->pdcch_dmrs_corr_thr,
m->epre_dBfs,
@ -260,7 +271,7 @@ static int ue_dl_nr_find_dci_ncce(srsran_ue_dl_nr_t* q,
}
// Extract PDCCH channel estimates
if (srsran_dmrs_pdcch_get_ce(&q->dmrs_pdcch[coreset_id], &dci_msg->location, q->pdcch_ce) < SRSRAN_SUCCESS) {
if (srsran_dmrs_pdcch_get_ce(&q->dmrs_pdcch[coreset_id], &location, q->pdcch_ce) < SRSRAN_SUCCESS) {
ERROR("Error extracting PDCCH DMRS");
return SRSRAN_ERROR;
}
@ -293,12 +304,15 @@ static bool find_dci_msg(srsran_dci_msg_nr_t* dci_msg, uint32_t nof_dci_msg, srs
return found;
}
static int ue_dl_nr_find_dl_dci_ss(srsran_ue_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_search_space_t* search_space,
uint16_t rnti,
srsran_rnti_type_t rnti_type)
static int ue_dl_nr_find_dci_ss(srsran_ue_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_search_space_t* search_space,
uint16_t rnti,
srsran_rnti_type_t rnti_type)
{
uint32_t dci_sizes[SRSRAN_DCI_NR_MAX_NOF_SIZES] = {};
uint32_t dci_sizes_count = 0;
// Select CORESET
uint32_t coreset_id = search_space->coreset_id;
if (coreset_id >= SRSRAN_UE_DL_NR_MAX_NOF_CORESET || !q->cfg.coreset_present[coreset_id]) {
@ -313,81 +327,124 @@ static int ue_dl_nr_find_dl_dci_ss(srsran_ue_dl_nr_t* q,
return SRSRAN_ERROR;
}
// Hard-coded values
srsran_dci_format_nr_t dci_format = srsran_dci_format_nr_1_0;
// Iterate all possible formats
for (uint32_t format_idx = 0; format_idx < SRSRAN_MIN(search_space->nof_formats, SRSRAN_DCI_FORMAT_NR_COUNT);
format_idx++) {
srsran_dci_format_nr_t dci_format = search_space->formats[format_idx];
// Calculate number of DCI bits
int dci_nof_bits = srsran_dci_nr_format_1_0_sizeof(&q->carrier, coreset, rnti_type);
if (dci_nof_bits <= SRSRAN_SUCCESS) {
ERROR("Error DCI size");
return SRSRAN_ERROR;
}
// Iterate all possible aggregation levels
for (uint32_t L = 0; L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR && q->dci_msg_count < SRSRAN_MAX_DCI_MSG_NR;
L++) {
// Calculate possible PDCCH DCI candidates
uint32_t candidates[SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {};
int nof_candidates = srsran_pdcch_nr_locations_coreset(
coreset, search_space, rnti, L, SRSRAN_SLOT_NR_MOD(q->carrier.numerology, slot_cfg->idx), candidates);
if (nof_candidates < SRSRAN_SUCCESS) {
ERROR("Error calculating DCI candidate location");
// Calculate number of DCI bits
uint32_t dci_nof_bits = srsran_dci_nr_size(&q->dci, search_space->type, dci_format);
if (dci_nof_bits == 0) {
ERROR("Error DCI size");
return SRSRAN_ERROR;
}
// Iterate over the candidates
for (int ncce_idx = 0; ncce_idx < nof_candidates && q->dci_msg_count < SRSRAN_MAX_DCI_MSG_NR; ncce_idx++) {
// Set DCI context
srsran_dci_msg_nr_t dci_msg = {};
dci_msg.location.L = L;
dci_msg.location.ncce = candidates[ncce_idx];
dci_msg.search_space = search_space->type;
dci_msg.coreset_id = search_space->coreset_id;
dci_msg.rnti_type = rnti_type;
dci_msg.rnti = rnti;
dci_msg.format = dci_format;
dci_msg.nof_bits = (uint32_t)dci_nof_bits;
// Find and decode PDCCH transmission in the given ncce
srsran_pdcch_nr_res_t res = {};
if (ue_dl_nr_find_dci_ncce(q, &dci_msg, &res, coreset_id) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
// Skip DCI format if the size was already searched for the search space
bool skip = false;
for (uint32_t i = 0; i < dci_sizes_count && !skip; i++) {
if (dci_nof_bits == dci_sizes[i]) {
skip = true;
}
}
if (skip) {
continue;
}
// If the CRC was not match, move to next candidate
if (!res.crc) {
continue;
// Append size
if (dci_sizes_count >= SRSRAN_DCI_NR_MAX_NOF_SIZES) {
ERROR("Exceed maximum number of DCI sizes");
return SRSRAN_ERROR;
}
dci_sizes[dci_sizes_count++] = dci_nof_bits;
// Iterate all possible aggregation levels
for (uint32_t L = 0;
L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR && q->dl_dci_msg_count < SRSRAN_MAX_DCI_MSG_NR;
L++) {
// Calculate possible PDCCH DCI candidates
uint32_t candidates[SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {};
int nof_candidates = srsran_pdcch_nr_locations_coreset(
coreset, search_space, rnti, L, SRSRAN_SLOT_NR_MOD(q->carrier.numerology, slot_cfg->idx), candidates);
if (nof_candidates < SRSRAN_SUCCESS) {
ERROR("Error calculating DCI candidate location");
return SRSRAN_ERROR;
}
// Detect if the DCI was a format 0_0
if (!srsran_dci_nr_format_1_0_valid(&dci_msg)) {
// Change grant format to 0_0
dci_msg.format = srsran_dci_format_nr_0_0;
// Iterate over the candidates
for (int ncce_idx = 0; ncce_idx < nof_candidates && q->dl_dci_msg_count < SRSRAN_MAX_DCI_MSG_NR; ncce_idx++) {
// Build DCI context
srsran_dci_ctx_t ctx = {};
ctx.location.L = L;
ctx.location.ncce = candidates[ncce_idx];
ctx.ss_type = search_space->type;
ctx.coreset_id = search_space->coreset_id;
ctx.rnti_type = rnti_type;
ctx.rnti = rnti;
ctx.format = dci_format;
// Build DCI message
srsran_dci_msg_nr_t dci_msg = {};
dci_msg.ctx = ctx;
dci_msg.nof_bits = (uint32_t)dci_nof_bits;
// Find and decode PDCCH transmission in the given ncce
srsran_pdcch_nr_res_t res = {};
if (ue_dl_nr_find_dci_ncce(q, &dci_msg, &res, coreset_id) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
// If the pending UL grant list is full or has the dci message, keep moving
if (q->pending_ul_dci_count >= SRSRAN_MAX_DCI_MSG_NR ||
find_dci_msg(q->pending_ul_dci_msg, q->pending_ul_dci_count, &dci_msg)) {
// If the CRC was not match, move to next candidate
if (!res.crc) {
continue;
}
// Save the grant in the pending UL grant list
q->pending_ul_dci_msg[q->pending_ul_dci_count] = dci_msg;
q->pending_ul_dci_count++;
// Detect if the DCI is the right direction
if (!srsran_dci_nr_valid_direction(&dci_msg)) {
// Change grant format direction
switch (dci_msg.ctx.format) {
case srsran_dci_format_nr_0_0:
dci_msg.ctx.format = srsran_dci_format_nr_1_0;
break;
case srsran_dci_format_nr_0_1:
dci_msg.ctx.format = srsran_dci_format_nr_1_1;
break;
case srsran_dci_format_nr_1_0:
dci_msg.ctx.format = srsran_dci_format_nr_0_0;
break;
case srsran_dci_format_nr_1_1:
dci_msg.ctx.format = srsran_dci_format_nr_0_1;
break;
default:
continue;
}
}
// Move to next candidate
continue;
}
// If UL grant, enqueue in UL list
if (dci_msg.ctx.format == srsran_dci_format_nr_0_0 || dci_msg.ctx.format == srsran_dci_format_nr_0_1) {
// If the pending UL grant list is full or has the dci message, keep moving
if (q->ul_dci_count >= SRSRAN_MAX_DCI_MSG_NR || find_dci_msg(q->ul_dci_msg, q->ul_dci_count, &dci_msg)) {
continue;
}
// Check if the grant exists already in the message list
if (find_dci_msg(q->dci_msg, q->dci_msg_count, &dci_msg)) {
// The same DCI is in the list, keep moving
continue;
}
// Save the grant in the pending UL grant list
q->ul_dci_msg[q->ul_dci_count] = dci_msg;
q->ul_dci_count++;
INFO("Found DCI in L=%d,ncce=%d", dci_msg.location.L, dci_msg.location.ncce);
// Append DCI message into the list
q->dci_msg[q->dci_msg_count] = dci_msg;
q->dci_msg_count++;
// Move to next candidate
continue;
}
// Check if the grant exists already in the DL list
if (find_dci_msg(q->dl_dci_msg, q->dl_dci_msg_count, &dci_msg)) {
// The same DCI is in the list, keep moving
continue;
}
INFO("Found DCI in L=%d,ncce=%d", dci_msg.ctx.location.L, dci_msg.ctx.location.ncce);
// Append DCI message into the list
q->dl_dci_msg[q->dl_dci_msg_count] = dci_msg;
q->dl_dci_msg_count++;
}
}
}
@ -410,27 +467,27 @@ int srsran_ue_dl_nr_find_dl_dci(srsran_ue_dl_nr_t* q,
nof_dci_msg = SRSRAN_MIN(nof_dci_msg, SRSRAN_MAX_DCI_MSG_NR);
// Reset grant and blind search information counters
q->dci_msg_count = 0;
q->dl_dci_msg_count = 0;
q->pdcch_info_count = 0;
// If the UE looks for a RAR and RA search space is provided, search for it
if (q->cfg.ra_search_space_present && rnti_type == srsran_rnti_type_ra) {
// Find DCIs in the RA search space
int ret = ue_dl_nr_find_dl_dci_ss(q, slot_cfg, &q->cfg.ra_search_space, rnti, rnti_type);
int ret = ue_dl_nr_find_dci_ss(q, slot_cfg, &q->cfg.ra_search_space, rnti, rnti_type);
if (ret < SRSRAN_SUCCESS) {
ERROR("Error searching RAR DCI");
return SRSRAN_ERROR;
}
} else {
// Iterate all possible common and UE search spaces
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE && q->dci_msg_count < nof_dci_msg; i++) {
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE && q->dl_dci_msg_count < nof_dci_msg; i++) {
// Skip search space if not present
if (!q->cfg.search_space_present[i]) {
continue;
}
// Find DCIs in the selected search space
int ret = ue_dl_nr_find_dl_dci_ss(q, slot_cfg, &q->cfg.search_space[i], rnti, rnti_type);
int ret = ue_dl_nr_find_dci_ss(q, slot_cfg, &q->cfg.search_space[i], rnti, rnti_type);
if (ret < SRSRAN_SUCCESS) {
ERROR("Error searching DCI");
return SRSRAN_ERROR;
@ -439,10 +496,12 @@ int srsran_ue_dl_nr_find_dl_dci(srsran_ue_dl_nr_t* q,
}
// Convert found DCI messages into DL grants
uint32_t dci_msg_count = SRSRAN_MIN(nof_dci_msg, q->dci_msg_count);
uint32_t dci_msg_count = SRSRAN_MIN(nof_dci_msg, q->dl_dci_msg_count);
for (uint32_t i = 0; i < dci_msg_count; i++) {
const srsran_coreset_t* coreset = &q->cfg.coreset[q->dci_msg[i].coreset_id];
srsran_dci_nr_format_1_0_unpack(&q->carrier, coreset, &q->dci_msg[i], &dci_dl_list[i]);
if (srsran_dci_nr_dl_unpack(&q->dci, &q->dl_dci_msg[i], &dci_dl_list[i]) < SRSRAN_SUCCESS) {
ERROR("Error unpacking grant %d;", i);
return SRSRAN_ERROR;
}
}
return (int)dci_msg_count;
@ -463,15 +522,14 @@ int srsran_ue_dl_nr_find_ul_dci(srsran_ue_dl_nr_t* q,
}
// Get DCI messages from the pending list
for (uint32_t i = 0; i < q->pending_ul_dci_count && count < nof_dci_msg; i++) {
srsran_dci_msg_nr_t* dci_msg = &q->pending_ul_dci_msg[i];
for (uint32_t i = 0; i < q->ul_dci_count && count < nof_dci_msg; i++) {
srsran_dci_msg_nr_t* dci_msg = &q->ul_dci_msg[i];
if (dci_msg->rnti_type != rnti_type || dci_msg->rnti != rnti) {
if (dci_msg->ctx.rnti_type != rnti_type || dci_msg->ctx.rnti != rnti) {
continue;
}
const srsran_coreset_t* coreset = &q->cfg.coreset[dci_msg->coreset_id];
if (srsran_dci_nr_format_0_0_unpack(&q->carrier, coreset, dci_msg, &dci_ul_list[count]) < SRSRAN_SUCCESS) {
if (srsran_dci_nr_ul_unpack(&q->dci, dci_msg, &dci_ul_list[count]) < SRSRAN_SUCCESS) {
ERROR("Unpacking DCI 0_0");
continue;
}
@ -479,7 +537,7 @@ int srsran_ue_dl_nr_find_ul_dci(srsran_ue_dl_nr_t* q,
}
// Reset pending UL grant list
q->pending_ul_dci_count = 0;
q->ul_dci_count = 0;
return count;
}
@ -638,7 +696,7 @@ static int ue_dl_nr_gen_ack_type2(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg,
int ue_dl_nr_pdsch_k1(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg, const srsran_dci_dl_nr_t* dci_dl)
{
// For DCI format 1_0, the PDSCH-to-HARQ_feedback timing indicator field values map to {1, 2, 3, 4, 5, 6, 7, 8}
if (dci_dl->format == srsran_dci_format_nr_1_0) {
if (dci_dl->ctx.format == srsran_dci_format_nr_1_0) {
return (int)dci_dl->harq_feedback + 1;
}
@ -668,10 +726,10 @@ int srsran_ue_dl_nr_pdsch_ack_resource(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg
}
// Fill PDSCH resource
pdsch_ack_resource->dci_format_1_1 = (dci_dl->format == srsran_dci_format_nr_1_1);
pdsch_ack_resource->dci_format_1_1 = (dci_dl->ctx.format == srsran_dci_format_nr_1_1);
pdsch_ack_resource->k1 = k1;
pdsch_ack_resource->v_dai_dl = dci_dl->dai;
pdsch_ack_resource->rnti = dci_dl->rnti;
pdsch_ack_resource->rnti = dci_dl->ctx.rnti;
pdsch_ack_resource->pucch_resource_id = dci_dl->pucch_resource;
return SRSRAN_SUCCESS;
@ -687,14 +745,14 @@ int srsran_ue_dl_nr_gen_ack(const srsran_ue_dl_nr_harq_ack_cfg_t* cfg,
}
// According TS 38.213 9.1.2 Type-1 HARQ-ACK codebook determination
if (cfg->pdsch_harq_ack_codebook == srsran_pdsch_harq_ack_codebook_semi_static) {
if (cfg->harq_ack_codebook == srsran_pdsch_harq_ack_codebook_semi_static) {
// This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = semi-static.
ERROR("Type-1 HARQ-ACK codebook determination is NOT implemented");
return SRSRAN_ERROR;
}
// According TS 38.213 9.1.3 Type-2 HARQ-ACK codebook determination
if (cfg->pdsch_harq_ack_codebook == srsran_pdsch_harq_ack_codebook_dynamic) {
if (cfg->harq_ack_codebook == srsran_pdsch_harq_ack_codebook_dynamic) {
// This clause applies if the UE is configured with pdsch-HARQ-ACK-Codebook = dynamic.
return ue_dl_nr_gen_ack_type2(cfg, ack_info, uci_data);
}

@ -110,7 +110,7 @@ int make_phy_harq_ack_cfg_test()
srsran_ue_dl_nr_harq_ack_cfg_t srsran_ue_dl_nr_harq_ack_cfg;
TESTASSERT(make_phy_harq_ack_cfg(phys_cell_group_cfg, &srsran_ue_dl_nr_harq_ack_cfg) == true);
TESTASSERT(srsran_ue_dl_nr_harq_ack_cfg.pdsch_harq_ack_codebook == srsran_pdsch_harq_ack_codebook_dynamic);
TESTASSERT(srsran_ue_dl_nr_harq_ack_cfg.harq_ack_codebook == srsran_pdsch_harq_ack_codebook_dynamic);
return SRSRAN_SUCCESS;
}

@ -118,12 +118,12 @@ static int work_gnb_dl(srsran_enb_dl_nr_t* enb_dl,
// Hard-coded values
srsran_dci_dl_nr_t dci_dl = {};
dci_dl.rnti = pdsch_cfg.grant.rnti;
dci_dl.rnti_type = pdsch_cfg.grant.rnti_type;
dci_dl.format = srsran_dci_format_nr_1_0;
dci_dl.location = *dci_location;
dci_dl.search_space = search_space->type;
dci_dl.coreset_id = 1;
dci_dl.ctx.rnti = pdsch_cfg.grant.rnti;
dci_dl.ctx.rnti_type = pdsch_cfg.grant.rnti_type;
dci_dl.ctx.format = srsran_dci_format_nr_1_0;
dci_dl.ctx.location = *dci_location;
dci_dl.ctx.ss_type = search_space->type;
dci_dl.ctx.coreset_id = 1;
dci_dl.freq_domain_assigment = 0;
dci_dl.time_domain_assigment = 0;
dci_dl.vrb_to_prb_mapping = 0;
@ -216,7 +216,7 @@ int main(int argc, char** argv)
goto clean_exit;
}
srsran_ue_dl_nr_pdcch_cfg_t pdcch_cfg = {};
srsran_pdcch_cfg_nr_t pdcch_cfg = {};
// Configure CORESET
srsran_coreset_t* coreset = &pdcch_cfg.coreset[1];
@ -232,6 +232,9 @@ int main(int argc, char** argv)
search_space->id = 0;
search_space->coreset_id = 1;
search_space->type = srsran_search_space_type_common_3;
search_space->formats[0] = srsran_dci_format_nr_0_0;
search_space->formats[1] = srsran_dci_format_nr_1_0;
search_space->nof_formats = 2;
for (uint32_t L = 0; L < SRSRAN_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) {
search_space->nof_candidates[L] = srsran_pdcch_nr_max_candidates_coreset(coreset, L);
}
@ -249,9 +252,14 @@ int main(int argc, char** argv)
if (srsran_ue_dl_nr_set_carrier(&ue_dl, &carrier)) {
ERROR("Error setting SCH NR carrier");
goto clean_exit;
goto clean_exit;
}
if (srsran_ue_dl_nr_set_pdcch_config(&ue_dl, &pdcch_cfg)) {
srsran_dci_cfg_nr_t dci_cfg = {};
dci_cfg.bwp_dl_initial_bw = carrier.nof_prb;
dci_cfg.bwp_ul_initial_bw = carrier.nof_prb;
dci_cfg.monitor_common_0_0 = true;
if (srsran_ue_dl_nr_set_pdcch_config(&ue_dl, &pdcch_cfg, &dci_cfg)) {
ERROR("Error setting CORESET");
goto clean_exit;
}
@ -261,7 +269,7 @@ int main(int argc, char** argv)
goto clean_exit;
}
if (srsran_enb_dl_nr_set_coreset(&enb_dl, coreset)) {
if (srsran_enb_dl_nr_set_pdcch_config(&enb_dl, &pdcch_cfg, &dci_cfg)) {
ERROR("Error setting CORESET");
goto clean_exit;
}
@ -346,15 +354,21 @@ int main(int argc, char** argv)
}
// Compute PDCCH candidate locations
uint32_t L = 0;
uint32_t L = 1;
uint32_t ncce_candidates[SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR] = {};
int nof_candidates = srsran_pdcch_nr_locations_coreset(
coreset, search_space, pdsch_cfg.grant.rnti, L, slot.idx, ncce_candidates);
int nof_candidates = srsran_pdcch_nr_locations_coreset(coreset,
search_space,
pdsch_cfg.grant.rnti,
L,
SRSRAN_SLOT_NR_MOD(carrier.numerology, slot.idx),
ncce_candidates);
if (nof_candidates < SRSRAN_SUCCESS) {
ERROR("Error getting PDCCH candidates");
goto clean_exit;
}
srsran_vec_fprint_i(stdout, (int*)ncce_candidates, nof_candidates);
// Setup DCI location
srsran_dci_location_t dci_location = {};
dci_location.ncce = ncce_candidates[0];

@ -14,8 +14,10 @@
#define SRSENB_NR_CC_WORKER_H
#include "srsran/interfaces/gnb_interfaces.h"
#include "srsran/interfaces/rrc_nr_interface_types.h"
#include "srsran/phy/enb/enb_dl_nr.h"
#include "srsran/srslog/srslog.h"
#include "srsran/srsran.h"
#include <array>
#include <vector>
@ -27,15 +29,11 @@ typedef struct {
srsran_enb_dl_nr_args_t dl;
} phy_nr_args_t;
typedef struct {
srsran_sch_hl_cfg_nr_t pdsch;
} phy_nr_cfg_t;
class phy_nr_state
{
public:
phy_nr_args_t args = {};
phy_nr_cfg_t cfg = {};
phy_nr_args_t args = {};
srsran::phy_cfg_nr_t cfg = {};
phy_nr_state()
{
@ -44,8 +42,7 @@ public:
args.dl.nof_tx_antennas = 1;
args.dl.pdsch.measure_evm = true;
args.dl.pdsch.measure_time = true;
args.dl.pdsch.sch.disable_simd = true;
cfg.pdsch.sch_cfg.mcs_table = srsran_mcs_table_256qam;
args.dl.pdsch.sch.disable_simd = false;
}
};

@ -60,7 +60,8 @@ bool cc_worker::set_carrier(const srsran_carrier_nr_t* carrier)
coreset.freq_resources[0] = true; // Enable the bottom 6 PRB for PDCCH
coreset.duration = 2;
if (srsran_enb_dl_nr_set_coreset(&enb_dl, &coreset) < SRSRAN_SUCCESS) {
srsran_dci_cfg_nr_t dci_cfg = phy_state->cfg.get_dci_cfg(*carrier);
if (srsran_enb_dl_nr_set_pdcch_config(&enb_dl, &phy_state->cfg.pdcch, &dci_cfg) < SRSRAN_SUCCESS) {
ERROR("Error setting coreset");
return false;
}

@ -100,17 +100,17 @@ void sf_worker::work_imp()
grants.pdsch[0].softbuffer_tx[0] = &softbuffer_tx;
srsran_softbuffer_tx_reset(&softbuffer_tx);
grants.pdsch[0].dci.rnti = 0x1234;
grants.pdsch[0].dci.format = srsran_dci_format_nr_1_0;
grants.pdsch[0].dci.ctx.rnti = 0x1234;
grants.pdsch[0].dci.ctx.format = srsran_dci_format_nr_1_0;
grants.pdsch[0].dci.freq_domain_assigment = 0x1FFF;
grants.pdsch[0].dci.time_domain_assigment = 0;
grants.pdsch[0].dci.mcs = 27;
grants.pdsch[0].dci.search_space = srsran_search_space_type_ue;
grants.pdsch[0].dci.coreset_id = 1;
grants.pdsch[0].dci.location.L = 0;
grants.pdsch[0].dci.location.ncce = 0;
grants.pdsch[0].dci.ctx.ss_type = srsran_search_space_type_ue;
grants.pdsch[0].dci.ctx.coreset_id = 1;
grants.pdsch[0].dci.ctx.location.L = 0;
grants.pdsch[0].dci.ctx.location.ncce = 0;
for (auto& w : cc_workers) {
w->work_dl(dl_cfg, grants);

@ -26,6 +26,7 @@ public:
~cc_worker();
bool set_carrier(const srsran_carrier_nr_t* carrier);
bool update_cfg();
void set_tti(uint32_t tti);
cf_t* get_rx_buffer(uint32_t antenna_idx);
@ -38,6 +39,7 @@ public:
int read_pdsch_d(cf_t* pdsch_d);
private:
bool configured = false;
srsran_slot_cfg_t dl_slot_cfg = {};
srsran_slot_cfg_t ul_slot_cfg = {};
uint32_t cc_idx = 0;

@ -35,6 +35,7 @@ public:
~sf_worker() = default;
bool set_carrier_unlocked(uint32_t cc_idx, const srsran_carrier_nr_t* carrier_);
bool update_cfg(uint32_t cc_idx);
/* Functions used by main PHY thread */
cf_t* get_buffer(uint32_t cc_idx, uint32_t antenna_idx);

@ -70,11 +70,6 @@ bool cc_worker::set_carrier(const srsran_carrier_nr_t* carrier)
return false;
}
if (srsran_ue_dl_nr_set_pdcch_config(&ue_dl, &phy->cfg.pdcch) < SRSRAN_SUCCESS) {
ERROR("Error setting carrier");
return false;
}
if (srsran_ue_ul_nr_set_carrier(&ue_ul, carrier) < SRSRAN_SUCCESS) {
ERROR("Error setting carrier");
return false;
@ -86,6 +81,20 @@ bool cc_worker::set_carrier(const srsran_carrier_nr_t* carrier)
return true;
}
bool cc_worker::update_cfg()
{
srsran_dci_cfg_nr_t dci_cfg = phy->cfg.get_dci_cfg(phy->carrier);
if (srsran_ue_dl_nr_set_pdcch_config(&ue_dl, &phy->cfg.pdcch, &dci_cfg) < SRSRAN_SUCCESS) {
logger.error("Error setting NR PDCCH configuration");
return false;
}
configured = true;
return true;
}
void cc_worker::set_tti(uint32_t tti)
{
dl_slot_cfg.idx = tti;
@ -129,7 +138,7 @@ void cc_worker::decode_pdcch_dl()
int n_dl =
srsran_ue_dl_nr_find_dl_dci(&ue_dl, &dl_slot_cfg, rnti.id, rnti.type, dci_rx.data(), (uint32_t)dci_rx.size());
if (n_dl < SRSRAN_SUCCESS) {
logger.error("Error decoding DL NR-PDCCH");
logger.error("Error decoding DL NR-PDCCH for %s=0x%x", srsran_rnti_type_str(rnti.type), rnti.id);
return;
}
@ -149,14 +158,17 @@ void cc_worker::decode_pdcch_dl()
if (logger.debug.enabled()) {
for (uint32_t i = 0; i < ue_dl.pdcch_info_count; i++) {
const srsran_ue_dl_nr_pdcch_info_t* info = &ue_dl.pdcch_info[i];
logger.debug("PDCCH: crst_id=%d, ss_id=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; crc=%s",
info->coreset_id,
info->ss_id,
info->location.ncce,
info->location.L,
logger.debug("PDCCH: rnti=0x%x, crst_id=%d, ss_type=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; "
"nof_bits=%d; crc=%s;",
info->dci_ctx.rnti,
info->dci_ctx.coreset_id,
info->dci_ctx.ss_type,
info->dci_ctx.location.ncce,
info->dci_ctx.location.L,
info->measure.epre_dBfs,
info->measure.rsrp_dBfs,
info->measure.norm_corr,
info->nof_bits,
info->result.crc ? "OK" : "KO");
}
}
@ -196,6 +208,11 @@ void cc_worker::decode_pdcch_ul()
bool cc_worker::work_dl()
{
// Do NOT process any DL if it is not configured
if (not configured) {
return true;
}
// Check if it is a DL slot, if not skip
if (!srsran_tdd_nr_is_dl(&phy->cfg.tdd, 0, dl_slot_cfg.idx)) {
return true;

@ -45,6 +45,15 @@ bool sf_worker::set_carrier_unlocked(uint32_t cc_idx, const srsran_carrier_nr_t*
return cc_workers.at(cc_idx)->set_carrier(carrier_);
}
bool sf_worker::update_cfg(uint32_t cc_idx)
{
if (cc_idx >= cc_workers.size()) {
return false;
}
return cc_workers[cc_idx]->update_cfg();
}
cf_t* sf_worker::get_buffer(uint32_t cc_idx, uint32_t antenna_idx)
{
if (cc_idx >= cc_workers.size()) {

@ -94,16 +94,16 @@ int worker_pool::set_ul_grant(std::array<uint8_t, SRSRAN_RAR_UL_GRANT_NBITS> pac
{
// Copy DCI bits and setup DCI context
srsran_dci_msg_nr_t dci_msg = {};
dci_msg.format = srsran_dci_format_nr_0_0; // MAC RAR grant shall be unpacked as DCI 0_0 format
dci_msg.rnti_type = rnti_type;
dci_msg.search_space = srsran_search_space_type_rar; // This indicates it is a MAC RAR
dci_msg.rnti = rnti;
dci_msg.ctx.format = srsran_dci_format_nr_rar; // MAC RAR grant shall be unpacked as DCI 0_0 format
dci_msg.ctx.rnti_type = rnti_type;
dci_msg.ctx.ss_type = srsran_search_space_type_rar; // This indicates it is a MAC RAR
dci_msg.ctx.rnti = rnti;
dci_msg.nof_bits = SRSRAN_RAR_UL_GRANT_NBITS;
srsran_vec_u8_copy(dci_msg.payload, packed_ul_grant.data(), SRSRAN_RAR_UL_GRANT_NBITS);
srsran_dci_ul_nr_t dci_ul = {};
if (srsran_dci_nr_rar_unpack(&dci_msg, &dci_ul) < SRSRAN_SUCCESS) {
if (srsran_dci_nr_ul_unpack(NULL, &dci_msg, &dci_ul) < SRSRAN_SUCCESS) {
return SRSRAN_ERROR;
}
@ -131,6 +131,13 @@ bool worker_pool::set_config(const srsran::phy_cfg_nr_t& cfg)
return false;
}
// Request workers to run any procedure related to configuration update
for (auto& w : workers) {
if (not w->update_cfg(0)) {
return false;
}
}
return true;
}

@ -562,8 +562,8 @@ bool rrc_nr::apply_mac_cell_group(const mac_cell_group_cfg_s& mac_cell_group_cfg
if (mac_cell_group_cfg.bsr_cfg_present) {
logger.debug("Handling MAC BSR config");
srsran::bsr_cfg_nr_t bsr_cfg = {};
bsr_cfg.periodic_timer = mac_cell_group_cfg.bsr_cfg.periodic_bsr_timer.to_number();
bsr_cfg.retx_timer = mac_cell_group_cfg.bsr_cfg.retx_bsr_timer.to_number();
bsr_cfg.periodic_timer = mac_cell_group_cfg.bsr_cfg.periodic_bsr_timer.to_number();
bsr_cfg.retx_timer = mac_cell_group_cfg.bsr_cfg.retx_bsr_timer.to_number();
if (mac->set_config(bsr_cfg) != SRSRAN_SUCCESS) {
return false;
}
@ -610,7 +610,7 @@ bool rrc_nr::apply_sp_cell_init_dl_pdsch(const asn1::rrc_nr::pdsch_cfg_s& pdsch_
bool rrc_nr::apply_res_csi_report_cfg(const asn1::rrc_nr::csi_report_cfg_s& csi_report_cfg)
{
uint32_t report_cfg_id = csi_report_cfg.report_cfg_id;
uint32_t report_cfg_id = csi_report_cfg.report_cfg_id;
srsran_csi_hl_report_cfg_t srsran_csi_hl_report_cfg;
if (make_phy_csi_report(csi_report_cfg, &srsran_csi_hl_report_cfg) == true) {
phy_cfg.csi.reports[report_cfg_id] = srsran_csi_hl_report_cfg;
@ -692,7 +692,7 @@ bool rrc_nr::apply_dl_common_cfg(const asn1::rrc_nr::dl_cfg_common_s& dl_cfg_com
// phy_cfg.pdcch.ra_rnti = 0x16; //< Supposed to be deduced from PRACH configuration
phy_cfg.pdcch.ra_search_space = phy_cfg.pdcch.search_space[pdcch_cfg_common.ra_search_space];
phy_cfg.pdcch.ra_search_space_present = true;
phy_cfg.pdcch.ra_search_space.type = srsran_search_space_type_common_3;
phy_cfg.pdcch.ra_search_space.type = srsran_search_space_type_common_1;
} else {
logger.warning("Search space %d not presenet for random access search space",
pdcch_cfg_common.ra_search_space);
@ -748,7 +748,6 @@ bool rrc_nr::apply_ul_common_cfg(const asn1::rrc_nr::ul_cfg_common_s& ul_cfg_com
if (ul_cfg_common.init_ul_bwp.rach_cfg_common_present) {
if (ul_cfg_common.init_ul_bwp.rach_cfg_common.type() == setup_release_c<rach_cfg_common_s>::types_opts::setup) {
rach_nr_cfg_t rach_nr_cfg = make_mac_rach_cfg(ul_cfg_common.init_ul_bwp.rach_cfg_common.setup());
phy_cfg.pdcch.ra_rnti = ul_cfg_common.init_ul_bwp.rach_cfg_common.setup().rach_cfg_generic.prach_cfg_idx;
mac->set_config(rach_nr_cfg);
// Make the RACH configuration for PHY

Loading…
Cancel
Save