* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fapi_5g / source / api / fapi2phy / p7 / nr5g_fapi_proc_dl_tti_req.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2021 Intel.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 /**
20  * @file
21  * This file consist of implementation of FAPI DL_TTI.request message.
22  *
23  **/
24 #include <rte_memcpy.h>
25 #include "nr5g_fapi_framework.h"
26 #include "nr5g_fapi_dpdk.h"
27 #include "nr5g_fapi_fapi2mac_api.h"
28 #include "nr5g_fapi_fapi2phy_api.h"
29 #include "nr5g_fapi_fapi2phy_p7_proc.h"
30 #include "nr5g_fapi_fapi2phy_p7_pvt_proc.h"
31 #include "nr5g_fapi_memory.h"
32
33 /** @ingroup group_source_api_p5_fapi2phy_proc
34  *
35  *  @param[in]  p_phy_instance Pointer to PHY instance.
36  *  @param[in]  p_fapi_req Pointer to FAPI DL_TTI.request message structure.
37  *  
38  *  @return     Returns ::SUCCESS and ::FAILURE.
39  *
40  *  @description
41  *  This message indicates the control information for a downlink slot. 
42  *
43 **/
44 uint8_t nr5g_fapi_dl_tti_request(
45     bool is_urllc,
46     p_nr5g_fapi_phy_instance_t p_phy_instance,
47     fapi_dl_tti_req_t * p_fapi_req,
48     fapi_vendor_msg_t * p_fapi_vendor_msg)
49 {
50     PDLConfigRequestStruct p_ia_dl_config_req;
51     PMAC2PHY_QUEUE_EL p_list_elem;
52     nr5g_fapi_stats_t *p_stats;
53
54     if (NULL == p_phy_instance) {
55         NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Invalid " "Phy Instance"));
56         return FAILURE;
57     }
58
59     p_stats = &p_phy_instance->stats;
60     p_stats->fapi_stats.fapi_dl_tti_req++;
61
62     if (NULL == p_fapi_req) {
63         NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Invalid fapi " "message"));
64         return FAILURE;
65     }
66
67     p_list_elem = nr5g_fapi_fapi2phy_create_api_list_elem((uint8_t)
68         MSG_TYPE_PHY_DL_CONFIG_REQ, 1,
69         (uint32_t) sizeof(DLConfigRequestStruct));
70     if (!p_list_elem) {
71         NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI.request] Unable to create "
72                 "list element. Out of memory!!!"));
73         return FAILURE;
74     }
75
76     p_ia_dl_config_req = (PDLConfigRequestStruct) (p_list_elem + 1);
77     if (FAILURE == nr5g_fapi_dl_tti_req_to_phy_translation(p_phy_instance,
78             p_fapi_req, p_fapi_vendor_msg, p_ia_dl_config_req)) {
79         nr5g_fapi_fapi2phy_destroy_api_list_elem(p_list_elem);
80         NR5G_FAPI_LOG(DEBUG_LOG, ("[DL_TTI.request][%d][%d,%d] Not Sent",
81                 p_phy_instance->phy_id, p_ia_dl_config_req->sSFN_Slot.nSFN,
82                 p_ia_dl_config_req->sSFN_Slot.nSlot));
83         return FAILURE;
84     }
85     /* Add element to send list */
86     nr5g_fapi_fapi2phy_add_to_api_list(is_urllc, p_list_elem);
87
88     p_stats->iapi_stats.iapi_dl_config_req++;
89     NR5G_FAPI_LOG(DEBUG_LOG, ("[DL_TTI.request][%u][%u,%u,%u] is_urllc %u",
90         p_phy_instance->phy_id,
91         p_ia_dl_config_req->sSFN_Slot.nSFN, p_ia_dl_config_req->sSFN_Slot.nSlot,
92         p_ia_dl_config_req->sSFN_Slot.nSym, is_urllc));
93
94     return SUCCESS;
95 }
96
97  /** @ingroup group_source_api_p7_fapi2phy_proc
98  *
99  *  @param[in]   p_fapi_req Pointer to FAPI DL_TTI.request structure.
100  *  @param[out]  p_ia_dl_config_req Pointer to IAPI DL_TTI.request structure.
101  *  
102  *  @return     Returns ::SUCCESS and ::FAILURE.
103  *
104  *  @description
105  *  This function converts FAPI DL_TTI.request to IAPI DL_Config.request
106  *  structure.
107  *
108 **/
109 uint8_t nr5g_fapi_dl_tti_req_to_phy_translation(
110     p_nr5g_fapi_phy_instance_t p_phy_instance,
111     fapi_dl_tti_req_t * p_fapi_req,
112     fapi_vendor_msg_t * p_fapi_vendor_msg,
113     PDLConfigRequestStruct p_phy_req)
114 {
115     int idx = 0, nDCI = 0, jdx = 0;
116     uint32_t pdsch_size, pdcch_size, pbch_size, csirs_size, total_size;
117     nr5g_fapi_stats_t *p_stats;
118
119     fapi_dl_tti_req_pdu_t *p_fapi_dl_tti_req_pdu = NULL;
120     fapi_dl_pdcch_pdu_t *p_pdcch_pdu = NULL;
121     fapi_dl_pdsch_pdu_t *p_pdsch_pdu = NULL;
122     fapi_dl_csi_rs_pdu_t *p_csi_rs_pdu = NULL;
123     fapi_dl_ssb_pdu_t *p_ssb_pdu = NULL;
124     fapi_ue_info_t *p_ueGrpInfo = NULL;
125
126     PPDUStruct pPduStruct = NULL;
127     PDLSCHPDUStruct p_dlsch_pdu = NULL;
128     PDCIPDUStruct p_dci_pdu = NULL;
129     PBCHPDUStruct p_bch_pdu = NULL;
130     PCSIRSPDUStruct pCSIRSPdu = NULL;
131     PPDSCHGroupInfoStruct pPDSCHGroupInfoStruct = NULL;
132
133     total_size = sizeof(DLConfigRequestStruct);
134     pdsch_size = RUP32B(sizeof(DLSCHPDUStruct));
135     pdcch_size = RUP32B(sizeof(DCIPDUStruct));
136     pbch_size = RUP32B(sizeof(BCHPDUStruct));
137     csirs_size = RUP32B(sizeof(CSIRSPDUStruct));
138
139     p_stats = &p_phy_instance->stats;
140     NR5G_FAPI_MEMSET(p_phy_req, sizeof(DLConfigRequestStruct), 0, total_size);
141     p_phy_req->sMsgHdr.nMessageType = MSG_TYPE_PHY_DL_CONFIG_REQ;
142     p_phy_req->sSFN_Slot.nCarrierIdx = p_phy_instance->phy_id;
143     p_phy_req->nGroup = p_fapi_req->nGroup;
144     p_phy_req->nPDU = p_fapi_req->nPdus;
145     p_phy_req->sSFN_Slot.nSFN = p_fapi_req->sfn;
146     p_phy_req->sSFN_Slot.nSlot = p_fapi_req->slot;
147
148     for (idx = 0; idx < p_phy_req->nGroup; ++idx) {
149         p_ueGrpInfo = &p_fapi_req->ue_grp_info[idx];
150         pPDSCHGroupInfoStruct = &p_phy_req->sPDSCHGroupInfoStruct[idx];
151         pPDSCHGroupInfoStruct->nUE = p_ueGrpInfo->nUe;
152         pPDSCHGroupInfoStruct->rsv1[0] = 0;
153         pPDSCHGroupInfoStruct->rsv1[1] = 0;
154         pPDSCHGroupInfoStruct->rsv1[2] = 0;
155         for (jdx = 0; jdx < p_ueGrpInfo->nUe; ++jdx) {
156             pPDSCHGroupInfoStruct->nPduIdx[jdx] = p_ueGrpInfo->pduIdx[jdx];
157         }
158     }
159
160     pPduStruct = p_phy_req->sDLPDU;
161     for (idx = 0; idx < p_phy_req->nPDU; ++idx) {
162         p_stats->fapi_stats.fapi_dl_tti_pdus++;
163         p_fapi_dl_tti_req_pdu = &p_fapi_req->pdus[idx];
164         switch (p_fapi_dl_tti_req_pdu->pduType) {
165             case FAPI_PDCCH_PDU_TYPE:
166                 nDCI++;
167                 p_dci_pdu = (PDCIPDUStruct) pPduStruct;
168                 NR5G_FAPI_MEMSET(p_dci_pdu, RUP32B(sizeof(DCIPDUStruct)), 0,
169                     pdcch_size);
170                 p_pdcch_pdu = &p_fapi_dl_tti_req_pdu->pdu.pdcch_pdu;
171                 p_dci_pdu->sPDUHdr.nPDUType = DL_PDU_TYPE_DCI;
172                 p_dci_pdu->sPDUHdr.nPDUSize = pdcch_size;
173                 total_size += pdcch_size;
174                 nr5g_fapi_fill_dci_pdu(p_phy_instance, p_pdcch_pdu, p_dci_pdu);
175                 break;
176
177             case FAPI_PDSCH_PDU_TYPE:
178                 p_dlsch_pdu = (PDLSCHPDUStruct) pPduStruct;
179                 p_pdsch_pdu = &p_fapi_dl_tti_req_pdu->pdu.pdsch_pdu;
180                 NR5G_FAPI_MEMSET(p_dlsch_pdu, RUP32B(sizeof(DLSCHPDUStruct)), 0,
181                     pdsch_size);
182                 p_dlsch_pdu->sPDUHdr.nPDUType = DL_PDU_TYPE_DLSCH;
183                 p_dlsch_pdu->sPDUHdr.nPDUSize = pdsch_size;
184                 total_size += pdsch_size;
185                 nr5g_fapi_fill_pdsch_pdu(p_phy_instance, p_pdsch_pdu, p_dlsch_pdu);
186                 break;
187
188             case FAPI_PBCH_PDU_TYPE:
189                 p_bch_pdu = (PBCHPDUStruct) pPduStruct;
190                 p_ssb_pdu = &p_fapi_dl_tti_req_pdu->pdu.ssb_pdu;
191                 NR5G_FAPI_MEMSET(p_bch_pdu, RUP32B(sizeof(BCHPDUStruct)), 0,
192                     pbch_size);
193                 p_bch_pdu->sPDUHdr.nPDUType = DL_PDU_TYPE_PBCH;
194                 p_bch_pdu->sPDUHdr.nPDUSize = pbch_size;
195                 total_size += pbch_size;
196                 nr5g_fapi_fill_ssb_pdu(p_phy_instance, p_bch_pdu, p_ssb_pdu);
197                 break;
198
199             case FAPI_CSIRS_PDU_TYPE:
200                 pCSIRSPdu = (PCSIRSPDUStruct) pPduStruct;
201                 p_csi_rs_pdu = &p_fapi_dl_tti_req_pdu->pdu.csi_rs_pdu;
202                 NR5G_FAPI_MEMSET(pCSIRSPdu, RUP32B(sizeof(CSIRSPDUStruct)), 0,
203                     csirs_size);
204                 pCSIRSPdu->sPDUHdr.nPDUType = DL_PDU_TYPE_CSIRS;
205                 pCSIRSPdu->sPDUHdr.nPDUSize = csirs_size;
206                 total_size += csirs_size;
207                 nr5g_fapi_fill_csi_rs_pdu(p_phy_instance, p_csi_rs_pdu, pCSIRSPdu);
208                 break;
209
210             default:
211                 NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI] Invalid Pdu Type: %d",
212                         pPduStruct->nPDUType));
213                 return FAILURE;
214         }
215         pPduStruct =
216             (PDUStruct *) ((uint8_t *) pPduStruct + pPduStruct->nPDUSize);
217         p_stats->iapi_stats.iapi_dl_tti_pdus++;
218     }
219
220     p_phy_req->nDCI = nDCI;
221     p_phy_req->sMsgHdr.nMessageLen = total_size;
222
223     if (NULL != p_fapi_vendor_msg)
224     {
225         nr5g_fapi_dl_tti_req_to_phy_translation_vendor_ext(p_phy_instance,
226                                                            p_fapi_vendor_msg,
227                                                            p_phy_req);
228     }
229
230     return SUCCESS;
231 }
232
233  /** @ingroup group_source_api_p5_fapi2phy_proc
234  *
235  *  @param[in]   p_fapi_vendor_msg  Pointer to FAPI DL_TTI.request vendor message.
236  *  @param[out]  p_ia_dl_config_req Pointer to IAPI DL_TTI.request structure.
237  *
238  *  @return     no return.
239  *
240  *  @description
241  *  This function fills fields for DL_TTI.request structure that come from
242  *  a vendor extension.
243  *
244 **/
245 void nr5g_fapi_dl_tti_req_to_phy_translation_vendor_ext(
246     p_nr5g_fapi_phy_instance_t p_phy_instance,
247     fapi_vendor_msg_t * p_fapi_vendor_msg,
248     PDLConfigRequestStruct p_phy_req)
249 {
250     int idx = 0;
251
252     fapi_vendor_dl_tti_req_t *p_vendor_dl_tti_req = NULL;
253     fapi_vendor_dl_pdcch_pdu_t *p_vendor_pdcch_pdu = NULL;
254     fapi_vendor_dl_pdsch_pdu_t *p_vendor_pdsch_pdu = NULL;
255     fapi_vendor_csi_rs_pdu_t *p_vendor_csi_rs_pdu = NULL;
256
257     PPDUStruct pPduStruct = NULL;
258     PDCIPDUStruct p_dci_pdu = NULL;
259     PDLSCHPDUStruct p_dlsch_pdu = NULL;
260     PCSIRSPDUStruct p_CSIRS_pdu = NULL;
261
262     p_vendor_dl_tti_req = &p_fapi_vendor_msg->p7_req_vendor.dl_tti_req;
263
264     p_phy_req->sSFN_Slot.nSym = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.sym;
265
266     p_phy_req->nLte_CRS_Present = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_present;
267     p_phy_req->nLte_CRS_carrierFreqDL = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_carrier_freq_dl;
268     p_phy_req->nLte_CRS_carrierBandwidthDL = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_carrier_bandwidth_dl;
269     p_phy_req->nLte_CRS_nrofCRS_Ports = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_nr_of_crs_ports;
270     p_phy_req->nLte_CRS_v_shift = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.lte_crs_v_shift;
271     p_phy_req->nPdcchPrecoderEn = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.pdcch_precoder_en;
272     p_phy_req->nSSBPrecoderEn = p_fapi_vendor_msg->p7_req_vendor.dl_tti_req.ssb_precoder_en;
273
274     pPduStruct = p_phy_req->sDLPDU;
275     for (idx = 0; idx < p_phy_req->nPDU; ++idx) {
276         switch (pPduStruct->nPDUType) {
277             case DL_PDU_TYPE_DCI: 
278                 p_dci_pdu = (PDCIPDUStruct) pPduStruct;
279                 p_vendor_pdcch_pdu =
280                     &p_vendor_dl_tti_req->pdus[idx].pdu.pdcch_pdu;
281
282                 if (USE_VENDOR_EPREXSSB == p_phy_instance->phy_config.use_vendor_EpreXSSB)
283                 {
284                     p_dci_pdu->nEpreRatioOfPDCCHToSSB =
285                         p_vendor_pdcch_pdu->dl_dci[0].epre_ratio_of_pdcch_to_ssb;
286                     p_dci_pdu->nEpreRatioOfDmrsToSSB =
287                         p_vendor_pdcch_pdu->dl_dci[0].epre_ratio_of_dmrs_to_ssb;
288                 }
289                 break;
290
291             case DL_PDU_TYPE_DLSCH:
292                 p_dlsch_pdu = (PDLSCHPDUStruct) pPduStruct;
293                 p_vendor_pdsch_pdu =
294                     &p_vendor_dl_tti_req->pdus[idx].pdu.pdsch_pdu;
295
296                 p_dlsch_pdu->nNrOfAntennaPorts = p_vendor_pdsch_pdu->nr_of_antenna_ports;
297
298                 if (USE_VENDOR_EPREXSSB == p_phy_instance->phy_config.use_vendor_EpreXSSB)
299                 {
300                     p_dlsch_pdu->nEpreRatioOfDmrsToSSB =
301                         p_vendor_pdsch_pdu->epre_ratio_of_dmrs_to_ssb;
302                     p_dlsch_pdu->nEpreRatioOfPDSCHToSSB =
303                         p_vendor_pdsch_pdu->epre_ratio_of_pdsch_to_ssb;
304                 }
305
306                 NR5G_FAPI_MEMCPY(p_dlsch_pdu->nTxRUIdx, sizeof(p_dlsch_pdu->nTxRUIdx),
307                     p_vendor_pdsch_pdu->tx_ru_idx, sizeof(p_vendor_pdsch_pdu->tx_ru_idx));
308                 break;
309
310             case DL_PDU_TYPE_PBCH:
311                 // No vendor ext
312                 break;
313
314             case DL_PDU_TYPE_CSIRS:
315                 p_CSIRS_pdu = (PCSIRSPDUStruct) pPduStruct;
316                 p_vendor_csi_rs_pdu = &p_vendor_dl_tti_req->pdus[idx].pdu.csi_rs_pdu;
317
318                 if (USE_VENDOR_EPREXSSB == p_phy_instance->phy_config.use_vendor_EpreXSSB)
319                 {
320                     p_CSIRS_pdu->nEpreRatioToSSB = p_vendor_csi_rs_pdu->epre_ratio_to_ssb;
321                 }
322                 break;
323
324             default:
325                 NR5G_FAPI_LOG(ERROR_LOG, ("[DL_TTI] Invalid Pdu Type: %d",
326                         pPduStruct->nPDUType));
327                 return;
328         }
329         pPduStruct =
330             (PDUStruct *) ((uint8_t *) pPduStruct + pPduStruct->nPDUSize);
331     }
332 }
333
334 /** @ingroup group_nr5g_test_config
335  *
336  *  @param[in]   p_pdcch_pdu
337  *  @param[out]  p_dci_pdu
338  *
339  *  @return      void
340  *
341  *  @description
342  *  This function fills IAPI DCIPdu from FAPI PDCCH Pdu
343  *
344 **/
345 void nr5g_fapi_fill_dci_pdu(
346     p_nr5g_fapi_phy_instance_t p_phy_instance,
347     fapi_dl_pdcch_pdu_t * p_pdcch_pdu,
348     PDCIPDUStruct p_dci_pdu)
349 {
350     nr5g_fapi_stats_t *p_stats = NULL;
351
352     p_stats = &p_phy_instance->stats;
353     p_stats->fapi_stats.fapi_dl_tti_pdcch_pdus++;
354
355     p_dci_pdu->nBWPSize = p_pdcch_pdu->bwpSize;
356     p_dci_pdu->nBWPStart = p_pdcch_pdu->bwpStart;
357     p_dci_pdu->nSubcSpacing = p_pdcch_pdu->subCarrierSpacing;
358     p_dci_pdu->nCpType = p_pdcch_pdu->cyclicPrefix;
359     p_dci_pdu->nCCEStartIndex = p_pdcch_pdu->startSymbolIndex;
360     p_dci_pdu->nNrOfSymbols = p_pdcch_pdu->durationSymbols;
361     p_dci_pdu->nStartSymbolIndex = p_pdcch_pdu->startSymbolIndex;
362     p_dci_pdu->nFreqDomain[0] = ((uint32_t) p_pdcch_pdu->freqDomainResource[0] |
363         (((uint32_t) p_pdcch_pdu->freqDomainResource[1]) << 8) |
364         (((uint32_t) p_pdcch_pdu->freqDomainResource[2]) << 16) |
365         (((uint32_t) p_pdcch_pdu->freqDomainResource[3]) << 24));
366     p_dci_pdu->nFreqDomain[1] = ((uint32_t) p_pdcch_pdu->freqDomainResource[4] |
367         (((uint32_t) p_pdcch_pdu->freqDomainResource[5]) << 8));
368     p_dci_pdu->nCCEToREGType = p_pdcch_pdu->cceRegMappingType;
369     p_dci_pdu->nREGBundleSize = p_pdcch_pdu->regBundleSize;
370     p_dci_pdu->nInterleaveSize = p_pdcch_pdu->interleaverSize;
371     p_dci_pdu->nShift = p_pdcch_pdu->shiftIndex;
372     p_dci_pdu->nCoreSetType = p_pdcch_pdu->coreSetType;
373     p_dci_pdu->nCCEStartIndex = p_pdcch_pdu->dlDci[0].cceIndex;
374     p_dci_pdu->nAggrLvl = p_pdcch_pdu->dlDci[0].aggregationLevel;
375     p_dci_pdu->nScid = p_pdcch_pdu->dlDci[0].scramblingId;
376     p_dci_pdu->nID = p_pdcch_pdu->dlDci[0].scramblingId;
377     p_dci_pdu->nRNTIScramb = p_pdcch_pdu->dlDci[0].scramblingRnti;
378     p_dci_pdu->nRNTI = p_pdcch_pdu->dlDci[0].rnti;
379     p_dci_pdu->nTotalBits = p_pdcch_pdu->dlDci[0].payloadSizeBits;
380
381     if (USE_VENDOR_EPREXSSB != p_phy_instance->phy_config.use_vendor_EpreXSSB) {
382     p_dci_pdu->nEpreRatioOfPDCCHToSSB =
383         nr5g_fapi_calculate_nEpreRatioOfPDCCHToSSB(p_pdcch_pdu->
384         dlDci[0].beta_pdcch_1_0);
385     p_dci_pdu->nEpreRatioOfDmrsToSSB =
386             nr5g_fapi_calculate_nEpreRatioOfDmrsToSSB(p_pdcch_pdu->
387                 dlDci[0].powerControlOffsetSS);
388     }
389
390     if (FAILURE == NR5G_FAPI_MEMCPY(p_dci_pdu->nDciBits,
391             sizeof(uint8_t) * MAX_DCI_BIT_BYTE_LEN,
392             p_pdcch_pdu->dlDci[0].payload,
393             sizeof(uint8_t) * MAX_DCI_BIT_BYTE_LEN)) {
394         NR5G_FAPI_LOG(ERROR_LOG, ("PDCCH: RNTI: %d -- DCI Bits copy error.",
395                 p_pdcch_pdu->dlDci[0].rnti));
396     }
397     p_stats->iapi_stats.iapi_dl_tti_pdcch_pdus++;
398 }
399
400 static uint32_t get_rbg_index_mask_from_MSB(uint32_t nth_bit) {
401     #define DLSCH_RBG_INDEX_MSB 0x80000000u
402     return DLSCH_RBG_INDEX_MSB >> nth_bit;
403 }
404
405 /** @ingroup group_source_api_p7_fapi2phy_proc
406  *
407  *  @param[in]  rb_bitmap Pointer to FAPI DL resource block bitmap.
408  *  @param[in]  rbg_size  Size of resource block group.
409  *
410  *  @return     Returns IAPI nRBGIndex
411  *
412  *  @description
413  *  Maps rbBitmap into nRBGIndex bits for pdsch.
414  *
415 **/
416 uint32_t nr5g_fapi_calc_pdsch_rbg_index(
417     const uint8_t rb_bitmap[FAPI_RB_BITMAP_SIZE],
418     uint16_t bwp_start,
419     uint16_t bwp_size
420     )
421 {
422     return nr5g_fapi_calc_rbg_index(
423         rb_bitmap, bwp_start, bwp_size, get_rbg_index_mask_from_MSB);
424 }
425
426 /** @ingroup group_nr5g_test_config
427  *
428  *  @param[in]    p_pdsch_pdu
429  *  @param[out]   p_dlsch_pdu
430  *
431  *  @return      void
432  *
433  *  @description
434  *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
435  *
436 **/
437 void nr5g_fapi_fill_pdsch_pdu(
438     p_nr5g_fapi_phy_instance_t p_phy_instance,
439     fapi_dl_pdsch_pdu_t * p_pdsch_pdu,
440     PDLSCHPDUStruct p_dlsch_pdu)
441 {
442     uint8_t resource_alloc_type, idx, port_index = 0u;
443     nr5g_fapi_stats_t *p_stats;
444     uint16_t bwp_start, bwp_size;
445
446     p_stats = &p_phy_instance->stats;
447     p_stats->fapi_stats.fapi_dl_tti_pdsch_pdus++;
448
449     bwp_size = p_dlsch_pdu->nBWPSize = p_pdsch_pdu->bwpSize;
450     bwp_start = p_dlsch_pdu->nBWPStart = p_pdsch_pdu->bwpStart;
451     p_dlsch_pdu->nSubcSpacing = p_pdsch_pdu->subCarrierSpacing;
452     p_dlsch_pdu->nCpType = p_pdsch_pdu->cyclicPrefix;
453     p_dlsch_pdu->nRNTI = p_pdsch_pdu->rnti;
454     p_dlsch_pdu->nUEId = p_pdsch_pdu->pdu_index;
455
456     // Codeword Information
457     p_dlsch_pdu->nNrOfCodeWords = p_pdsch_pdu->nrOfCodeWords;
458     p_dlsch_pdu->nMCS[0] = p_pdsch_pdu->cwInfo[0].mcsIndex;
459     p_dlsch_pdu->nMcsTable = p_pdsch_pdu->cwInfo[0].mcsTable;
460     p_dlsch_pdu->nRV[0] = p_pdsch_pdu->cwInfo[0].rvIndex;
461     p_dlsch_pdu->nTBSize[0] = p_pdsch_pdu->cwInfo[0].tbSize;
462     if (p_pdsch_pdu->nrOfCodeWords == 2) {
463         p_dlsch_pdu->nMCS[1] = p_pdsch_pdu->cwInfo[1].mcsIndex;
464         p_dlsch_pdu->nRV[1] = p_pdsch_pdu->cwInfo[1].rvIndex;
465         p_dlsch_pdu->nTBSize[1] = p_pdsch_pdu->cwInfo[1].tbSize;
466     }
467     //p_dlsch_pdu->nNrOfAntennaPorts = p_phy_instance->phy_config.n_nr_of_rx_ant;
468     p_dlsch_pdu->nNrOfLayers = p_pdsch_pdu->nrOfLayers;
469     p_dlsch_pdu->nNrOfAntennaPorts = p_dlsch_pdu->nNrOfLayers;
470     p_dlsch_pdu->nTransmissionScheme = p_pdsch_pdu->transmissionScheme;
471     p_dlsch_pdu->nDMRSConfigType = p_pdsch_pdu->dmrsConfigType;
472     p_dlsch_pdu->nNIDnSCID = p_pdsch_pdu->dlDmrsScramblingId;
473     p_dlsch_pdu->nNid = p_pdsch_pdu->dataScramblingId;
474     p_dlsch_pdu->nSCID = p_pdsch_pdu->scid;
475
476     for (idx = 0;
477         (idx < FAPI_MAX_DMRS_PORTS && port_index < p_dlsch_pdu->nNrOfLayers);
478         idx++) {
479         if ((p_pdsch_pdu->dmrsPorts >> idx) && 0x0001) {
480             p_dlsch_pdu->nPortIndex[port_index++] = idx;
481         }
482     }
483
484     // Resource Allocation Information
485     resource_alloc_type =
486     p_dlsch_pdu->nResourceAllocType = p_pdsch_pdu->resourceAlloc;
487     if(FAPI_DL_RESOURCE_ALLOC_TYPE_0 == resource_alloc_type) {
488         p_dlsch_pdu->nRBGSize = nr5g_fapi_calc_n_rbg_size(bwp_size);
489         p_dlsch_pdu->nRBGIndex = nr5g_fapi_calc_pdsch_rbg_index(
490             p_pdsch_pdu->rbBitmap, bwp_start, bwp_size);
491     }
492
493     p_dlsch_pdu->nRBStart = p_pdsch_pdu->rbStart;
494     p_dlsch_pdu->nRBSize = p_pdsch_pdu->rbSize;
495     p_dlsch_pdu->nPMI = (p_pdsch_pdu->preCodingAndBeamforming.numPrgs > 0)
496         ? p_pdsch_pdu->preCodingAndBeamforming.pmi_bfi[0].pmIdx
497         : 0;
498     p_dlsch_pdu->nVRBtoPRB = p_pdsch_pdu->vrbToPrbMapping;
499     p_dlsch_pdu->nStartSymbolIndex = p_pdsch_pdu->startSymbIndex;
500     p_dlsch_pdu->nNrOfSymbols = p_pdsch_pdu->nrOfSymbols;
501     p_dlsch_pdu->nNrOfCDMs = p_pdsch_pdu->numDmrsCdmGrpsNoData;
502     p_dlsch_pdu->nMappingType = p_pdsch_pdu->mappingType;
503     p_dlsch_pdu->nNrOfDMRSSymbols = p_pdsch_pdu->nrOfDmrsSymbols;
504     p_dlsch_pdu->nDMRSAddPos = p_pdsch_pdu->dmrsAddPos;
505
506     // PTRS Information
507     p_dlsch_pdu->nPTRSTimeDensity = p_pdsch_pdu->ptrsTimeDensity;
508     p_dlsch_pdu->nPTRSFreqDensity = p_pdsch_pdu->ptrsFreqDensity;
509     p_dlsch_pdu->nPTRSReOffset = p_pdsch_pdu->ptrsReOffset;
510     p_dlsch_pdu->nEpreRatioOfPDSCHToPTRS = p_pdsch_pdu->nEpreRatioOfPdschToPtrs;
511
512     if (USE_VENDOR_EPREXSSB != p_phy_instance->phy_config.use_vendor_EpreXSSB) {
513         p_dlsch_pdu->nEpreRatioOfDmrsToSSB =
514             nr5g_fapi_calculate_nEpreRatioOfDmrsToSSB(
515                 p_pdsch_pdu->powerControlOffsetSS);
516         p_dlsch_pdu->nEpreRatioOfPDSCHToSSB =
517             nr5g_fapi_calculate_nEpreRatioOfPDSCHToSSB(
518                 p_pdsch_pdu->powerControlOffset);
519     }
520
521     // PTRS Information
522     p_dlsch_pdu->nPTRSPresent = p_pdsch_pdu->pduBitMap & 0x0001;
523     p_dlsch_pdu->nNrOfPTRSPorts =
524         __builtin_popcount(p_pdsch_pdu->ptrsPortIndex);
525     for (idx = 0; idx < p_dlsch_pdu->nNrOfPTRSPorts &&
526         idx < MAX_DL_PER_UE_PTRS_PORT_NUM; idx++) {
527         p_dlsch_pdu->nPTRSPortIndex[idx] = idx;
528     }
529
530     // Don't Cares
531     p_dlsch_pdu->nNrOfDMRSAssPTRS[0] = 0x1;
532     p_dlsch_pdu->nNrOfDMRSAssPTRS[1] = 0x1;
533     p_dlsch_pdu->n1n2 = 0x201;
534
535     p_dlsch_pdu->nNrofTxRU = port_index;
536
537     p_stats->iapi_stats.iapi_dl_tti_pdsch_pdus++;
538 }
539
540 /** @ingroup group_nr5g_test_config
541  *
542  *  @param[in]  beta_pdcch_1_0
543  *
544  *  @return     uint16_t mapping
545  *
546  *  @description
547  *  This function maps FAPI to IAPI value range.
548  *
549  *
550  * Please refer 5G FAPI-IAPI Translator Module SW Design Document for details on
551  * the mapping.
552  *
553  * |-----------------------------------------|
554  * | nEpreRatioOfPDCCHToSSb | beta_PDCCH_1_0 |
555  * |-----------------------------------------|
556  * |             1          |      0 - 2     |
557  * |          1000          |        3       |
558  * |          2000          |        4       |
559  * |          3000          |        5       |
560  * |          4000          |        6       |
561  * |          5000          |        7       |
562  * |          6000          |        8       |
563  * |          7000          |        9       |
564  * |          8000          |       10       |
565  * |          9000          |       11       |
566  * |         10000          |       12       |
567  * |         11000          |       13       |
568  * |         12000          |       14       |
569  * |         13000          |       15       |
570  * |         14000          |       16       |
571  * |         14000          |       17       |
572  * |-----------------------------------------|
573  *
574 **/
575 uint16_t nr5g_fapi_calculate_nEpreRatioOfPDCCHToSSB(
576     uint8_t beta_pdcch_1_0)
577 {
578     if (beta_pdcch_1_0 > 0 && beta_pdcch_1_0 <= 2) {
579         return 1;
580     } else if (beta_pdcch_1_0 > 1 && beta_pdcch_1_0 < 17) {
581         return ((beta_pdcch_1_0 - 2) * 1000);
582     } else if (beta_pdcch_1_0 == 17) {
583         return ((beta_pdcch_1_0 - 3) * 1000);
584     } else {
585         return 0;
586     }
587 }
588
589 /** @ingroup group_nr5g_test_config
590  *
591  *  @param[in]  power_control_offset_ss
592  *
593  *  @return     uint16_t mapping
594  *
595  *  @description
596  *  This function maps FAPI to IAPI value range.
597  *
598  *
599  * nEpreRatioOfDmrsToSSB: 1->20000, 0.001dB step, -6dB to 14dB
600  * powerControlOffsetSS:  0->3, 3dB step, -3dB to 6dB
601  * |----------------------------------------------|
602  * | nEpreRatioOfDmrsToSSB | powerControlOffsetSS |
603  * |----------------------------------------------|
604  * |     3000              |          0           |
605  * |     6000              |          1           |
606  * |     9000              |          2           |
607  * |     12000             |          3           |
608  * |----------------------------------------------|
609  *
610 **/
611 uint16_t nr5g_fapi_calculate_nEpreRatioOfDmrsToSSB(
612     uint8_t power_control_offset_ss)
613 {
614     switch(power_control_offset_ss)
615     {
616         case 0:
617             return 3000;
618         case 1:
619             return 6000;
620         case 2:
621             return 9000;
622         case 3:
623             return 12000;
624         default:
625             NR5G_FAPI_LOG(ERROR_LOG,
626                 ("Unsupported value of power_control_offset_ss."));
627             return 0;
628     }
629 }
630
631
632 /** @ingroup group_nr5g_test_config
633  *
634  *  @param[in]  power_control_offset
635  *
636  *  @return     uint16_t mapping
637  *
638  *  @description
639  *  This function maps FAPI to IAPI value range.
640  *
641  *
642  * nEpreRatioOfPDSCHToSSB: 1->20000, 0.001dB step, -6dB to 14dB
643  * powerControlOffset:  0->23, 1dB step, -8dB to 15dB
644  * |----------------------------------------------|
645  * | nEpreRatioOfPDSCHToSSB | powerControlOffset  |
646  * |----------------------------------------------|
647  * |             1          |        0-2          |
648  * |          1000          |          3          |
649  * |          2000          |          4          |
650  * |          3000          |          5          |
651  * |          4000          |          6          |
652  * |          5000          |          7          |
653  * |          6000          |          8          |
654  * |          7000          |          9          |
655  * |          8000          |         10          |
656  * |          9000          |         11          |
657  * |         10000          |         12          |
658  * |         11000          |         13          |
659  * |         12000          |         14          |
660  * |         13000          |         15          |
661  * |         14000          |         16          |
662  * |         15000          |         17          |
663  * |         16000          |         18          |
664  * |         17000          |         19          |
665  * |         18000          |         20          |
666  * |         19000          |         21          |
667  * |         20000          |      22-23          |
668  * |----------------------------------------------|
669  *
670 **/
671 uint16_t nr5g_fapi_calculate_nEpreRatioOfPDSCHToSSB(uint8_t power_control_offset)
672 {
673     #define MAPPING_SIZE 24U
674
675     static const uint16_t power_control_offset_to_epre_ratio[MAPPING_SIZE] = {
676     //      0      1      2      3      4      5      6      7
677             1,     1,     1,  1000,  2000,  3000,  4000,  5000,
678     //      8      9     10     11     12     13     14     15
679          6000,  7000,  8000,  9000, 10000, 11000, 12000, 13000,
680     //     16     17     18     19     20     21     22     23
681         14000, 15000, 16000, 17000, 18000, 19000, 20000, 20000
682     };
683
684     if(MAPPING_SIZE > power_control_offset)
685     {
686         return power_control_offset_to_epre_ratio[power_control_offset];
687     }
688     else
689     {
690         NR5G_FAPI_LOG(ERROR_LOG,
691             ("Unsupported value of power_control_offset=%u.",
692             power_control_offset));
693         return 0;
694     }
695 }
696
697 /** @ingroup group_nr5g_test_config
698  *
699  *  @param[in]  ssb_offset_point_a
700  *  @param[in]  sub_c_common
701  *
702  *  @return     uint8_t nSSBPrbOffset
703  *
704  *  @description
705  *  This function maps FAPI to IAPI value range.
706  *
707  * Please refer 5G FAPI-IAPI Translator Module SW Design Document for details on
708  * the mapping.
709  *
710 **/
711 uint8_t nr5g_fapi_calculate_nSSBPrbOffset(
712     uint16_t ssb_offset_point_a, uint8_t sub_c_common)
713 {
714     return ssb_offset_point_a/pow(2, sub_c_common);
715 }
716
717 /** @ingroup group_nr5g_test_config
718  *
719  *  @param[in]   p_dlsch_pdu
720  *  @param[out]  p_pdsch_pdu
721  *
722  *  @return      void
723  *
724  *  @description
725  *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
726  *
727 **/
728 void nr5g_fapi_fill_ssb_pdu(
729     p_nr5g_fapi_phy_instance_t p_phy_instance,
730     PBCHPDUStruct p_bch_pdu,
731     fapi_dl_ssb_pdu_t * p_ssb_pdu)
732 {
733     uint8_t *p_mib = (uint8_t *) & p_bch_pdu->nMIB[0];
734     uint8_t *payload = (uint8_t *) & p_ssb_pdu->bchPayload.bchPayload;
735     nr5g_fapi_stats_t *p_stats;
736
737     p_mib[0] = payload[0];
738     p_mib[1] = payload[1];
739     p_mib[2] = payload[2];
740     p_stats = &p_phy_instance->stats;
741     p_stats->fapi_stats.fapi_dl_tti_ssb_pdus++;
742     p_bch_pdu->nSSBSubcOffset = p_ssb_pdu->ssbSubCarrierOffset;
743     p_bch_pdu->nSSBPrbOffset =
744         nr5g_fapi_calculate_nSSBPrbOffset(p_ssb_pdu->ssbOffsetPointA,
745             p_phy_instance->phy_config.sub_c_common);
746     p_stats->iapi_stats.iapi_dl_tti_ssb_pdus++;
747 }
748
749 /** @ingroup group_nr5g_test_config
750  *
751  *  @param[in]   p_dlsch_pdu
752  *  @param[out]  p_pdsch_pdu
753  *
754  *  @return      void
755  *
756  *  @description
757  *  This function fills FAPI PDSCH Pdu from IAPI DLSCHPDU
758  *
759 **/
760 void nr5g_fapi_fill_csi_rs_pdu(
761     p_nr5g_fapi_phy_instance_t p_phy_instance,
762     fapi_dl_csi_rs_pdu_t * p_csi_rs_pdu,
763     PCSIRSPDUStruct p_CSIRS_pdu)
764 {
765     nr5g_fapi_stats_t *p_stats;
766
767     p_stats = &p_phy_instance->stats;
768     p_stats->fapi_stats.fapi_dl_tti_csi_rs_pdus++;
769
770     p_CSIRS_pdu->nBWPSize = p_csi_rs_pdu->bwpSize;
771     p_CSIRS_pdu->nBWPStart = p_csi_rs_pdu->bwpStart;
772     p_CSIRS_pdu->nCDMType = p_csi_rs_pdu->cdmType;
773     p_CSIRS_pdu->nCSIType = p_csi_rs_pdu->csiType;
774     p_CSIRS_pdu->nCpType = p_csi_rs_pdu->cyclicPrefix;
775     p_CSIRS_pdu->nFreqDensity = p_csi_rs_pdu->freqDensity;
776     p_CSIRS_pdu->nFreqDomain = p_csi_rs_pdu->freqDomain;
777     p_CSIRS_pdu->nNrOfRBs = p_csi_rs_pdu->nrOfRbs;
778     p_CSIRS_pdu->nScrambId = p_csi_rs_pdu->scramId;
779     p_CSIRS_pdu->nStartRB = p_csi_rs_pdu->startRb;
780     p_CSIRS_pdu->nSubcSpacing = p_csi_rs_pdu->subCarrierSpacing;
781     p_CSIRS_pdu->nSymbL0 = p_csi_rs_pdu->symbL0;
782     p_CSIRS_pdu->nSymbL1 = p_csi_rs_pdu->symbL1;
783     p_CSIRS_pdu->nRow = p_csi_rs_pdu->row;
784     // Not mapping the beamforming parameters
785     // p_CSIRS_pdu->powerControlOffset = p_csi_rs_pdu->powerControlOffset;
786
787     if (USE_VENDOR_EPREXSSB != p_phy_instance->phy_config.use_vendor_EpreXSSB) {
788         p_CSIRS_pdu->nEpreRatioToSSB = nr5g_fapi_calculate_nEpreRatioOfDmrsToSSB(p_csi_rs_pdu->powerControlOffsetSs);
789     }
790
791     p_stats->iapi_stats.iapi_dl_tti_csi_rs_pdus++;
792 }