Merge remote-tracking branch 'origin/remove-sched-response-doc' into integration_2025_w46 (!3757)
Remove schedule response and update L1 threading documentation
This merge requests removes the somewhat superfluous "schedule response"
mechanism. "schedule response" was run after running the scheduler
itself and copied various FAPI messages into a global msgDataTx
structure from which the various TX/RX jobs were triggered. It is not
necessary, though, given that the scheduler is run inside the tx_func()
(running the TX jobs of the L1), and so the scheduler output FAPI
messages can directly be read into a variable of the existing
NR_Sched_Rsp_t type. This allows to delete a couple of hundred lines of
code (while retaining functionality), and simplifies the msgDataTx type
(which is still there to trigger TX job (including the scheduler) from
the ru thread).
In short, prior, there was this call chain:
- tx_func() calls run_scheduler_monolithic() (through fptr
NR_slot_indication())
- get some memory through allocate_sched_response() which has enough
space for NR_Sched_Rsp_t type variable
- call the scheduler and fill the variable
- call nr_schedule_response() (through fptr NR_schedule_response())
which copies into L1: to msgDataTx for TX, to separate structures
for RX
this is changed to
- tx_func() runs one message at a time, hence we can use memory in the
data segment for NR_Sched_Rsp_t. It calls run_scheduler_monolithic()
through the fptr
- pointers into NR_Sched_Rsp_t are passed to the scheduler, which
fills as before
- we return, memory is in its right place and does not need an extra
copy.
Additionally, this merge request updates documentation on threading and
cleans up some unused code along the way.
This commit is contained in:
+1
-10
@@ -652,7 +652,6 @@ add_library(SCHED_LIB ${SCHED_SRC})
|
||||
target_link_libraries(SCHED_LIB PRIVATE asn1_lte_rrc_hdrs)
|
||||
|
||||
set(SCHED_NR_SRC
|
||||
${OPENAIR1_DIR}/SCHED_NR/fapi_nr_l1.c
|
||||
${OPENAIR1_DIR}/SCHED_NR/phy_procedures_nr_gNB.c
|
||||
${OPENAIR1_DIR}/SCHED_NR/nr_prach_procedures.c
|
||||
${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c
|
||||
@@ -939,7 +938,6 @@ set(PHY_SRC_UE
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dci_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_tools.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_dlsch_coding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
|
||||
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch.c
|
||||
@@ -1215,7 +1213,6 @@ set (MAC_SRC
|
||||
|
||||
set (MAC_NR_SRC
|
||||
${NR_PHY_INTERFACE_DIR}/NR_IF_Module.c
|
||||
${NR_PHY_INTERFACE_DIR}/nr_sched_response.c
|
||||
${NR_GNB_MAC_DIR}/main.c
|
||||
${NR_GNB_MAC_DIR}/config.c
|
||||
${NR_GNB_MAC_DIR}/gNB_scheduler.c
|
||||
@@ -1283,12 +1280,6 @@ set (MISC_NFAPI_LTE
|
||||
|
||||
add_library(MISC_NFAPI_LTE_LIB ${MISC_NFAPI_LTE})
|
||||
|
||||
set (MISC_NFAPI_NR
|
||||
${OPENAIR1_DIR}/SCHED/nfapi_nr_dummy.c
|
||||
)
|
||||
|
||||
add_library(MISC_NFAPI_NR_LIB ${MISC_NFAPI_NR})
|
||||
|
||||
add_library(L2
|
||||
${L2_SRC}
|
||||
${MAC_SRC}
|
||||
@@ -2091,7 +2082,7 @@ if (${T_TRACER})
|
||||
oai_eth_transpro HASHTABLE UTIL
|
||||
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB
|
||||
NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
|
||||
MISC_NFAPI_LTE_LIB MISC_NFAPI_NR_LIB
|
||||
MISC_NFAPI_LTE_LIB
|
||||
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU
|
||||
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE MAC_NR_COMMON MAC_UE_NR ngap
|
||||
GTPV1U SCTP_CLIENT MME_APP LIB_NAS_UE SIMU
|
||||
|
||||
@@ -15,7 +15,6 @@ Ref :
|
||||
DLSCH encoding : 200.0
|
||||
L1 Rx processing : 530.0
|
||||
PUSCH inner-receiver : 360.0
|
||||
Schedule Response : 1.0
|
||||
DL & UL scheduling timing : 17.0
|
||||
UL Indication : 1.0
|
||||
Slot Indication : 13.0
|
||||
@@ -31,7 +30,6 @@ DeviationThreshold :
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.25
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.50
|
||||
|
||||
@@ -15,7 +15,6 @@ Ref :
|
||||
DLSCH encoding : 110.0
|
||||
L1 Rx processing : 345.0
|
||||
PUSCH inner-receiver : 150.0
|
||||
Schedule Response : 1.0
|
||||
DL & UL scheduling timing : 5.0
|
||||
UL Indication : 1.0
|
||||
Slot Indication : 6.0
|
||||
@@ -31,7 +30,6 @@ DeviationThreshold :
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.50
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.50
|
||||
|
||||
@@ -15,7 +15,6 @@ Ref :
|
||||
DLSCH encoding : 230.0
|
||||
L1 Rx processing : 175.0
|
||||
PUSCH inner-receiver : 100.0
|
||||
Schedule Response : 3.0
|
||||
DL & UL scheduling timing : 11.0
|
||||
UL Indication : 3.0
|
||||
Slot Indication : 14.0
|
||||
@@ -28,7 +27,6 @@ DeviationThreshold :
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.50
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.25
|
||||
|
||||
@@ -15,7 +15,6 @@ Ref :
|
||||
DLSCH encoding : 140.0
|
||||
L1 Rx processing : 345.0
|
||||
PUSCH inner-receiver : 155.0
|
||||
Schedule Response : 1.0
|
||||
DL & UL scheduling timing : 8.0
|
||||
UL Indication : 3.0
|
||||
Slot Indication : 9.0
|
||||
@@ -31,7 +30,6 @@ DeviationThreshold :
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.35
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.35
|
||||
|
||||
@@ -15,7 +15,6 @@ Ref :
|
||||
DLSCH encoding : 90.0
|
||||
L1 Rx processing : 290.0
|
||||
PUSCH inner-receiver : 115.0
|
||||
Schedule Response : 1.0
|
||||
DL & UL scheduling timing : 4.0
|
||||
UL Indication : 2.0
|
||||
Slot Indication : 5.0
|
||||
@@ -31,7 +30,6 @@ DeviationThreshold :
|
||||
DLSCH encoding : 0.25
|
||||
L1 Rx processing : 0.25
|
||||
PUSCH inner-receiver : 0.25
|
||||
Schedule Response : 1.00
|
||||
DL & UL scheduling timing : 0.50
|
||||
UL Indication : 1.00
|
||||
Slot Indication : 0.50
|
||||
|
||||
@@ -575,8 +575,8 @@ int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L,
|
||||
return f;
|
||||
}
|
||||
|
||||
void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) {
|
||||
|
||||
void get_coreset_rballoc(const uint8_t *FreqDomainResource, int *n_rb, int *rb_offset)
|
||||
{
|
||||
uint8_t count=0, start=0, start_set=0;
|
||||
|
||||
uint64_t bitmap = (((uint64_t)FreqDomainResource[0])<<37)|
|
||||
@@ -599,7 +599,7 @@ void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset) {
|
||||
}
|
||||
|
||||
// According to 38.211 7.3.2.2
|
||||
int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration)
|
||||
int get_coreset_num_cces(const uint8_t *FreqDomainResource, int duration)
|
||||
{
|
||||
int num_rbs;
|
||||
int rb_offset;
|
||||
|
||||
@@ -280,8 +280,8 @@ uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, ui
|
||||
|
||||
int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs);
|
||||
int get_SLIV(uint8_t S, uint8_t L);
|
||||
void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset);
|
||||
int get_coreset_num_cces(uint8_t *FreqDomainResource, int duration);
|
||||
void get_coreset_rballoc(const uint8_t *FreqDomainResource, int *n_rb, int *rb_offset);
|
||||
int get_coreset_num_cces(const uint8_t *FreqDomainResource, int duration);
|
||||
int get_nr_table_idx(int nr_bandP, uint8_t scs_index);
|
||||
int32_t get_delta_duplex(int nr_bandP, uint8_t scs_index);
|
||||
frame_type_t get_frame_type(uint16_t nr_bandP, uint8_t scs_index);
|
||||
|
||||
@@ -1916,8 +1916,6 @@ INPUT = \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_api.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_setup.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/E1AP/e1ap_asnc.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/nr_sched_response.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/nr_sched_response.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/NR_IF_Module.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/NR_PHY_INTERFACE/NR_IF_Module.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair2/SDAP/nr_sdap/nr_sdap.h \
|
||||
@@ -2012,7 +2010,6 @@ INPUT = \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_sss.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_uci_tools_common.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_prach.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_TRANSPORT/nr_scrambling.c \
|
||||
@@ -2294,10 +2291,8 @@ INPUT = \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_frame_config_nr.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_frame_config_nr.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/nr_prach_procedures.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/fapi_nr_l1.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/phy_procedures_nr_gNB.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/sched_nr.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/fapi_nr_l1.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../openair1/SCHED_NR/nr_ru_procedures.c \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/if_defs.h \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/../radio/ETHERNET/ethernet_lib.h \
|
||||
|
||||
@@ -161,9 +161,9 @@ unpack function is called.
|
||||
## P7 DL Transmission by VNF
|
||||
|
||||
DL messages are scheduled at the VNF, through gNB_dlsch_ulsch_scheduler(). gNB_dlsch_ulsch_scheduler() is called when
|
||||
handling a SLOT.indication message in trigger_scheduler().
|
||||
handling a SLOT.indication message in phy_nr_slot_indication().
|
||||
|
||||
The function trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind) calls the functions oai_nfapi_[DL P7 msg]_
|
||||
The function phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *slot_ind) calls the functions oai_nfapi_[DL P7 msg]_
|
||||
req(), calling in turn call the send_p7_msg function pointer, which contain the logic to pack the message into a buffer
|
||||
and send it to the PNF.
|
||||
Finally, NR_UL_indication is called to process the other P7 messages received from the PNF that were put in theire
|
||||
@@ -215,7 +215,7 @@ bool nfapi_vnf_p7_tx_data_req(nfapi_vnf_p7_config_t* config, nfapi_nr_tx_data_re
|
||||
graph TD
|
||||
softmodem_start[nr-softmodem init] --> P5_configuration[configure_nr_nfapi_vnf] --> transport_init[Transport mechanism init] --> send_first_msg[Send first P5 message to PNF]
|
||||
transport_init[Transport mechanism init] --> P5_recv_loop[P5 receive loop] -- P5 Message processing --> P5_recv_loop[P5 receive loop]
|
||||
P5_recv_loop[P5 receive loop] -- Start.response callback called --> P7_config[P7 Configuration] --> P7_loop[P7 Loop] --> P7_msg_recv[P7 message received] --> call_vnf_handle_p7[Call vnf_nr_handle_p7_msg] --> hdr_unpack[Unpack header] --> call_specific_p7_handler[Call specific P7 message handler] --> slot_ind[Is a SLOT.indication?] -- Yes --> trig_scheduler[Call trigger_scheduler] --> gNB_ulsch_dlsch_sched[Call gNB_dlsch_ulsch_scheduler] --> send_p7_dl[Process and send P7 messages to PNF] --> call_ul_ind[Call NR_UL_indication] --> proc_p7[Process P7 messages in queue] --> P7_loop[P7 Loop]
|
||||
P5_recv_loop[P5 receive loop] -- Start.response callback called --> P7_config[P7 Configuration] --> P7_loop[P7 Loop] --> P7_msg_recv[P7 message received] --> call_vnf_handle_p7[Call vnf_nr_handle_p7_msg] --> hdr_unpack[Unpack header] --> call_specific_p7_handler[Call specific P7 message handler] --> slot_ind[Is a SLOT.indication?] -- Yes --> trig_scheduler[Call phy_nr_slot_indication] --> gNB_ulsch_dlsch_sched[Call gNB_dlsch_ulsch_scheduler] --> send_p7_dl[Process and send P7 messages to PNF] --> call_ul_ind[Call NR_UL_indication] --> proc_p7[Process P7 messages in queue] --> P7_loop[P7 Loop]
|
||||
slot_ind[Is a SLOT.indication?] -- No --> put_queue[Put message in queue] --> P7_loop[P7 Loop];
|
||||
|
||||
|
||||
|
||||
+94
-71
@@ -1,74 +1,97 @@
|
||||
This document is a high-level overview over the L1 threading mechanism.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A[ru_thread] --> RFin>block rx_rf] --> feprx
|
||||
feprx --> half-slot --> end_feprx
|
||||
feprx --> second-thread -- block_end_feprx --> end_feprx>feprx]
|
||||
end_feprx --> rx_nr_prach_ru
|
||||
rx_nr_prach_ru -- block_queue_singleton --> resp_L1>resp L1]
|
||||
resp_L1 -- async launch --> rx_func
|
||||
resp_L1 -- immediate return --> RFin
|
||||
|
||||
subgraph rxfunc
|
||||
rx_func_implem[rx_func]
|
||||
subgraph rxfuncbeg
|
||||
handle_nr_slot_ind
|
||||
--> rnti_to_remove-mgmt
|
||||
--> L1_nr_prach_procedures
|
||||
--> apply_nr_rotation_RX
|
||||
end
|
||||
subgraph phy_procedures_gNB_uespec_RX
|
||||
fill_ul_rb_mask
|
||||
--> pucch(decode each gNB->pucch)
|
||||
-->nr_fill_ul_indication
|
||||
--> nr_ulsch_procedures
|
||||
--> nr_ulsch_decoding
|
||||
--> segInParallel[[all segments decode in parallel]]
|
||||
--> barrier_end_of_ulsch_decoding
|
||||
end
|
||||
subgraph NR_UL_indication
|
||||
handle_nr_rach
|
||||
--> handle_nr_uci
|
||||
--> handle_nr_ulsch
|
||||
subgraph gNB_dlsch_ulsch_scheduler
|
||||
run_pdcp
|
||||
--> schedule_xxxx
|
||||
end
|
||||
handle_nr_ulsch --> gNB_dlsch_ulsch_scheduler
|
||||
subgraph NR_Schedule_response
|
||||
L1_tx_free3>L1_tx_free]
|
||||
--> handle_nr_nfapi_xxx_pdu
|
||||
--> sendTxFilled((L1_tx_filled))
|
||||
--> nr_fill_ul_xxx
|
||||
--> nr_schedule_rx_prach()
|
||||
end
|
||||
gNB_dlsch_ulsch_scheduler --> NR_Schedule_response
|
||||
end
|
||||
rx_func_implem --> rxfuncbeg
|
||||
rxfuncbeg --> phy_procedures_gNB_uespec_RX
|
||||
phy_procedures_gNB_uespec_RX --> NR_UL_indication
|
||||
-- block_queue_block_PNF_monolithic --> L1_tx_free2>L1 tx filled]
|
||||
-- async launch --> tx_func
|
||||
L1_tx_free2 -- send_msg --> rsp((resp_L1))
|
||||
end
|
||||
rx_func --> rxfunc
|
||||
|
||||
|
||||
subgraph tx_func
|
||||
direction LR
|
||||
subgraph phy_procedures_gNB_TX
|
||||
dcitop[nr_generate dci top]
|
||||
--> nr_generate_csi_rs
|
||||
--> apply_nr_rotation_TX
|
||||
-- send_msg --> end_tx_func((L1_tx_out))
|
||||
end
|
||||
subgraph tx_reorder_thread
|
||||
L1_tx_out>L1_tx_out]
|
||||
--> reorder{re order} --> reorder
|
||||
reorder --> ru_tx_func
|
||||
reorder --> L1_tx_free((L1_tx_free))
|
||||
ru_tx_func --> feptx_prec
|
||||
--> feptx_ofdm
|
||||
end
|
||||
end
|
||||
|
||||
ru_thread --> RFin[block rx_rf] --> UL{is UL slot?}
|
||||
UL -- yes --> wait_free_rx_tti --> fep_rx --> rx_nr_prach_ru --> msg:L1_tx_out
|
||||
UL -- no --> msg:L1_tx_out
|
||||
msg:L1_tx_out -- asnyc launch --> L1_tx_thread
|
||||
msg:L1_tx_out --> RFin
|
||||
```
|
||||
|
||||
The main thread is `ru_thread()`. It blocks on reception of radio samples
|
||||
(either time domain or frequency domain). In the case of an UL slot, it waits
|
||||
that no more than N UL jobs are scheduled (via `wait_free_rx_tti()`, which
|
||||
waits on queue `L1_rx_out`, cf. the RX L1 processing further below). Then:
|
||||
|
||||
- if the radio is time domain-based, it performs RX front-end processing (RX
|
||||
FEP -> `fep_rx()`, i.e. DFT) to reach a frequency domain representation of
|
||||
the RX signal, as well as does DFT for PRACH.
|
||||
- if the radio is frequency domain-based, nothing is done.
|
||||
|
||||
Afterwards, it triggers TX processing by pushing a message into the FIFO queue
|
||||
`L1_tx_out`, which asynchronously starts a TX job in `L1_tx_thread()` (see
|
||||
below). After that, it blocks again on reception on the radio.
|
||||
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
L1_tx_thread --> TX_in[block L1_tx_out] --> NR_slot_indication
|
||||
|
||||
subgraph tx_func
|
||||
|
||||
NR_slot_indication --> msg:resp_L1 --> phy_procedures_gNB_tx --> ru_tx_func
|
||||
NR_slot_indication["run the scheduler:
|
||||
- monolithic: run_scheduler_monolithic()
|
||||
- nFAPI: send indication via pnf_send_slot_ind()"]
|
||||
msg:resp_L1 -- async launch --> L1_RX_thread
|
||||
end
|
||||
ru_tx_func --> TX_in
|
||||
```
|
||||
|
||||
The `L1_tx_thread()` processes individual TX jobs sequentially, by waiting for
|
||||
new messages on queue `L1_tx_out`, signalling individual TX jobs. For each
|
||||
message, it calls `tx_func()` which does in order:
|
||||
|
||||
- run the scheduler through `NR_slot_indication`, which corresponds to a
|
||||
"Slot.indication" in FAPI parlance. This runs the scheduler, and schedules a
|
||||
given slot (either downlink, uplink, or both).
|
||||
- trigger RX processing by pushing a message into the FIFO queue `resp_L1`,
|
||||
asynchronously starting an RX job in `L1_rx_thread()` (see below).
|
||||
- process the current L1 TX job through `phy_procedures_gNB_tx()`
|
||||
- write to the radio board via `ru_tx_func()`.
|
||||
|
||||
After these steps, `tx_func()` return to `L1_tx_thread()`, which will wait for
|
||||
the next TX job.
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
L1_rx_thread --> RX_in[block resp_L1] --> L1_nr_prach_proc
|
||||
|
||||
subgraph rx_func
|
||||
|
||||
L1_nr_prach_proc --> phase_comp{apply phase comp.?}
|
||||
phase_comp -- yes --> apply_nr_rotation --> phy_procedures_gNB_uespec_RX
|
||||
phase_comp -- no --> phy_procedures_gNB_uespec_RX
|
||||
phy_procedures_gNB_uespec_RX --> NR_ul_indication --> msg:L1_rx_out
|
||||
NR_ul_indication["run the scheduler: NR_UL_indication()"]
|
||||
msg:L1_rx_out -- async signal free --> ru_thread
|
||||
end
|
||||
msg:L1_rx_out --> RX_in
|
||||
```
|
||||
|
||||
The `L1_rx_thread()` processes individual RX jobs sequentially. It waits for a
|
||||
new RX job through the queue `resp_L1`, and then calls `rx_func()`, which does
|
||||
in order:
|
||||
|
||||
- run PRACH processing via `L1_nr_prach_proc()`
|
||||
- optionally apply rotation to the RX signal if phase compensation is to be
|
||||
applied
|
||||
- run the current L1 RX job through (`phy_procedures_gNB_uespec_RX()`), which
|
||||
notably includes PUCCH, PUSCH, SRS processing
|
||||
- call the scheduler through `NR_ul_indication()`, which corresponds to FAPI
|
||||
uplink messages (e.g., `RX_data.indication`, `CRC.indication`,
|
||||
`UCI.indication` etc.)
|
||||
- signal completion via FIFO queue `L1_rx_out()`, which tells `ru_thread()`
|
||||
that RX processing finished.
|
||||
|
||||
The signalling of scheduler data is done through a variable `UL_INFO`, which is
|
||||
filled by `L1_nr_prach_proc()` (for PRACH) and `phy_procedures_gNB_uespec_RX()`
|
||||
(for PUCCH, PUSCH, SRS).
|
||||
|
||||
After these steps, `rx_func()` returns to `L1_rx_thread()`, which will wait the
|
||||
next RX job.
|
||||
|
||||
Note that while individual TX (RX) jobs are run sequentially through
|
||||
`L1_tx_thread()` (`L1_rx_thread()`), both TX and RX processing run in
|
||||
parallel.
|
||||
|
||||
+1
-1
@@ -177,7 +177,7 @@ it would be better to call **NR_UL_indication()** now instead of before (on prev
|
||||
* nr_common_signal_procedures()
|
||||
generate common signals
|
||||
{: .func4}
|
||||
* nr_generate_dci_top()
|
||||
* nr_generate_dci()
|
||||
generate DCI: the scheduling informtion for each UE in both DL and UL
|
||||
{: .func4}
|
||||
* nr_generate_pdsch()
|
||||
|
||||
+2
-2
@@ -242,10 +242,10 @@ To see the (any) periodical output at the PNF, define `NFAPI_TRACE_LEVEL=info`.
|
||||
This output shows:
|
||||
|
||||
```
|
||||
41056.739654 [I] 3556767424: pnf_p7_slot_ind: [P7:1] msgs ontime 489 thr DL 0.06 UL 0.01 msg late 0 (vtime)
|
||||
41056.739654 [I] 3556767424: nr_pnf_p7_get_msgs: [P7:1] msgs ontime 489 thr DL 0.06 UL 0.01 msg late 0 (vtime)
|
||||
```
|
||||
|
||||
The first numbers are timestamps. `pnf_p7_slot_ind` is the name of the
|
||||
The first numbers are timestamps. `nr_pnf_p7_get_msgs` is the name of the
|
||||
functions that prints the output. `[P7:1]` refers to the fact that these are
|
||||
information on P7, of PHY ID 1. Finally, `msgs ontime 489` means that in the
|
||||
last window (since the last print), 489 messages arrived at the PNF in total.
|
||||
|
||||
@@ -194,13 +194,7 @@ void handle_nr_srs_measurements(const module_id_t module_id,
|
||||
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
|
||||
|
||||
/* TODO these declarations are to be removed */
|
||||
void nr_schedule_dl_tti_req(void) {};
|
||||
void nr_schedule_ul_dci_req() {};
|
||||
void nr_schedule_tx_req() {};
|
||||
void nr_schedule_ul_tti_req() {};
|
||||
void nr_slot_select() {};
|
||||
void NR_UL_indication(NR_UL_IND_t *UL_INFO) {};
|
||||
void gNB_dlsch_ulsch_scheduler() {};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
@@ -156,10 +156,6 @@ extern char uecap_xer[1024];
|
||||
char uecap_xer_in=0;
|
||||
|
||||
/* TODO these declarations are to be removed */
|
||||
void nr_schedule_dl_tti_req(void) {};
|
||||
void nr_schedule_ul_dci_req() {};
|
||||
void nr_schedule_tx_req() {};
|
||||
void nr_schedule_ul_tti_req() {};
|
||||
void nr_slot_select() {};
|
||||
|
||||
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
|
||||
|
||||
+17
-27
@@ -55,7 +55,6 @@
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "SCHED_NR/phy_frame_config_nr.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "assertions.h"
|
||||
@@ -65,7 +64,6 @@
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "nfapi_nr_interface_scf.h"
|
||||
#include "notified_fifo.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h"
|
||||
#include "thread-pool.h"
|
||||
#include "time_meas.h"
|
||||
#include "utils.h"
|
||||
@@ -82,8 +80,6 @@ static void tx_func(processingData_L1tx_t *info)
|
||||
int slot_rx = info->slot_rx;
|
||||
LOG_D(NR_PHY, "%d.%d running tx_func\n", frame_tx, slot_tx);
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
module_id_t module_id = gNB->Mod_id;
|
||||
uint8_t CC_id = gNB->CC_id;
|
||||
NR_IF_Module_t *ifi = gNB->if_inst;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
|
||||
@@ -94,15 +90,22 @@ static void tx_func(processingData_L1tx_t *info)
|
||||
reset_active_ulsch(gNB, frame_rx);
|
||||
}
|
||||
|
||||
clear_slot_beamid(gNB, slot_tx);
|
||||
|
||||
nfapi_nr_slot_indication_scf_t ind = {.sfn = frame_tx, .slot = slot_tx};
|
||||
start_meas(&gNB->slot_indication_stats);
|
||||
ifi->NR_slot_indication(module_id, CC_id, frame_tx, slot_tx);
|
||||
// this variable is very big (multiple MB), so we put it into static storage
|
||||
// to not overflow the stack while still having it in local (function) scope
|
||||
// also, tx_func() is only executed by one thread, serially
|
||||
static NR_Sched_Rsp_t sched_response;
|
||||
ifi->NR_slot_indication(&ind, &sched_response);
|
||||
stop_meas(&gNB->slot_indication_stats);
|
||||
gNB->msgDataTx->timestamp_tx = info->timestamp_tx;
|
||||
info = gNB->msgDataTx;
|
||||
|
||||
info->gNB = gNB;
|
||||
|
||||
// At this point, MAC scheduler just ran, including scheduling
|
||||
// PRACH/PUCCH/PUSCH, so trigger RX chain processing
|
||||
nr_save_ul_tti_req(gNB, &sched_response.UL_tti_req);
|
||||
LOG_D(NR_PHY, "Trigger RX for %d.%d\n", frame_rx, slot_rx);
|
||||
notifiedFIFO_elt_t *res = newNotifiedFIFO_elt(sizeof(processingData_L1_t), 0, &gNB->resp_L1, NULL);
|
||||
processingData_L1_t *syncMsg = NotifiedFifoData(res);
|
||||
@@ -119,7 +122,13 @@ static void tx_func(processingData_L1tx_t *info)
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx || IS_SOFTMODEM_RFSIM
|
||||
|| cfg->analog_beamforming_ve.analog_beam_list) {
|
||||
start_meas(&info->gNB->phy_proc_tx);
|
||||
phy_procedures_gNB_TX(info, frame_tx, slot_tx, 1);
|
||||
phy_procedures_gNB_TX(info->gNB,
|
||||
&sched_response.DL_req,
|
||||
&sched_response.TX_req,
|
||||
&sched_response.UL_dci_req,
|
||||
frame_tx,
|
||||
slot_tx,
|
||||
1);
|
||||
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
processingData_RU_t syncMsgRU;
|
||||
@@ -131,14 +140,6 @@ static void tx_func(processingData_L1tx_t *info)
|
||||
ru_tx_func((void *)&syncMsgRU);
|
||||
stop_meas(&info->gNB->phy_proc_tx);
|
||||
}
|
||||
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
/* this thread is done with the sched_info, decrease the reference counter.
|
||||
* This only applies for monolithic; in the PNF, the memory is allocated in
|
||||
* a ring buffer that should never be overwritten (one frame duration). */
|
||||
LOG_D(NR_PHY, "Calling deref_sched_response for id %d (tx_func) in %d.%d\n", info->sched_response_id, frame_tx, slot_tx);
|
||||
deref_sched_response(info->sched_response_id);
|
||||
}
|
||||
}
|
||||
|
||||
void *L1_rx_thread(void *arg)
|
||||
@@ -248,7 +249,6 @@ static size_t dump_L1_meas_stats(PHY_VARS_gNB *gNB, RU_t *ru, char *output, size
|
||||
output += print_meas_log(&gNB->ul_indication_stats, "UL Indication", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->slot_indication_stats, "Slot Indication", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->rx_pusch_stats, "PUSCH inner-receiver", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->schedule_response_stats, "Schedule Response", NULL, NULL, output, end - output);
|
||||
output += print_meas_log(&gNB->rx_prach, "PRACH RX", NULL, NULL, output, end - output);
|
||||
if (ru->feprx)
|
||||
output += print_meas_log(&ru->ofdm_demod_stats, "feprx", NULL, NULL, output, end - output);
|
||||
@@ -310,7 +310,6 @@ void *nrL1_stats_thread(void *param) {
|
||||
reset_meas(&gNB->ul_indication_stats);
|
||||
reset_meas(&gNB->slot_indication_stats);
|
||||
reset_meas(&gNB->rx_pusch_stats);
|
||||
reset_meas(&gNB->schedule_response_stats);
|
||||
reset_meas(&gNB->dlsch_scrambling_stats);
|
||||
reset_meas(&gNB->dlsch_modulation_stats);
|
||||
reset_meas(&gNB->dlsch_resource_mapping_stats);
|
||||
@@ -358,14 +357,6 @@ void init_gNB_Tpool(int inst)
|
||||
// create the TX thread responsible for TX processing start event (L1_tx_out msg queue), then launch tx_func()
|
||||
threadCreate(&gNB->L1_tx_thread, L1_tx_thread, (void *)gNB, "L1_tx_thread", gNB->L1_tx_thread_core, OAI_PRIORITY_RT_MAX);
|
||||
|
||||
notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t), 0, &gNB->L1_tx_out, NULL);
|
||||
processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
|
||||
memset(msgDataTx, 0, sizeof(processingData_L1tx_t));
|
||||
init_DLSCH_struct(gNB, msgDataTx);
|
||||
memset(msgDataTx->ssb, 0, 64 * sizeof(NR_gNB_SSB_t));
|
||||
// this will be removed when the msgDataTx is not necessary anymore
|
||||
gNB->msgDataTx = msgDataTx;
|
||||
|
||||
if (!IS_SOFTMODEM_NOSTATS)
|
||||
threadCreate(&proc->L1_stats_thread, nrL1_stats_thread, (void *)gNB, "L1_stats", -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
@@ -442,7 +433,6 @@ void init_gNB()
|
||||
AssertFatal((gNB->if_inst = NR_IF_Module_init(inst)) != NULL, "Cannot register interface");
|
||||
|
||||
LOG_I(NR_PHY, "Registered with MAC interface module (%p)\n", gNB->if_inst);
|
||||
gNB->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
|
||||
gNB->prach_energy_counter = 0;
|
||||
|
||||
@@ -423,8 +423,6 @@ int start_L1L2(module_id_t gnb_id)
|
||||
/* block threads */
|
||||
oai_exit = 0;
|
||||
sync_var = -1;
|
||||
extern void init_sched_response(void);
|
||||
init_sched_response();
|
||||
|
||||
/* update config */
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
#include "PHY/INIT/phy_init.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "PHY/LTE_TRANSPORT/transport_proto.h"
|
||||
#include "openair1/SCHED_NR/fapi_nr_l1.h"
|
||||
#include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "openair1/PHY/defs_gNB.h"
|
||||
#include <openair1/SCHED/fapi_l1.h>
|
||||
@@ -1108,17 +1107,6 @@ void pnf_nr_phy_deallocate_p7_vendor_ext(void *header)
|
||||
free(header);
|
||||
}
|
||||
|
||||
extern void nr_schedule_ul_dci_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_t *UL_dci_req);
|
||||
int pnf_phy_ul_dci_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_dci_request_t *req)
|
||||
{
|
||||
DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL);
|
||||
PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst?
|
||||
|
||||
nr_schedule_ul_dci_req(gNB, req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) {
|
||||
if (req->hi_dci0_request_body.number_of_dci == 0 && req->hi_dci0_request_body.number_of_hi == 0)
|
||||
@@ -1149,21 +1137,6 @@ int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfa
|
||||
}
|
||||
|
||||
|
||||
// from dl_tti_req_fn fptr
|
||||
extern void nr_schedule_dl_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_request_t *DL_req);
|
||||
int pnf_phy_dl_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_dl_tti_request_t *DL_req)
|
||||
{
|
||||
DevAssert(proc == NULL);
|
||||
DevAssert(sync_var == 0);
|
||||
DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL);
|
||||
PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst?
|
||||
|
||||
nr_schedule_dl_tti_req(gNB, DL_req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) {
|
||||
|
||||
if (RC.eNB == 0) {
|
||||
@@ -1256,18 +1229,6 @@ int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, n
|
||||
}
|
||||
|
||||
|
||||
extern void nr_schedule_tx_req(PHY_VARS_gNB *gNB, nfapi_nr_tx_data_request_t *TX_req);
|
||||
int pnf_phy_tx_data_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_tx_data_request_t *req)
|
||||
{
|
||||
DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL);
|
||||
PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst?
|
||||
|
||||
nr_schedule_tx_req(gNB, req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) {
|
||||
uint16_t sfn = NFAPI_SFNSF2SFN(req->sfn_sf);
|
||||
uint16_t sf = NFAPI_SFNSF2SF(req->sfn_sf);
|
||||
@@ -1293,16 +1254,6 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req);
|
||||
int pnf_phy_ul_tti_req(gNB_L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_nr_ul_tti_request_t *req)
|
||||
{
|
||||
DevAssert(RC.gNB != NULL && RC.gNB[0] != NULL);
|
||||
PHY_VARS_gNB *gNB = RC.gNB[0]; // phy_inst?
|
||||
|
||||
nr_schedule_ul_tti_req(gNB, req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pnf_phy_ul_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) {
|
||||
if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n",
|
||||
__FUNCTION__,
|
||||
@@ -1711,10 +1662,10 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf
|
||||
}
|
||||
|
||||
// NR
|
||||
p7_config->dl_tti_req_fn = &pnf_phy_dl_tti_req;
|
||||
p7_config->ul_tti_req_fn = &pnf_phy_ul_tti_req;
|
||||
p7_config->ul_dci_req_fn = &pnf_phy_ul_dci_req;
|
||||
p7_config->tx_data_req_fn = &pnf_phy_tx_data_req;
|
||||
p7_config->dl_tti_req_fn = NULL;
|
||||
p7_config->ul_tti_req_fn = NULL;
|
||||
p7_config->ul_dci_req_fn = NULL;
|
||||
p7_config->tx_data_req_fn = NULL;
|
||||
|
||||
// LTE
|
||||
p7_config->dl_config_req = &pnf_phy_dl_config_req;
|
||||
@@ -1825,13 +1776,6 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf
|
||||
nfapi_nr_send_pnf_start_resp(config, p7_config->phy_id);
|
||||
printf("[PNF] Sending first P7 slot indication\n");
|
||||
#endif
|
||||
#if 1
|
||||
nfapi_pnf_p7_slot_ind(p7_config, p7_config->phy_id, 0, 0);
|
||||
printf("[PNF] Sent first P7 slot ind\n");
|
||||
#else
|
||||
nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // SFN_SF set to zero - correct???
|
||||
printf("[PNF] Sent first P7 subframe ind\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2321,7 +2265,7 @@ static void maybe_slow_down_pnf(int mu)
|
||||
last_execution = current_execution;
|
||||
}
|
||||
|
||||
void handle_nr_slot_ind(uint16_t sfn, uint16_t slot)
|
||||
void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, NR_Sched_Rsp_t *sched_resp)
|
||||
{
|
||||
nfapi_pnf_p7_config_t *config = p7_config_g;
|
||||
pnf_p7_t *_this = (pnf_p7_t *)(config);
|
||||
@@ -2352,7 +2296,14 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot)
|
||||
oai_nfapi_nr_slot_indication(&ind);
|
||||
|
||||
// copy data from appropriate p7 slot buffers into channel structures for PHY processing
|
||||
nfapi_pnf_p7_slot_ind(config, config->phy_id, sfn, slot);
|
||||
nfapi_pnf_p7_get_msgs(config,
|
||||
config->phy_id,
|
||||
sfn,
|
||||
slot,
|
||||
&sched_resp->DL_req,
|
||||
&sched_resp->UL_tti_req,
|
||||
&sched_resp->UL_dci_req,
|
||||
&sched_resp->TX_req);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,8 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr,
|
||||
void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port);
|
||||
|
||||
void oai_subframe_ind(uint16_t sfn, uint16_t sf);
|
||||
void handle_nr_slot_ind(uint16_t sfn, uint16_t slot);
|
||||
struct NR_Sched_Rsp;
|
||||
void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, struct NR_Sched_Rsp *resp);
|
||||
void sfnslot_add_slot(int mu, uint16_t *sfn, uint16_t *slot, int offset);
|
||||
|
||||
int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind);
|
||||
|
||||
@@ -124,7 +124,6 @@ int vnf_nr_unpack_vendor_extension_tlv(nfapi_tl_t *tl,
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
void install_nr_schedule_handlers(NR_IF_Module_t *if_inst);
|
||||
void install_schedule_handlers(IF_Module_t *if_inst);
|
||||
extern int sf_ahead;
|
||||
|
||||
@@ -326,71 +325,6 @@ int pnf_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wake_gNB_rxtx(PHY_VARS_gNB *gNB, uint16_t sfn, uint16_t slot) {
|
||||
struct timespec curr_t;
|
||||
clock_gettime(CLOCK_MONOTONIC,&curr_t);
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "\n wake_gNB_rxtx before assignment sfn:%d slot:%d TIME %d.%d",sfn,slot,curr_t.tv_sec,curr_t.tv_nsec);
|
||||
gNB_L1_proc_t *proc=&gNB->proc;
|
||||
gNB_L1_rxtx_proc_t *L1_proc= (slot&1)? &proc->L1_proc : &proc->L1_proc_tx;
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "%s(eNB:%p, sfn:%d, sf:%d)\n", __FUNCTION__, eNB, sfn, sf);
|
||||
//int i;
|
||||
struct timespec wait;
|
||||
clock_gettime(CLOCK_REALTIME, &wait);
|
||||
wait.tv_sec = 0;
|
||||
wait.tv_nsec +=5000L;
|
||||
//wait.tv_nsec = 0;
|
||||
// wake up TX for subframe n+sf_ahead
|
||||
// lock the TX mutex and make sure the thread is ready
|
||||
AssertFatal(gNB->if_inst->sl_ahead==6,"gNB->if_inst->sl_ahead %d : This is hard-coded to 6 in nfapi P7!!!\n",gNB->if_inst->sl_ahead);
|
||||
if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt );
|
||||
exit_fun( "error locking mutex_rxtx" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
{
|
||||
static uint16_t old_slot = 0;
|
||||
static uint16_t old_sfn = 0;
|
||||
proc->slot_rx = old_slot;
|
||||
proc->frame_rx = old_sfn;
|
||||
// Try to be 1 frame back
|
||||
old_slot = slot;
|
||||
old_sfn = sfn;
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "\n wake_gNB_rxtx after assignment sfn:%d slot:%d",proc->frame_rx,proc->slot_rx);
|
||||
if (old_slot == 0 && old_sfn % 100 == 0) LOG_W( PHY,"[gNB] sfn/slot:%d%d old_sfn/slot:%d%d proc[rx:%d%d]\n", sfn, slot, old_sfn, old_slot, proc->frame_rx, proc->slot_rx);
|
||||
}
|
||||
|
||||
++L1_proc->instance_cnt;
|
||||
//LOG_D( PHY,"[VNF-subframe_ind] sfn/sf:%d:%d proc[frame_rx:%d subframe_rx:%d] L1_proc->instance_cnt_rxtx:%d \n", sfn, sf, proc->frame_rx, proc->subframe_rx, L1_proc->instance_cnt_rxtx);
|
||||
// We have just received and processed the common part of a subframe, say n.
|
||||
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
|
||||
// transmitted timestamp of the next TX slot (first).
|
||||
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
|
||||
// we want to generate subframe (n+N), so TS_tx = TX_rx+N*samples_per_tti,
|
||||
// and proc->subframe_tx = proc->subframe_rx+sf_ahead
|
||||
L1_proc->timestamp_tx = proc->timestamp_rx + (gNB->if_inst->sl_ahead *fp->samples_per_subframe);
|
||||
L1_proc->frame_rx = proc->frame_rx;
|
||||
L1_proc->slot_rx = proc->slot_rx;
|
||||
L1_proc->frame_tx = (L1_proc->slot_rx > (19-gNB->if_inst->sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx;
|
||||
L1_proc->slot_tx = (L1_proc->slot_rx + gNB->if_inst->sl_ahead)%20;
|
||||
|
||||
//LOG_D(PHY, "sfn/sf:%d%d proc[rx:%d%d] rx:%d%d] About to wake rxtx thread\n\n", sfn, slot, proc->frame_rx, proc->slot_rx, L1_proc->frame_rx, L1_proc->slot_rx);
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "\nEntering wake_gNB_rxtx sfn %d slot %d\n",L1_proc->frame_rx,L1_proc->slot_rx);
|
||||
// the thread can now be woken up
|
||||
if (pthread_cond_signal(&L1_proc->cond) != 0) {
|
||||
LOG_E( PHY, "[gNB] ERROR pthread_cond_signal for gNB RXn-TXnp4 thread\n");
|
||||
exit_fun( "ERROR pthread_clond_signal" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
//LOG_D(PHY,"%s() About to attempt pthread_mutex_unlock\n", __FUNCTION__);
|
||||
pthread_mutex_unlock( &L1_proc->mutex );
|
||||
//LOG_D(PHY,"%s() UNLOCKED pthread_mutex_unlock\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) {
|
||||
L1_proc_t *proc=&eNB->proc;
|
||||
L1_rxtx_proc_t *L1_proc= (sf&1)? &proc->L1_proc : &proc->L1_proc_tx;
|
||||
@@ -498,28 +432,6 @@ int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) {
|
||||
}
|
||||
|
||||
|
||||
int phy_slot_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn, uint16_t slot) {
|
||||
static uint8_t first_time = 1;
|
||||
|
||||
if (first_time) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] slot indication %d.%d\n", sfn, slot);
|
||||
first_time = 0;
|
||||
}
|
||||
|
||||
if (RC.gNB && RC.gNB[0]->configured) {
|
||||
// uint16_t sfn = NFAPI_SFNSF2SFN(sfn_sf);
|
||||
// uint16_t sf = NFAPI_SFNSF2SF(sfn_sf);
|
||||
LOG_D(PHY,"[VNF] slot indication sfn:%d slot:%d\n", sfn, slot);
|
||||
wake_gNB_rxtx(RC.gNB[0], sfn, slot); // DONE: find NR equivalent
|
||||
} else {
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() RC.gNB:%p\n", __FUNCTION__, RC.gNB);
|
||||
|
||||
if (RC.gNB) NFAPI_TRACE(NFAPI_TRACE_INFO, "RC.gNB[0]->configured:%d\n", RC.gNB[0]->configured);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int phy_subframe_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) {
|
||||
static uint8_t first_time = 1;
|
||||
|
||||
@@ -971,65 +883,63 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_
|
||||
//NR phy indication
|
||||
|
||||
|
||||
NR_Sched_Rsp_t g_sched_resp;
|
||||
void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slot, NR_Sched_Rsp_t* sched_info);
|
||||
int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req);
|
||||
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req);
|
||||
int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t* tx_data_req);
|
||||
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t* ul_dci_req);
|
||||
|
||||
int trigger_scheduler(nfapi_nr_slot_indication_scf_t *slot_ind)
|
||||
{
|
||||
// Call into the scheduler (this is hardcoded and should be init properly!)
|
||||
// memset(sched_resp, 0, sizeof(*sched_resp));
|
||||
gNB_dlsch_ulsch_scheduler(0, slot_ind->sfn, slot_ind->slot, &g_sched_resp);
|
||||
|
||||
#ifdef ENABLE_AERIAL
|
||||
bool send_slt_resp = false;
|
||||
if (g_sched_resp.DL_req.dl_tti_request_body.nPDUs> 0) {
|
||||
oai_fapi_dl_tti_req(&g_sched_resp.DL_req);
|
||||
send_slt_resp = true;
|
||||
}
|
||||
if (g_sched_resp.UL_tti_req.n_pdus > 0) {
|
||||
oai_fapi_ul_tti_req(&g_sched_resp.UL_tti_req);
|
||||
send_slt_resp = true;
|
||||
}
|
||||
if (g_sched_resp.TX_req.Number_of_PDUs > 0) {
|
||||
oai_fapi_tx_data_req(&g_sched_resp.TX_req);
|
||||
send_slt_resp = true;
|
||||
}
|
||||
if (g_sched_resp.UL_dci_req.numPdus > 0) {
|
||||
oai_fapi_ul_dci_req(&g_sched_resp.UL_dci_req);
|
||||
send_slt_resp = true;
|
||||
}
|
||||
if (send_slt_resp) {
|
||||
oai_fapi_send_end_request(0,slot_ind->sfn, slot_ind->slot);
|
||||
}
|
||||
#else
|
||||
if (g_sched_resp.DL_req.dl_tti_request_body.nPDUs > 0)
|
||||
oai_nfapi_dl_tti_req(&g_sched_resp.DL_req);
|
||||
|
||||
if (g_sched_resp.UL_tti_req.n_pdus > 0)
|
||||
oai_nfapi_ul_tti_req(&g_sched_resp.UL_tti_req);
|
||||
|
||||
if (g_sched_resp.TX_req.Number_of_PDUs > 0)
|
||||
oai_nfapi_tx_data_req(&g_sched_resp.TX_req);
|
||||
|
||||
if (g_sched_resp.UL_dci_req.numPdus > 0)
|
||||
oai_nfapi_ul_dci_req(&g_sched_resp.UL_dci_req);
|
||||
#endif
|
||||
|
||||
NR_UL_IND_t ind = {.frame = slot_ind->sfn, .slot = slot_ind->slot, };
|
||||
NR_UL_indication(&ind);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int phy_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind)
|
||||
{
|
||||
LOG_D(MAC, "VNF SFN/Slot %d.%d \n", ind->sfn, ind->slot);
|
||||
|
||||
trigger_scheduler(ind);
|
||||
// this variable is very big (multiple MB), so we put it into static storage
|
||||
// to not overflow the stack while still having it in local (function) scope
|
||||
// also, phy_nr_slot_indication() is only executed by one thread, serially
|
||||
static NR_Sched_Rsp_t sched_response;
|
||||
NR_IF_Module_t *ifi = RC.nrmac[0]->if_inst;
|
||||
ifi->NR_slot_indication(ind, &sched_response);
|
||||
|
||||
#ifdef ENABLE_AERIAL
|
||||
bool send_slt_resp = false;
|
||||
if (sched_response.DL_req.dl_tti_request_body.nPDUs> 0) {
|
||||
oai_fapi_dl_tti_req(&sched_response.DL_req);
|
||||
send_slt_resp = true;
|
||||
}
|
||||
if (sched_response.UL_tti_req.n_pdus > 0) {
|
||||
oai_fapi_ul_tti_req(&sched_response.UL_tti_req);
|
||||
send_slt_resp = true;
|
||||
}
|
||||
if (sched_response.TX_req.Number_of_PDUs > 0) {
|
||||
oai_fapi_tx_data_req(&sched_response.TX_req);
|
||||
send_slt_resp = true;
|
||||
}
|
||||
if (sched_response.UL_dci_req.numPdus > 0) {
|
||||
oai_fapi_ul_dci_req(&sched_response.UL_dci_req);
|
||||
send_slt_resp = true;
|
||||
}
|
||||
if (send_slt_resp) {
|
||||
oai_fapi_send_end_request(0, ind->sfn, ind->slot);
|
||||
}
|
||||
#else
|
||||
if (sched_response.DL_req.dl_tti_request_body.nPDUs > 0)
|
||||
oai_nfapi_dl_tti_req(&sched_response.DL_req);
|
||||
|
||||
if (sched_response.UL_tti_req.n_pdus > 0)
|
||||
oai_nfapi_ul_tti_req(&sched_response.UL_tti_req);
|
||||
|
||||
if (sched_response.TX_req.Number_of_PDUs > 0)
|
||||
oai_nfapi_tx_data_req(&sched_response.TX_req);
|
||||
|
||||
if (sched_response.UL_dci_req.numPdus > 0)
|
||||
oai_nfapi_ul_dci_req(&sched_response.UL_dci_req);
|
||||
#endif
|
||||
|
||||
/* the below works because the function behind the callback collects
|
||||
* messages from queue into which messages have been copied.
|
||||
* TODO we should have different callbacks for received messages and call
|
||||
* into the scheduler separately for each message instead of one big one. */
|
||||
NR_UL_IND_t ul_ind = {.frame = ind->sfn, .slot = ind->slot, };
|
||||
ifi->NR_UL_indication(&ul_ind);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1305,7 +1215,7 @@ void *configure_nr_p7_vnf(void *ptr)
|
||||
p7_vnf->config->port = p7_vnf->local_port;
|
||||
#ifndef ENABLE_AERIAL
|
||||
p7_vnf->config->sync_indication = &phy_sync_indication;
|
||||
p7_vnf->config->slot_indication = &phy_slot_indication;
|
||||
p7_vnf->config->slot_indication = NULL;
|
||||
p7_vnf->config->harq_indication = &phy_harq_indication;
|
||||
#endif
|
||||
p7_vnf->config->nr_crc_indication = &phy_nr_crc_indication;
|
||||
@@ -1367,7 +1277,7 @@ void *vnf_p7_thread_start(void *ptr) {
|
||||
p7_vnf->config->port = p7_vnf->local_port;
|
||||
p7_vnf->config->sync_indication = &phy_sync_indication;
|
||||
p7_vnf->config->subframe_indication = &phy_subframe_indication;
|
||||
p7_vnf->config->slot_indication = &phy_slot_indication;
|
||||
p7_vnf->config->slot_indication = NULL;
|
||||
|
||||
p7_vnf->config->harq_indication = &phy_harq_indication;
|
||||
p7_vnf->config->crc_indication = &phy_crc_indication;
|
||||
|
||||
@@ -145,8 +145,14 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7);
|
||||
int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len);
|
||||
int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len);
|
||||
|
||||
|
||||
int pnf_p7_slot_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot);
|
||||
int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7,
|
||||
uint16_t phy_id,
|
||||
uint16_t sfn,
|
||||
uint16_t slot,
|
||||
nfapi_nr_dl_tti_request_t* ret_dl_tti,
|
||||
nfapi_nr_ul_tti_request_t* ret_ul_tti,
|
||||
nfapi_nr_ul_dci_request_t* ret_ul_dci,
|
||||
nfapi_nr_tx_data_request_t* ret_tx_data);
|
||||
int pnf_p7_subframe_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn_sf);
|
||||
int nfapi_pnf_p7_nr_slot_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_slot_indication_scf_t* ind);
|
||||
int nfapi_pnf_p7_nr_rx_data_ind(nfapi_pnf_p7_config_t* config, nfapi_nr_rx_data_indication_t* ind);
|
||||
|
||||
@@ -856,7 +856,7 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config);
|
||||
*/
|
||||
int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config);
|
||||
|
||||
/*! NR Slot indication
|
||||
/*! NR get stuff
|
||||
* message copied from nfapi_pnf_p7_subframe_ind
|
||||
* \param config A pointer to a PNF P7 config
|
||||
* \param phy_id The phy_id for the phy instance
|
||||
@@ -868,8 +868,14 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config);
|
||||
*
|
||||
* If messages are not in the subframe buffer, they dummy subframe messages will be sent
|
||||
*/
|
||||
int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot);
|
||||
|
||||
int nfapi_pnf_p7_get_msgs(nfapi_pnf_p7_config_t* config,
|
||||
uint16_t phy_id,
|
||||
uint16_t sfn,
|
||||
uint16_t slot,
|
||||
nfapi_nr_dl_tti_request_t* ret_dl_tti,
|
||||
nfapi_nr_ul_tti_request_t* ret_ul_tti,
|
||||
nfapi_nr_ul_dci_request_t* ret_ul_dci,
|
||||
nfapi_nr_tx_data_request_t* ret_tx_data);
|
||||
|
||||
/*! Subframe indication
|
||||
* \param config A pointer to a PNF P7 config
|
||||
|
||||
@@ -672,52 +672,48 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t slot)
|
||||
int nr_pnf_p7_get_msgs(pnf_p7_t* pnf_p7,
|
||||
uint16_t phy_id,
|
||||
uint16_t sfn,
|
||||
uint16_t slot,
|
||||
nfapi_nr_dl_tti_request_t* ret_dl_tti,
|
||||
nfapi_nr_ul_tti_request_t* ret_ul_tti,
|
||||
nfapi_nr_ul_dci_request_t* ret_ul_dci,
|
||||
nfapi_nr_tx_data_request_t* ret_tx_data)
|
||||
{
|
||||
//This function is aligned with rx sfn/slot
|
||||
|
||||
// We could either send an event to the p7 thread have have it run the
|
||||
// subframe or we could handle it here and lock access to the subframe
|
||||
// buffers. If we do it on the p7 thread then we run the risk of blocking
|
||||
// on the udp send.
|
||||
|
||||
// todo : consider a more efficent lock mechasium
|
||||
//uint16_t NUM_SLOTS = 20;//10* 2^mu
|
||||
|
||||
if(pthread_mutex_lock(&(pnf_p7->mutex)) != 0)
|
||||
{
|
||||
if (pthread_mutex_lock(&(pnf_p7->mutex)) != 0) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to lock mutex\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// save the curren time, sfn and slot
|
||||
// TODO useful?
|
||||
pnf_p7->slot_start_time_hr = pnf_get_current_time_hr();
|
||||
|
||||
//We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs slot_ahead from rx thread.
|
||||
|
||||
// We align the pnf_p7 sfn/slot with tx sfn/slot, and vnf is synced with pnf_p7 sfn/slot. This is so that the scheduler runs
|
||||
// slot_ahead from rx thread.
|
||||
pnf_p7->sfn = sfn;
|
||||
pnf_p7->slot = slot;
|
||||
|
||||
uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(pnf_p7->mu, sfn,slot);
|
||||
uint32_t tx_slot_dec = NFAPI_SFNSLOT2DEC(pnf_p7->mu, sfn, slot);
|
||||
uint8_t buffer_index_tx = tx_slot_dec % NFAPI_SLOTNUM(pnf_p7->mu);
|
||||
|
||||
// If the subframe_buffer has been configured
|
||||
if(pnf_p7->_public.slot_buffer_size!= 0) // for now value is same as sf_buffer_size
|
||||
if (pnf_p7->_public.slot_buffer_size != 0) // for now value is same as sf_buffer_size
|
||||
{
|
||||
|
||||
// apply the shift to the incoming sfn_sf
|
||||
if(pnf_p7->slot_shift != 0) // see in vnf_build_send_dl_node_sync
|
||||
if (pnf_p7->slot_shift != 0) // see in vnf_build_send_dl_node_sync
|
||||
{
|
||||
uint16_t shifted_slot = slot + pnf_p7->slot_shift;
|
||||
|
||||
// adjust for wrap-around
|
||||
if(shifted_slot < 0)
|
||||
if (shifted_slot < 0)
|
||||
shifted_slot += NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu);
|
||||
else if(shifted_slot > NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu))
|
||||
else if (shifted_slot > NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu))
|
||||
shifted_slot -= NFAPI_MAX_SFNSLOTDEC(pnf_p7->mu);
|
||||
|
||||
// NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/slot (%d -> %d)\n", pnf_p7->sfn_slot_shift, NFAPI_SFNSF2DEC(sfn_slot), shifted_sfn_slot);
|
||||
//NFAPI_TRACE(NFAPI_TRACE_INFO, "Applying shift %d to sfn/slot (%d -> %d)\n", pnf_p7->sfn_slot_shift,
|
||||
//NFAPI_SFNSF2DEC(sfn_slot), shifted_sfn_slot);
|
||||
slot = shifted_slot;
|
||||
|
||||
//
|
||||
@@ -729,64 +725,77 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl
|
||||
|
||||
nfapi_pnf_p7_slot_buffer_t* tx_slot_buffer = &(pnf_p7->slot_buffer[buffer_index_tx]);
|
||||
|
||||
ret_dl_tti->SFN = sfn;
|
||||
ret_dl_tti->Slot = slot;
|
||||
ret_dl_tti->dl_tti_request_body.nPDUs = 0;
|
||||
ret_tx_data->SFN = sfn;
|
||||
ret_tx_data->Slot = slot;
|
||||
ret_tx_data->Number_of_PDUs = 0;
|
||||
nfapi_nr_dl_tti_request_t* dl_tti_req = &tx_slot_buffer->dl_tti_req;
|
||||
nfapi_nr_tx_data_request_t* tx_data_req = &tx_slot_buffer->tx_data_req;
|
||||
if (dl_tti_req->dl_tti_request_body.nPDUs > 0 && dl_tti_req->SFN == sfn && dl_tti_req->Slot == slot) {
|
||||
DevAssert(pnf_p7->_public.dl_tti_req_fn != NULL);
|
||||
DevAssert(pnf_p7->_public.tx_data_req_fn != NULL);
|
||||
if (tx_data_req->Number_of_PDUs > 0 && tx_data_req->SFN == sfn && tx_data_req->Slot == slot) {
|
||||
(pnf_p7->_public.dl_tti_req_fn)(NULL, &(pnf_p7->_public), dl_tti_req);
|
||||
(pnf_p7->_public.tx_data_req_fn)(&(pnf_p7->_public), tx_data_req);
|
||||
} else {
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%4d.%2d no corresponding tx_data.request for dl_tti.request, dropping\n", sfn, slot);
|
||||
nfapi_nr_tx_data_request_t* txd = &tx_slot_buffer->tx_data_req;
|
||||
if (dl_tti_req->SFN == sfn && dl_tti_req->Slot == slot && txd->SFN == sfn && txd->Slot == slot) {
|
||||
nfapi_nr_dl_tti_request_body_t* p_tti = &dl_tti_req->dl_tti_request_body;
|
||||
int ret_idx = 0;
|
||||
for (int i = 0; i < p_tti->nPDUs; ++i) {
|
||||
int tx_index = p_tti->dl_tti_pdu_list[i].pdsch_pdu.pdsch_pdu_rel15.pduIndex - 1;
|
||||
if (tx_index >= txd->Number_of_PDUs) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR,
|
||||
"%4d.%2d no corresponding tx_data.request for dl_tti.request index %d, dropping\n",
|
||||
sfn,
|
||||
slot,
|
||||
tx_index);
|
||||
continue;
|
||||
}
|
||||
ret_dl_tti->dl_tti_request_body.dl_tti_pdu_list[ret_idx] = p_tti->dl_tti_pdu_list[i];
|
||||
// TODO avoid huge copy
|
||||
ret_tx_data->pdu_list[ret_idx] = txd->pdu_list[i];
|
||||
ret_idx++;
|
||||
}
|
||||
ret_dl_tti->dl_tti_request_body.nPDUs = ret_idx;
|
||||
ret_tx_data->Number_of_PDUs = ret_idx;
|
||||
|
||||
tx_slot_buffer->dl_tti_req.SFN = -1;
|
||||
tx_slot_buffer->dl_tti_req.Slot = -1;
|
||||
tx_slot_buffer->tx_data_req.SFN = -1;
|
||||
tx_slot_buffer->tx_data_req.Slot = -1;
|
||||
}
|
||||
if (tx_data_req->Number_of_PDUs > 0 && tx_data_req->SFN == sfn && tx_data_req->Slot == slot) {
|
||||
// there is a tx_data.request in this slot, but no corresponding
|
||||
// dl_tti.request (when they need to come pairwise)
|
||||
NFAPI_TRACE(NFAPI_TRACE_ERROR, "%4d.%2d no corresponding dl_tti.request for tx_data.request, dropping\n", sfn, slot);
|
||||
tx_slot_buffer->tx_data_req.SFN = -1;
|
||||
tx_slot_buffer->tx_data_req.Slot = -1;
|
||||
}
|
||||
|
||||
if(tx_slot_buffer->ul_tti_req.n_pdus > 0 && tx_slot_buffer->ul_tti_req.SFN == sfn && tx_slot_buffer->ul_tti_req.Slot == slot)
|
||||
{
|
||||
DevAssert(pnf_p7->_public.ul_tti_req_fn != NULL);
|
||||
(pnf_p7->_public.ul_tti_req_fn)(NULL, &(pnf_p7->_public), &tx_slot_buffer->ul_tti_req);
|
||||
ret_ul_tti->SFN = sfn;
|
||||
ret_ul_tti->Slot = slot;
|
||||
ret_ul_tti->n_pdus = 0;
|
||||
if (tx_slot_buffer->ul_tti_req.SFN == sfn && tx_slot_buffer->ul_tti_req.Slot == slot) {
|
||||
nfapi_nr_ul_tti_request_t* p = &tx_slot_buffer->ul_tti_req;
|
||||
ret_ul_tti->n_pdus = p->n_pdus;
|
||||
for (int i = 0; i < p->n_pdus; ++i)
|
||||
ret_ul_tti->pdus_list[i] = p->pdus_list[i];
|
||||
tx_slot_buffer->ul_tti_req.SFN = -1;
|
||||
tx_slot_buffer->ul_tti_req.Slot = -1;
|
||||
}
|
||||
|
||||
if(tx_slot_buffer->ul_dci_req.numPdus > 0 && tx_slot_buffer->ul_dci_req.SFN == sfn && tx_slot_buffer->ul_dci_req.Slot == slot)
|
||||
{
|
||||
DevAssert(pnf_p7->_public.ul_dci_req_fn != NULL);
|
||||
(pnf_p7->_public.ul_dci_req_fn)(NULL, &(pnf_p7->_public), &tx_slot_buffer->ul_dci_req);
|
||||
ret_ul_dci->SFN = sfn;
|
||||
ret_ul_dci->Slot = slot;
|
||||
ret_ul_dci->numPdus = 0;
|
||||
if (tx_slot_buffer->ul_dci_req.SFN == sfn && tx_slot_buffer->ul_dci_req.Slot == slot) {
|
||||
nfapi_nr_ul_dci_request_t* p = &tx_slot_buffer->ul_dci_req;
|
||||
ret_ul_dci->numPdus = p->numPdus;
|
||||
for (int i = 0; i < p->numPdus; ++i)
|
||||
ret_ul_dci->ul_dci_pdu_list[i] = p->ul_dci_pdu_list[i];
|
||||
tx_slot_buffer->ul_dci_req.SFN = -1;
|
||||
tx_slot_buffer->ul_dci_req.Slot = -1;
|
||||
}
|
||||
|
||||
//send the periodic timing info if configured
|
||||
if(pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period)
|
||||
{
|
||||
// send the periodic timing info if configured
|
||||
if (pnf_p7->_public.timing_info_mode_periodic && (pnf_p7->timing_info_period_counter++) == pnf_p7->_public.timing_info_period) {
|
||||
pnf_nr_pack_and_send_timing_info(pnf_p7);
|
||||
|
||||
pnf_p7->timing_info_period_counter = 0;
|
||||
}
|
||||
else if(pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send)
|
||||
{
|
||||
} else if (pnf_p7->_public.timing_info_mode_aperiodic && pnf_p7->timing_info_aperiodic_send) {
|
||||
pnf_nr_pack_and_send_timing_info(pnf_p7);
|
||||
|
||||
pnf_p7->timing_info_aperiodic_send = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
pnf_p7->timing_info_ms_counter++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (sfn % 128 == 0 && slot == 0) {
|
||||
@@ -794,14 +803,19 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl
|
||||
int ontime = s->dl_tti.ontime + s->ul_tti.ontime + s->ul_dci.ontime + s->tx_data.ontime;
|
||||
int late = s->dl_tti.late + s->ul_tti.late + s->ul_dci.late + s->tx_data.late;
|
||||
|
||||
float dl_thr = (float) s->dl.bytes * 8 / 1000 / 1000 / 1.28f; // every 128 frames = 1.28 s
|
||||
float ul_thr = (float) s->ul.bytes * 8 / 1000 / 1000 / 1.28f;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[P7:%d] msgs ontime %d thr DL %.2f UL %.2f msg late %d (vtime)\n", pnf_p7->_public.phy_id, ontime, dl_thr, ul_thr, late);
|
||||
float dl_thr = (float)s->dl.bytes * 8 / 1000 / 1000 / 1.28f; // every 128 frames = 1.28 s
|
||||
float ul_thr = (float)s->ul.bytes * 8 / 1000 / 1000 / 1.28f;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO,
|
||||
"[P7:%d] msgs ontime %d thr DL %.2f UL %.2f msg late %d (vtime)\n",
|
||||
pnf_p7->_public.phy_id,
|
||||
ontime,
|
||||
dl_thr,
|
||||
ul_thr,
|
||||
late);
|
||||
memset(s, 0, sizeof(*s));
|
||||
}
|
||||
|
||||
if(pthread_mutex_unlock(&(pnf_p7->mutex)) != 0)
|
||||
{
|
||||
if (pthread_mutex_unlock(&(pnf_p7->mutex)) != 0) {
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "failed to unlock mutex\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -809,8 +823,6 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf)
|
||||
{
|
||||
// We could either send an event to the p7 thread have have it run the
|
||||
|
||||
@@ -89,15 +89,22 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot)
|
||||
int nfapi_pnf_p7_get_msgs(nfapi_pnf_p7_config_t* config,
|
||||
uint16_t phy_id,
|
||||
uint16_t sfn,
|
||||
uint16_t slot,
|
||||
nfapi_nr_dl_tti_request_t* ret_dl_tti,
|
||||
nfapi_nr_ul_tti_request_t* ret_ul_tti,
|
||||
nfapi_nr_ul_dci_request_t* ret_ul_dci,
|
||||
nfapi_nr_tx_data_request_t* ret_tx_data)
|
||||
{
|
||||
// Verify that config is not null
|
||||
if(config == 0)
|
||||
if (config == 0)
|
||||
return -1;
|
||||
|
||||
pnf_p7_t* _this = (pnf_p7_t*)(config);
|
||||
|
||||
return pnf_p7_slot_ind(_this, phy_id, sfn, slot);
|
||||
return nr_pnf_p7_get_msgs(_this, phy_id, sfn, slot, ret_dl_tti, ret_ul_tti, ret_ul_dci, ret_tx_data);
|
||||
}
|
||||
|
||||
int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf)
|
||||
|
||||
@@ -1210,12 +1210,6 @@ void send_dl_subframe_msgs_interleaved(int p7Sock, int phy_id, struct sockaddr_i
|
||||
//free(req.tx_request_body.tx_pdu_list);
|
||||
}
|
||||
|
||||
void send_slot_indication(phy_info_t* phy_info)
|
||||
{
|
||||
// DONE: add sfn and slot as members in the phy_info
|
||||
nfapi_pnf_p7_slot_ind(phy_info->config, phy_info->phy_id, phy_info->sfn, phy_info->slot);
|
||||
}
|
||||
|
||||
void send_subframe_indication(phy_info_t* phy_info)
|
||||
{
|
||||
nfapi_pnf_p7_subframe_ind(phy_info->config, phy_info->phy_id, phy_info->sfn_sf);
|
||||
|
||||
-1
@@ -36,7 +36,6 @@
|
||||
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "defs.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
+13
-25
@@ -39,11 +39,13 @@
|
||||
#include <complex.h>
|
||||
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
|
||||
#include <string.h>
|
||||
#include "nfapi/open-nFAPI/fapi/inc/nr_fapi_p5_utils.h"
|
||||
|
||||
static void init_DLSCH_struct(PHY_VARS_gNB *gNB);
|
||||
static void destroy_DLSCH_struct(const PHY_VARS_gNB *gNB);
|
||||
|
||||
int l1_north_init_gNB()
|
||||
{
|
||||
AssertFatal(RC.nb_nr_L1_inst > 0, "Failed to init PHY callbacks: nb_nr_L1_inst = %d\n", RC.nb_nr_L1_inst);
|
||||
@@ -58,7 +60,6 @@ int l1_north_init_gNB()
|
||||
|
||||
LOG_D(NR_PHY, "RC.gNB[%d]: installing callbacks\n", i);
|
||||
RC.gNB[i]->if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
RC.gNB[i]->if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -155,6 +156,8 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
/// Transport init necessary for NR synchro
|
||||
init_nr_transport(gNB);
|
||||
|
||||
init_DLSCH_struct(gNB);
|
||||
|
||||
gNB->nr_srs_info = (nr_srs_info_t **)malloc16_clear(gNB->max_nb_srs * sizeof(nr_srs_info_t*));
|
||||
for (int id = 0; id < gNB->max_nb_srs; id++) {
|
||||
gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
|
||||
@@ -241,6 +244,8 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
|
||||
reset_nr_transport(gNB);
|
||||
|
||||
destroy_DLSCH_struct(gNB);
|
||||
|
||||
NR_gNB_COMMON * common_vars = &gNB->common_vars;
|
||||
for (int j = 0; j < common_vars->num_beams_period; j++) {
|
||||
if (common_vars->beam_id)
|
||||
@@ -281,13 +286,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB)
|
||||
|
||||
}
|
||||
|
||||
//Adding nr_schedule_handler
|
||||
void install_nr_schedule_handlers(NR_IF_Module_t *if_inst)
|
||||
{
|
||||
if_inst->NR_PHY_config_req = nr_phy_config_request;
|
||||
if_inst->NR_Schedule_response = nr_schedule_response;
|
||||
}
|
||||
|
||||
void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,
|
||||
int N_RB_DL,
|
||||
int N_RB_UL,
|
||||
@@ -401,37 +399,27 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config)
|
||||
init_timeshift_rotation(fp);
|
||||
}
|
||||
|
||||
void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg)
|
||||
static void init_DLSCH_struct(PHY_VARS_gNB *gNB)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value;
|
||||
msg->num_pdsch_slot = 0;
|
||||
|
||||
msg->dlsch = malloc16(gNB->max_nb_pdsch * sizeof(NR_gNB_DLSCH_t *));
|
||||
int num_cw = NR_MAX_NB_LAYERS > 4? 2:1;
|
||||
gNB->dlsch = calloc(gNB->max_nb_pdsch, sizeof(*gNB->dlsch));
|
||||
for (int i = 0; i < gNB->max_nb_pdsch; i++) {
|
||||
LOG_D(PHY, "Allocating Transport Channel Buffers for DLSCH %d/%d\n", i, gNB->max_nb_pdsch);
|
||||
msg->dlsch[i] = (NR_gNB_DLSCH_t *)malloc16(num_cw * sizeof(NR_gNB_DLSCH_t));
|
||||
for (int j = 0; j < num_cw; j++) {
|
||||
msg->dlsch[i][j] = new_gNB_dlsch(fp, grid_size);
|
||||
}
|
||||
gNB->dlsch[i] = new_gNB_dlsch(fp, grid_size);
|
||||
}
|
||||
}
|
||||
|
||||
void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg)
|
||||
static void destroy_DLSCH_struct(const PHY_VARS_gNB *gNB)
|
||||
{
|
||||
const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
const nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
const uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value;
|
||||
int num_cw = NR_MAX_NB_LAYERS > 4? 2:1;
|
||||
for (int i = 0; i < gNB->max_nb_pdsch; i++) {
|
||||
for (int j = 0; j < num_cw; j++) {
|
||||
free_gNB_dlsch(&msg->dlsch[i][j], grid_size, fp);
|
||||
free_gNB_dlsch(&gNB->dlsch[i], grid_size, fp);
|
||||
}
|
||||
free(msg->dlsch[i]);
|
||||
}
|
||||
free(msg->dlsch);
|
||||
free(gNB->dlsch);
|
||||
}
|
||||
|
||||
void init_nr_transport(PHY_VARS_gNB *gNB)
|
||||
|
||||
@@ -46,9 +46,6 @@ int l1_north_init_gNB(void);
|
||||
void init_nr_transport(PHY_VARS_gNB *gNB);
|
||||
void reset_nr_transport(PHY_VARS_gNB *gNB);
|
||||
|
||||
void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg);
|
||||
void reset_DLSCH_struct(const PHY_VARS_gNB *gNB, processingData_L1tx_t *msg);
|
||||
|
||||
void RCconfig_nrUE_prs(void *cfg);
|
||||
void init_nr_prs_ue_vars(PHY_VARS_NR_UE *ue);
|
||||
void nr_init_dl_harq_processes(NR_DL_UE_HARQ_t harq_list[2][NR_MAX_DLSCH_HARQ_PROCESSES], int number_of_processes, int num_rb);
|
||||
|
||||
@@ -51,8 +51,8 @@ static void nr_pdcch_scrambling(uint32_t *in, uint32_t size, uint32_t Nid, uint3
|
||||
out[i] = in[i] ^ seq[i];
|
||||
}
|
||||
|
||||
static void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
int txdataF_offset,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot)
|
||||
@@ -237,16 +237,3 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
*(unsigned long long *)dci_pdu->Payload);
|
||||
} // for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++)
|
||||
}
|
||||
|
||||
void nr_generate_dci_top(processingData_L1tx_t *msgTx, int slot, int txdataF_offset)
|
||||
{
|
||||
PHY_VARS_gNB *gNB = msgTx->gNB;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
start_meas(&gNB->dci_generation_stats);
|
||||
for (int i = 0; i < msgTx->num_ul_pdcch; i++)
|
||||
nr_generate_dci(msgTx->gNB, &msgTx->ul_pdcch_pdu[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, frame_parms, slot);
|
||||
for (int i = 0; i < msgTx->num_dl_pdcch; i++)
|
||||
nr_generate_dci(msgTx->gNB, &msgTx->pdcch_pdu[i].pdcch_pdu_rel15, txdataF_offset, frame_parms, slot);
|
||||
stop_meas(&gNB->dci_generation_stats);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@
|
||||
#include "PHY/NR_REFSIG/nr_refsig.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
|
||||
|
||||
void nr_generate_dci_top(processingData_L1tx_t *msgTx, int slot, int txdataF_offset);
|
||||
void nr_generate_dci(PHY_VARS_gNB *gNB,
|
||||
const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15,
|
||||
int txdataF_offset,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot);
|
||||
|
||||
int16_t find_nr_pdcch(int frame,int slot, PHY_VARS_gNB *gNB,find_type_t type);
|
||||
|
||||
@@ -42,6 +46,6 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB,
|
||||
int slot,
|
||||
nfapi_nr_ul_dci_request_pdus_t *pdcch_pdu);
|
||||
|
||||
void nr_fill_reg_list(int cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15);
|
||||
void nr_fill_reg_list(int cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15);
|
||||
|
||||
#endif //__PHY_NR_TRANSPORT_DCI__H
|
||||
|
||||
@@ -42,7 +42,7 @@ int compfunc(const void *a, const void *b)
|
||||
return (*(int *)a - *(int *)b);
|
||||
}
|
||||
|
||||
void nr_fill_reg_list(int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15)
|
||||
void nr_fill_reg_list(int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE], const nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15)
|
||||
{
|
||||
int bsize = pdcch_pdu_rel15->RegBundleSize;
|
||||
int R = pdcch_pdu_rel15->InterleaverSize;
|
||||
|
||||
@@ -51,7 +51,7 @@ static void nr_pdsch_codeword_scrambling(uint8_t *in, uint32_t size, uint8_t q,
|
||||
nr_codeword_scrambling(in, size, q, Nid, n_RNTI, out);
|
||||
}
|
||||
|
||||
static int do_ptrs_symbol(nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15,
|
||||
static int do_ptrs_symbol(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15,
|
||||
int start_sc,
|
||||
int symbol_sz,
|
||||
c16_t *txF,
|
||||
@@ -339,7 +339,7 @@ static inline void neg_dmrs(c16_t *in, c16_t *out, int sz)
|
||||
|
||||
static inline int do_onelayer(NR_DL_FRAME_PARMS *frame_parms,
|
||||
int slot,
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15,
|
||||
const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15,
|
||||
int layer,
|
||||
c16_t *output,
|
||||
c16_t *txl_start,
|
||||
@@ -457,7 +457,7 @@ static inline void do_txdataF(c16_t **txdataF,
|
||||
int symbol_sz,
|
||||
c16_t txdataF_precoding[][symbol_sz],
|
||||
PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15,
|
||||
const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15,
|
||||
int ant,
|
||||
int start_sc,
|
||||
int txdataF_offset_per_symbol)
|
||||
@@ -465,7 +465,7 @@ static inline void do_txdataF(c16_t **txdataF,
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
int rb = 0;
|
||||
uint16_t subCarrier = start_sc;
|
||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||
const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||
while (rb < rel15->rbSize) {
|
||||
// get pmi info
|
||||
const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0;
|
||||
@@ -555,8 +555,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
|
||||
time_stats_t *dlsch_scrambling_stats = &gNB->dlsch_scrambling_stats;
|
||||
time_stats_t *dlsch_modulation_stats = &gNB->dlsch_modulation_stats;
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15;
|
||||
const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB;
|
||||
const int symbol_sz=frame_parms->ofdm_symbol_size;
|
||||
const int dmrs_Type = rel15->dmrsConfigType;
|
||||
@@ -580,7 +579,6 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
/* PTRS */
|
||||
uint16_t dlPtrsSymPos = 0;
|
||||
int n_ptrs = 0;
|
||||
uint32_t ptrsSymbPerSlot = 0;
|
||||
if (rel15->pduBitmap & 0x1) {
|
||||
set_ptrs_symb_idx(&dlPtrsSymPos,
|
||||
rel15->NrOfSymbols,
|
||||
@@ -588,15 +586,13 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
1 << rel15->PTRSTimeDensity,
|
||||
rel15->dlDmrsSymbPos);
|
||||
n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity;
|
||||
ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
||||
}
|
||||
harq->unav_res = ptrsSymbPerSlot * n_ptrs;
|
||||
|
||||
#ifdef DEBUG_DLSCH
|
||||
printf("PDSCH encoding:\nPayload:\n");
|
||||
for (int i = 0; i < (harq->B >> 3); i += 16) {
|
||||
for (int i = 0; i < (dlsch->B >> 3); i += 16) {
|
||||
for (int j = 0; j < 16; j++)
|
||||
printf("0x%02x\t", harq->pdu[i + j]);
|
||||
printf("0x%02x\t", dlsch->pdu[i + j]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\nEncoded payload:\n");
|
||||
@@ -609,7 +605,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
#endif
|
||||
|
||||
if (IS_SOFTMODEM_DLSIM)
|
||||
memcpy(harq->f, input_ptr, (encoded_length + 7) >> 3);
|
||||
memcpy(dlsch->f, input_ptr, (encoded_length + 7) >> 3);
|
||||
|
||||
c16_t mod_symbs[rel15->NrOfCodewords][encoded_length] __attribute__((aligned(64)));
|
||||
for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) {
|
||||
@@ -680,7 +676,7 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
// pmi = prgs_list[rbidx/prg_size].pm_idx, rbidx =0,...,rbSize-1
|
||||
// The Precoding matrix:
|
||||
// The Codebook Type I
|
||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||
const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming;
|
||||
// beam number in multi-beam scenario (concurrent beams)
|
||||
int bitmap = SL_to_bitmap(rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
@@ -777,9 +773,8 @@ static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSC
|
||||
return ((size_output_tb + 511) >> 9) << 6;
|
||||
}
|
||||
|
||||
void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_array, int frame, int slot)
|
||||
{
|
||||
PHY_VARS_gNB *gNB = msgTx->gNB;
|
||||
NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
|
||||
time_stats_t *dlsch_encoding_stats = &gNB->dlsch_encoding_stats;
|
||||
time_stats_t *tinput = &gNB->tinput;
|
||||
@@ -792,10 +787,9 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
|
||||
size_t size_output = 0;
|
||||
|
||||
for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
for (int i = 0; i < n_dlsch; i++) {
|
||||
NR_gNB_DLSCH_t *dlsch = &dlsch_array[i];
|
||||
const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15;
|
||||
|
||||
LOG_D(PHY,
|
||||
"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n",
|
||||
@@ -819,10 +813,10 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity;
|
||||
ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, rel15->StartSymbolIndex, rel15->NrOfSymbols);
|
||||
}
|
||||
harq->unav_res = ptrsSymbPerSlot * n_ptrs;
|
||||
dlsch->unav_res = ptrsSymbPerSlot * n_ptrs;
|
||||
|
||||
/// CRC, coding, interleaving and rate matching
|
||||
AssertFatal(harq->pdu != NULL, "%4d.%2d no HARQ PDU for PDSCH generation\n", msgTx->frame, msgTx->slot);
|
||||
AssertFatal(dlsch->pdu != NULL, "%4d.%2d no PDU for PDSCH generation\n", frame, slot);
|
||||
|
||||
/* output and its parts for each dlsch should be aligned on 64 bytes (or 8 * 64 bits)
|
||||
* => size_output is a sum of parts sizes rounded up to a multiple of 8 * 64
|
||||
@@ -836,7 +830,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
|
||||
start_meas(dlsch_encoding_stats);
|
||||
if (nr_dlsch_encoding(gNB,
|
||||
msgTx,
|
||||
n_dlsch,
|
||||
dlsch_array,
|
||||
frame,
|
||||
slot,
|
||||
frame_parms,
|
||||
@@ -854,8 +849,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot)
|
||||
stop_meas(dlsch_encoding_stats);
|
||||
|
||||
unsigned char *output_ptr = output;
|
||||
for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
output_ptr += do_one_dlsch(output_ptr, gNB, msgTx->dlsch[dlsch_id], slot);
|
||||
for (int i = 0; i < n_dlsch; i++) {
|
||||
output_ptr += do_one_dlsch(output_ptr, gNB, &dlsch_array[i], slot);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,15 +35,11 @@
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
|
||||
void nr_fill_dlsch_dl_tti_req(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu);
|
||||
void nr_fill_dlsch_tx_req(processingData_L1tx_t *msgTx, int idx, uint8_t *sdu);
|
||||
|
||||
void nr_generate_pdsch(processingData_L1tx_t *msgTx,
|
||||
int frame,
|
||||
int slot);
|
||||
void nr_generate_pdsch(PHY_VARS_gNB *gNB, int n_dlsch, NR_gNB_DLSCH_t *dlsch_array, int frame, int slot);
|
||||
|
||||
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
processingData_L1tx_t *msgTx,
|
||||
int n_dlsch,
|
||||
NR_gNB_DLSCH_t *dlsch_array,
|
||||
int frame,
|
||||
uint8_t slot,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
@@ -52,20 +52,19 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM
|
||||
a_segments = a_segments / 273 + 1;
|
||||
}
|
||||
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
if (harq->b) {
|
||||
free16(harq->b, a_segments * 1056);
|
||||
harq->b = NULL;
|
||||
if (dlsch->b) {
|
||||
free16(dlsch->b, a_segments * 1056);
|
||||
dlsch->b = NULL;
|
||||
}
|
||||
if (harq->f) {
|
||||
free16(harq->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
|
||||
harq->f = NULL;
|
||||
if (dlsch->f) {
|
||||
free16(dlsch->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
|
||||
dlsch->f = NULL;
|
||||
}
|
||||
for (int r = 0; r < a_segments; r++) {
|
||||
free(harq->c[r]);
|
||||
harq->c[r] = NULL;
|
||||
free(dlsch->c[r]);
|
||||
dlsch->c[r] = NULL;
|
||||
}
|
||||
free(harq->c);
|
||||
free(dlsch->c);
|
||||
}
|
||||
|
||||
NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB)
|
||||
@@ -80,34 +79,33 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB)
|
||||
|
||||
LOG_D(PHY, "Allocating %d segments (MAX %d, N_PRB %d)\n", a_segments, MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER, N_RB);
|
||||
uint32_t dlsch_bytes = a_segments * 1056; // allocated bytes per segment
|
||||
NR_gNB_DLSCH_t dlsch;
|
||||
NR_gNB_DLSCH_t dlsch = {0};
|
||||
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch.harq_process;
|
||||
bzero(harq, sizeof(NR_DL_gNB_HARQ_t));
|
||||
harq->b = malloc16(dlsch_bytes);
|
||||
AssertFatal(harq->b, "cannot allocate memory for harq->b\n");
|
||||
bzero(harq->b, dlsch_bytes);
|
||||
dlsch.b = malloc16(dlsch_bytes);
|
||||
AssertFatal(dlsch.b, "cannot allocate memory for dlsch.b\n");
|
||||
bzero(dlsch.b, dlsch_bytes);
|
||||
|
||||
harq->c = (uint8_t **)malloc16(a_segments * sizeof(uint8_t *));
|
||||
dlsch.c = (uint8_t **)malloc16(a_segments * sizeof(uint8_t *));
|
||||
for (int r = 0; r < a_segments; r++) {
|
||||
// account for filler in first segment and CRCs for multiple segment case
|
||||
// [hna] 8448 is the maximum CB size in NR
|
||||
// 68*348 = 68*(maximum size of Zc)
|
||||
// In section 5.3.2 in 38.212, the for loop is up to N + 2*Zc (maximum size of N is 66*Zc, therefore 68*Zc)
|
||||
harq->c[r] = malloc16(8448);
|
||||
AssertFatal(harq->c[r], "cannot allocate harq->c[%d]\n", r);
|
||||
bzero(harq->c[r], 8448);
|
||||
dlsch.c[r] = malloc16(8448);
|
||||
AssertFatal(dlsch.c[r], "cannot allocate dlsch.c[%d]\n", r);
|
||||
bzero(dlsch.c[r], 8448);
|
||||
}
|
||||
|
||||
harq->f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
|
||||
AssertFatal(harq->f, "cannot allocate harq->f\n");
|
||||
bzero(harq->f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
|
||||
dlsch.f = malloc16(N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
|
||||
AssertFatal(dlsch.f, "cannot allocate dlsch->f\n");
|
||||
bzero(dlsch.f, N_RB * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8 * NR_MAX_NB_LAYERS);
|
||||
|
||||
return (dlsch);
|
||||
}
|
||||
|
||||
int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
processingData_L1tx_t *msgTx,
|
||||
int n_dlsch,
|
||||
NR_gNB_DLSCH_t *dlsch_array,
|
||||
int frame,
|
||||
uint8_t slot,
|
||||
NR_DL_FRAME_PARMS *frame_parms,
|
||||
@@ -122,28 +120,18 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
{
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ENCODING, VCD_FUNCTION_IN);
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t TBs[msgTx->num_pdsch_slot];
|
||||
nrLDPC_TB_encoding_parameters_t TBs[n_dlsch];
|
||||
memset(TBs, 0, sizeof(TBs));
|
||||
nrLDPC_slot_encoding_parameters_t slot_parameters = {.frame = frame,
|
||||
.slot = slot,
|
||||
.nb_TBs = msgTx->num_pdsch_slot,
|
||||
.threadPool = &gNB->threadPool,
|
||||
.tinput = tinput,
|
||||
.tprep = tprep,
|
||||
.tparity = tparity,
|
||||
.toutput = toutput,
|
||||
.TBs = TBs};
|
||||
|
||||
int num_segments = 0;
|
||||
|
||||
for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
for (int i = 0; i < n_dlsch; i++) {
|
||||
NR_gNB_DLSCH_t *dlsch = &dlsch_array[i];
|
||||
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
unsigned int crc = 1;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15;
|
||||
uint32_t A = rel15->TBSize[0] << 3;
|
||||
unsigned char *a = harq->pdu;
|
||||
unsigned char *a = dlsch->pdu;
|
||||
if (rel15->rnti != SI_RNTI) {
|
||||
ws_trace_t tmp = {.nr = true,
|
||||
.direction = DIRECTION_DOWNLINK,
|
||||
@@ -182,9 +170,8 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
// printf("CRC %x (A %d)\n",crc,A);
|
||||
// printf("a0 %d a1 %d a2 %d\n", a[A>>3], a[1+(A>>3)], a[2+(A>>3)]);
|
||||
B = A + 24;
|
||||
// harq->b = a;
|
||||
AssertFatal((A / 8) + 4 <= max_bytes, "A %d is too big (A/8+4 = %d > %d)\n", A, (A / 8) + 4, max_bytes);
|
||||
memcpy(harq->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes?
|
||||
memcpy(dlsch->b, a, (A / 8) + 4); // why is this +4 if the CRC is only 3 bytes?
|
||||
} else {
|
||||
// Add 16-bit crc (polynomial A) to payload
|
||||
crc = crc16(a, A) >> 16;
|
||||
@@ -193,21 +180,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
// printf("CRC %x (A %d)\n",crc,A);
|
||||
// printf("a0 %d a1 %d \n", a[A>>3], a[1+(A>>3)]);
|
||||
B = A + 16;
|
||||
// harq->b = a;
|
||||
AssertFatal((A / 8) + 3 <= max_bytes, "A %d is too big (A/8+3 = %d > %d)\n", A, (A / 8) + 3, max_bytes);
|
||||
memcpy(harq->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
|
||||
memcpy(dlsch->b, a, (A / 8) + 3); // using 3 bytes to mimic the case of 24 bit crc
|
||||
}
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id];
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i];
|
||||
|
||||
// The harq_pid is not unique among the active HARQ processes in the instance so we use dlsch_id instead
|
||||
TB_parameters->harq_unique_pid = dlsch_id;
|
||||
// The harq_pid is not unique among the active HARQ processes in the instance so we use i instead
|
||||
TB_parameters->harq_unique_pid = i;
|
||||
TB_parameters->BG = rel15->maintenance_parms_v3.ldpcBaseGraph;
|
||||
TB_parameters->Z = harq->Z;
|
||||
TB_parameters->A = A;
|
||||
start_meas(dlsch_segmentation_stats);
|
||||
TB_parameters->Kb = nr_segmentation(harq->b,
|
||||
harq->c,
|
||||
TB_parameters->Kb = nr_segmentation(dlsch->b,
|
||||
dlsch->c,
|
||||
B,
|
||||
&TB_parameters->C,
|
||||
&TB_parameters->K,
|
||||
@@ -228,20 +213,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
size_t segments_offset = 0;
|
||||
size_t dlsch_offset = 0;
|
||||
|
||||
for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id];
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
|
||||
for (int i = 0; i < n_dlsch; i++) {
|
||||
NR_gNB_DLSCH_t *dlsch = &dlsch_array[i];
|
||||
const nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->pdsch_pdu->pdsch_pdu_rel15;
|
||||
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id];
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i];
|
||||
|
||||
#ifdef DEBUG_DLSCH_CODING
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
LOG_D(PHY, "Encoder: B %d F %d \n", harq->B, TB_parameters->F);
|
||||
LOG_D(PHY, "Encoder: B %d F %d \n", dlsch->B, TB_parameters->F);
|
||||
LOG_D(PHY, "start ldpc encoder segment %d/%d\n", r, TB_parameters->C);
|
||||
LOG_D(PHY, "input %d %d %d %d %d \n", harq->c[r][0], harq->c[r][1], harq->c[r][2], harq->c[r][3], harq->c[r][4]);
|
||||
LOG_D(PHY, "input %d %d %d %d %d \n", dlsch->c[r][0], dlsch->c[r][1], dlsch->c[r][2], dlsch->c[r][3], dlsch->c[r][4]);
|
||||
for (int cnt = 0; cnt < 22 * (TB_parameters->Z) / 8; cnt++) {
|
||||
LOG_D(PHY, "%d ", harq->c[r][cnt]);
|
||||
LOG_D(PHY, "%d ", dlsch->c[r][cnt]);
|
||||
}
|
||||
LOG_D(PHY, "\n");
|
||||
}
|
||||
@@ -259,7 +243,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
rel15->NrOfSymbols,
|
||||
nb_re_dmrs,
|
||||
get_num_dmrs(rel15->dlDmrsSymbPos),
|
||||
harq->unav_res,
|
||||
dlsch->unav_res,
|
||||
rel15->qamModOrder[0],
|
||||
rel15->nrOfLayers);
|
||||
|
||||
@@ -270,7 +254,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
|
||||
segment_parameters->c = harq->c[r];
|
||||
segment_parameters->c = dlsch->c[r];
|
||||
segment_parameters->E = nr_get_E(TB_parameters->G, TB_parameters->C, TB_parameters->Qm, rel15->nrOfLayers, r);
|
||||
|
||||
reset_meas(&segment_parameters->ts_interleave);
|
||||
@@ -287,10 +271,19 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
|
||||
dlsch_offset += ceil_mod(dlsch_size, 8 * 64);
|
||||
}
|
||||
|
||||
nrLDPC_slot_encoding_parameters_t slot_parameters = {.frame = frame,
|
||||
.slot = slot,
|
||||
.nb_TBs = n_dlsch,
|
||||
.threadPool = &gNB->threadPool,
|
||||
.tinput = tinput,
|
||||
.tprep = tprep,
|
||||
.tparity = tparity,
|
||||
.toutput = toutput,
|
||||
.TBs = TBs};
|
||||
gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters);
|
||||
|
||||
for (int dlsch_id = 0; dlsch_id < msgTx->num_pdsch_slot; dlsch_id++) {
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[dlsch_id];
|
||||
for (int i = 0; i < n_dlsch; i++) {
|
||||
nrLDPC_TB_encoding_parameters_t *TB_parameters = &TBs[i];
|
||||
for (int r = 0; r < TB_parameters->C; r++) {
|
||||
nrLDPC_segment_encoding_parameters_t *segment_parameters = &TB_parameters->segments[r];
|
||||
merge_meas(dlsch_interleaving_stats, &segment_parameters->ts_interleave);
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file PHY/NR_TRANSPORT/nr_dlsch_tools.c
|
||||
* \brief Top-level routines for decoding DLSCH transport channel from 38-214, V15.2.0 2018-06
|
||||
* \author Guy De Souza
|
||||
* \date 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: desouza@eurecom.fr
|
||||
* \note
|
||||
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "nr_dlsch.h"
|
||||
#include "../../../nfapi/oai_integration/vendor_ext.h"
|
||||
|
||||
void nr_fill_dlsch_dl_tti_req(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu)
|
||||
{
|
||||
NR_gNB_DLSCH_t *dlsch = &msgTx->dlsch[msgTx->num_pdsch_slot][0];
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
/// DLSCH struct
|
||||
memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu));
|
||||
AssertFatal(msgTx->num_pdsch_slot == pdsch_pdu->pdsch_pdu_rel15.pduIndex,
|
||||
"PDSCH PDU index %d does not match msgTx index %d\n",
|
||||
pdsch_pdu->pdsch_pdu_rel15.pduIndex,
|
||||
msgTx->num_pdsch_slot);
|
||||
msgTx->num_pdsch_slot++;
|
||||
harq->pdu = NULL;
|
||||
}
|
||||
|
||||
void nr_fill_dlsch_tx_req(processingData_L1tx_t *msgTx, int idx, uint8_t *sdu)
|
||||
{
|
||||
AssertFatal(sdu != NULL, "sdu is null\n");
|
||||
|
||||
/* not sure if FAPI could transmit DL_TTI_req and TX_req in different orders.
|
||||
* for the moment, assume they are in the same order (and check!) */
|
||||
NR_gNB_DLSCH_t *dlsch = &msgTx->dlsch[idx][0];
|
||||
NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
|
||||
nfapi_nr_dl_tti_pdsch_pdu *pdsch = &harq->pdsch_pdu;
|
||||
AssertFatal(pdsch->pdsch_pdu_rel15.pduIndex == idx, "PDSCH PDU index %d does not match %d\n", pdsch->pdsch_pdu_rel15.pduIndex, idx);
|
||||
harq->pdu = sdu;
|
||||
}
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "defs.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
+14
-47
@@ -53,30 +53,6 @@ typedef struct {
|
||||
int lut[MAX_PUCCH0_NID][160][14];
|
||||
} NR_gNB_PUCCH0_LUT_t;
|
||||
|
||||
typedef struct {
|
||||
/// Nfapi DLSCH PDU
|
||||
nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu;
|
||||
/// pointer to pdu from MAC interface (this is "a" in 36.212)
|
||||
uint8_t *pdu;
|
||||
/// Pointer to the payload
|
||||
uint8_t *b;
|
||||
/// Pointers to transport block segments
|
||||
uint8_t **c;
|
||||
/// Frame where current HARQ round was sent
|
||||
uint32_t frame;
|
||||
/// Interleaver outputs
|
||||
uint8_t *f;
|
||||
/// LDPC lifting size
|
||||
uint32_t Z;
|
||||
/// REs unavailable for DLSCH (overlapping with PTRS, CSIRS etc.)
|
||||
uint32_t unav_res;
|
||||
} NR_DL_gNB_HARQ_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t active;
|
||||
nfapi_nr_dl_tti_csi_rs_pdu csirs_pdu;
|
||||
} NR_gNB_CSIRS_t;
|
||||
|
||||
typedef struct {
|
||||
int dump_frame;
|
||||
int round_trials[8];
|
||||
@@ -121,19 +97,20 @@ typedef struct {
|
||||
} NR_gNB_PHY_STATS_t;
|
||||
|
||||
typedef struct {
|
||||
/// Pointers to variables related to DLSCH harq process
|
||||
NR_DL_gNB_HARQ_t harq_process;
|
||||
/// Active flag for baseband transmitter processing
|
||||
uint8_t active;
|
||||
/// Number of soft channel bits
|
||||
uint32_t G;
|
||||
/// Nfapi DLSCH PDU
|
||||
const nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu;
|
||||
/// pointer to pdu from MAC interface (this is "a" in 36.212)
|
||||
uint8_t *pdu;
|
||||
/// Pointer to the payload
|
||||
uint8_t *b;
|
||||
/// Pointers to transport block segments
|
||||
uint8_t **c;
|
||||
/// Interleaver outputs
|
||||
uint8_t *f;
|
||||
/// REs unavailable for DLSCH (overlapping with PTRS, CSIRS etc.)
|
||||
uint32_t unav_res;
|
||||
} NR_gNB_DLSCH_t;
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
nfapi_nr_dl_tti_ssb_pdu ssb_pdu;
|
||||
} NR_gNB_SSB_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t NumPRSResources;
|
||||
prs_config_t prs_cfg[NR_MAX_PRS_RESOURCES_PER_SET];
|
||||
@@ -409,6 +386,8 @@ typedef struct PHY_VARS_gNB_s {
|
||||
|
||||
NR_gNB_COMMON common_vars;
|
||||
prach_list_t prach_list;
|
||||
// TODO: can we remove c from NR_gNB_DLSCH_t and put it on the stack?
|
||||
NR_gNB_DLSCH_t *dlsch;
|
||||
NR_gNB_PRS prs_vars;
|
||||
NR_gNB_PUSCH *pusch_vars;
|
||||
NR_gNB_PUCCH_t *pucch;
|
||||
@@ -494,7 +473,6 @@ typedef struct PHY_VARS_gNB_s {
|
||||
time_stats_t rx_pusch_symbol_processing_stats;
|
||||
time_stats_t ul_indication_stats;
|
||||
time_stats_t slot_indication_stats;
|
||||
time_stats_t schedule_response_stats;
|
||||
time_stats_t ulsch_decoding_stats;
|
||||
time_stats_t ts_deinterleave;
|
||||
time_stats_t ts_rate_unmatch;
|
||||
@@ -522,7 +500,6 @@ typedef struct PHY_VARS_gNB_s {
|
||||
int L1_rx_thread_core;
|
||||
pthread_t L1_tx_thread;
|
||||
int L1_tx_thread_core;
|
||||
struct processingData_L1tx *msgDataTx;
|
||||
void *scopeData;
|
||||
} PHY_VARS_gNB;
|
||||
|
||||
@@ -599,16 +576,6 @@ typedef struct processingData_L1tx {
|
||||
int slot_rx;
|
||||
openair0_timestamp timestamp_tx;
|
||||
PHY_VARS_gNB *gNB;
|
||||
nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu[NFAPI_NR_MAX_NB_CORESETS];
|
||||
nfapi_nr_ul_dci_request_pdus_t ul_pdcch_pdu[NFAPI_NR_MAX_NB_CORESETS];
|
||||
NR_gNB_CSIRS_t csirs_pdu[NR_SYMBOLS_PER_SLOT];
|
||||
NR_gNB_DLSCH_t **dlsch;
|
||||
NR_gNB_SSB_t ssb[64];
|
||||
uint16_t num_pdsch_slot;
|
||||
int num_dl_pdcch;
|
||||
int num_ul_pdcch;
|
||||
/* a reference to the sched_response, to release it when not needed anymore */
|
||||
int sched_response_id;
|
||||
} processingData_L1tx_t;
|
||||
|
||||
typedef struct processingData_L1rx {
|
||||
|
||||
@@ -9,30 +9,12 @@ typedef struct pnf_p7_t pnf_p7_t;
|
||||
typedef struct vnf_t vnf_t;
|
||||
typedef struct vnf_p7_t vnf_p7_t;
|
||||
|
||||
void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB,
|
||||
int frame, int slot,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){}
|
||||
|
||||
void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){}
|
||||
|
||||
void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
|
||||
nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
|
||||
uint8_t *sdu){
|
||||
}
|
||||
void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx,
|
||||
int frame, int slot,
|
||||
nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){
|
||||
}
|
||||
int l1_north_init_gNB(void){return 0;}
|
||||
|
||||
int slot_ahead = 6;
|
||||
//uint8_t nfapi_mode=0;
|
||||
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;}
|
||||
|
||||
void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB,
|
||||
int frame, int slot,
|
||||
nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){}
|
||||
void nr_fill_ulsch(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
int slot,
|
||||
@@ -47,8 +29,6 @@ void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_p
|
||||
|
||||
void nr_phy_config_request(NR_PHY_Config_t *gNB){}
|
||||
|
||||
void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){}
|
||||
|
||||
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){}
|
||||
|
||||
bool vnf_nr_send_p5_msg(vnf_t *vnf, uint16_t p5_idx, nfapi_nr_p4_p5_message_header_t *msg, uint32_t msg_len)
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
//Dummy NR defs to avoid linking errors
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/NR_IF_Module.h"
|
||||
#include "openair1/PHY/LTE_TRANSPORT/transport_common.h"
|
||||
|
||||
void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB,
|
||||
int frame, int slot,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *pdcch_pdu){}
|
||||
|
||||
void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu){}
|
||||
|
||||
void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
|
||||
nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
|
||||
uint8_t *sdu){
|
||||
}
|
||||
void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx,
|
||||
int frame, int slot,
|
||||
nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu){
|
||||
}
|
||||
int l1_north_init_gNB(void){return 0;}
|
||||
|
||||
int slot_ahead = 6;
|
||||
//uint8_t nfapi_mode=0;
|
||||
NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {return NULL;}
|
||||
|
||||
void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB,
|
||||
int frame, int slot,
|
||||
nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu){}
|
||||
void nr_fill_ulsch(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
int slot,
|
||||
nfapi_nr_pusch_pdu_t *ulsch_pdu){}
|
||||
void nr_fill_pucch(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
int slot,
|
||||
nfapi_nr_pucch_pdu_t *pucch_pdu){}
|
||||
void nr_schedule_rx_prach(PHY_VARS_gNB *gNB, int SFN, int Slot, nfapi_nr_prach_pdu_t *prach_pdu)
|
||||
{
|
||||
}
|
||||
|
||||
void nr_phy_config_request(NR_PHY_Config_t *gNB){}
|
||||
|
||||
void install_nr_schedule_handlers(NR_IF_Module_t *if_inst){}
|
||||
|
||||
//void nr_dump_frame_parms(NR_DL_FRAME_PARMS *fp){}
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file fapi_nr_l1.c
|
||||
* \brief functions for FAPI L1 interface
|
||||
* \author R. Knopp, WEI-TAI CHEN
|
||||
* \date 2017, 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom, NTUST
|
||||
* \email: knopp@eurecom.fr, kroempa@gmail.com
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include "fapi_nr_l1.h"
|
||||
#include "common/ran_context.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_dci.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h"
|
||||
#include "nfapi/oai_integration/nfapi_vnf.h"
|
||||
|
||||
void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot,
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu)
|
||||
{
|
||||
|
||||
AssertFatal(dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag== 1, "bchPayloadFlat %d != 1\n",
|
||||
dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag);
|
||||
|
||||
uint8_t i_ssb = dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex;
|
||||
|
||||
LOG_D(NR_PHY,"%d.%d : ssb index %d pbch_pdu: %x\n",frame,slot,i_ssb,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload);
|
||||
if (msgTx->ssb[i_ssb].active)
|
||||
AssertFatal(1==0,"SSB PDU with index %d already active\n",i_ssb);
|
||||
else {
|
||||
msgTx->ssb[i_ssb].active = true;
|
||||
memcpy((void*)&msgTx->ssb[i_ssb].ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_pdu));
|
||||
}
|
||||
}
|
||||
|
||||
void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx, int frame, int slot, nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu)
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
for (int id = 0; id < NR_NUMBER_OF_SYMBOLS_PER_SLOT; id++) {
|
||||
NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[id];
|
||||
if (csirs->active == 0) {
|
||||
LOG_D(NR_PHY,"Frame %d Slot %d CSI_RS with ID %d is now active\n",frame,slot,id);
|
||||
csirs->active = 1;
|
||||
memcpy((void*)&csirs->csirs_pdu, (void*)csirs_pdu, sizeof(nfapi_nr_dl_tti_csi_rs_pdu));
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == 0)
|
||||
LOG_E(MAC,"CSI-RS list is full\n");
|
||||
}
|
||||
|
||||
void nr_schedule_dl_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_dl_tti_request_t *DL_req)
|
||||
{
|
||||
DevAssert(gNB != NULL);
|
||||
DevAssert(DL_req != NULL);
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
|
||||
int frame = DL_req->SFN;
|
||||
int slot = DL_req->Slot;
|
||||
|
||||
int slot_type = nr_slot_select(cfg, frame, slot);
|
||||
DevAssert(slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT);
|
||||
|
||||
processingData_L1tx_t *msgTx = gNB->msgDataTx;
|
||||
msgTx->slot = slot;
|
||||
msgTx->frame = frame;
|
||||
|
||||
uint8_t number_dl_pdu = DL_req->dl_tti_request_body.nPDUs;
|
||||
|
||||
for (int i = 0; i < number_dl_pdu; i++) {
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i];
|
||||
LOG_D(NR_PHY, "NFAPI: dl_pdu %d : type %d\n", i, dl_tti_pdu->PDUType);
|
||||
switch (dl_tti_pdu->PDUType) {
|
||||
case NFAPI_NR_DL_TTI_SSB_PDU_TYPE:
|
||||
handle_nr_nfapi_ssb_pdu(msgTx, frame, slot, dl_tti_pdu);
|
||||
break;
|
||||
|
||||
case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE:
|
||||
LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot);
|
||||
msgTx->pdcch_pdu[msgTx->num_dl_pdcch] = dl_tti_pdu->pdcch_pdu;
|
||||
msgTx->num_dl_pdcch++;
|
||||
break;
|
||||
|
||||
case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE:
|
||||
LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot);
|
||||
handle_nfapi_nr_csirs_pdu(msgTx, frame, slot, &dl_tti_pdu->csi_rs_pdu);
|
||||
break;
|
||||
|
||||
case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE:
|
||||
LOG_D(NR_PHY, "frame %d, slot %d, Got NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE for %d.%d\n", frame, slot, DL_req->SFN, DL_req->Slot);
|
||||
nr_fill_dlsch_dl_tti_req(msgTx, &dl_tti_pdu->pdsch_pdu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nr_schedule_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req)
|
||||
{
|
||||
DevAssert(gNB != NULL);
|
||||
DevAssert(UL_tti_req != NULL);
|
||||
|
||||
int frame = UL_tti_req->SFN;
|
||||
int slot = UL_tti_req->Slot;
|
||||
|
||||
for (int i = 0; i < UL_tti_req->n_pdus; i++) {
|
||||
int type = UL_tti_req->pdus_list[i].pdu_type;
|
||||
LOG_D(NR_PHY,
|
||||
"frame %d, slot %d got %s for %d.%d\n",
|
||||
frame,
|
||||
slot,
|
||||
txt_nfapi_nr_ul_config_pdu_type[type],
|
||||
UL_tti_req->SFN,
|
||||
UL_tti_req->Slot);
|
||||
switch (type) {
|
||||
case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:
|
||||
nr_fill_ulsch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE:
|
||||
nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: {
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu;
|
||||
prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
if (!prach)
|
||||
LOG_W(NR_PHY_RACH, "Error in scheduling rach\n");
|
||||
} break;
|
||||
case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE:
|
||||
nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nr_schedule_tx_req(PHY_VARS_gNB *gNB, nfapi_nr_tx_data_request_t *TX_req)
|
||||
{
|
||||
DevAssert(gNB != NULL);
|
||||
DevAssert(TX_req != NULL);
|
||||
processingData_L1tx_t *msgTx = gNB->msgDataTx;
|
||||
|
||||
for (int idx = 0; idx < TX_req->Number_of_PDUs; ++idx) {
|
||||
uint8_t *sdu = (uint8_t *)TX_req->pdu_list[idx].TLVs[0].value.direct;
|
||||
nr_fill_dlsch_tx_req(msgTx, idx, sdu);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_schedule_ul_dci_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_dci_request_t *UL_dci_req)
|
||||
{
|
||||
DevAssert(gNB != NULL);
|
||||
DevAssert(UL_dci_req != NULL);
|
||||
processingData_L1tx_t *msgTx = gNB->msgDataTx;
|
||||
|
||||
msgTx->num_ul_pdcch = UL_dci_req->numPdus;
|
||||
for (int i = 0; i < UL_dci_req->numPdus; i++)
|
||||
msgTx->ul_pdcch_pdu[i] = UL_dci_req->ul_dci_pdu_list[i];
|
||||
}
|
||||
|
||||
void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO)
|
||||
{
|
||||
// copy data from L2 interface into L1 structures
|
||||
module_id_t Mod_id = Sched_INFO->module_id;
|
||||
frame_t frame = Sched_INFO->frame;
|
||||
slot_t slot = Sched_INFO->slot;
|
||||
|
||||
AssertFatal(RC.gNB != NULL, "RC.gNB is null\n");
|
||||
AssertFatal(RC.gNB[Mod_id] != NULL, "RC.gNB[%d] is null\n", Mod_id);
|
||||
|
||||
PHY_VARS_gNB *gNB = RC.gNB[Mod_id];
|
||||
start_meas(&gNB->schedule_response_stats);
|
||||
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
|
||||
int slot_type = nr_slot_select(cfg, frame, slot);
|
||||
|
||||
clear_slot_beamid(gNB, slot); // reset beam_id information for the slot to be processed
|
||||
DevAssert(NFAPI_MODE == NFAPI_MONOLITHIC);
|
||||
bool is_dl = slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT;
|
||||
|
||||
processingData_L1tx_t *msgTx = gNB->msgDataTx;
|
||||
/* store the sched_response_id for the TX thread to release it when done */
|
||||
msgTx->sched_response_id = Sched_INFO->sched_response_id;
|
||||
|
||||
DevAssert(Sched_INFO->DL_req.SFN == frame);
|
||||
DevAssert(Sched_INFO->DL_req.Slot == slot);
|
||||
|
||||
if (is_dl) {
|
||||
nr_schedule_dl_tti_req(gNB, &Sched_INFO->DL_req);
|
||||
}
|
||||
|
||||
nr_schedule_ul_tti_req(gNB, &Sched_INFO->UL_tti_req);
|
||||
|
||||
if (is_dl) {
|
||||
nr_schedule_tx_req(gNB, &Sched_INFO->TX_req);
|
||||
|
||||
nr_schedule_ul_dci_req(gNB, &Sched_INFO->UL_dci_req);
|
||||
/* Both the current thread and the TX thread will access the sched_info
|
||||
* at the same time, so increase its reference counter, so that it is
|
||||
* released only when both threads are done with it.
|
||||
*/
|
||||
inc_ref_sched_response(Sched_INFO->sched_response_id);
|
||||
}
|
||||
|
||||
/* this thread is done with the sched_info, decrease the reference counter */
|
||||
if ((slot_type == NR_DOWNLINK_SLOT || slot_type == NR_MIXED_SLOT) && NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
LOG_D(NR_PHY, "Calling dref_sched_response for id %d in %d.%d (sched_response)\n", Sched_INFO->sched_response_id, frame, slot);
|
||||
deref_sched_response(Sched_INFO->sched_response_id);
|
||||
}
|
||||
stop_meas(&gNB->schedule_response_stats);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/*! \file fapi_nr_l1.h
|
||||
* \brief function prototypes for FAPI L1 interface
|
||||
* \author R. Knopp, WEI-TAI CHEN
|
||||
* \date 2017, 2018
|
||||
* \version 0.1
|
||||
* \company Eurecom, NTUST
|
||||
* \email: knopp@eurecom.fr, kroempa@gmail.com
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "nfapi_nr_interface_scf.h"
|
||||
|
||||
// added
|
||||
void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,
|
||||
int frame,int slot,
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu);
|
||||
|
||||
void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO);
|
||||
|
||||
void handle_nfapi_nr_csirs_pdu(processingData_L1tx_t *msgTx,
|
||||
int frame, int slot,
|
||||
nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu);
|
||||
|
||||
void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB,
|
||||
int frame, int subframe,
|
||||
nfapi_nr_dl_tti_pdcch_pdu *dcl_dl_pdu);
|
||||
|
||||
void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
|
||||
nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
|
||||
uint8_t *sdu);
|
||||
|
||||
//added
|
||||
|
||||
void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB,
|
||||
int frame, int slot,
|
||||
nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu);
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/NR_TRANSPORT/nr_transport_proto.h"
|
||||
#include "nfapi_nr_interface_scf.h"
|
||||
#include "fapi_nr_l1.h"
|
||||
#include "nfapi_pnf.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "PHY/NR_TRANSPORT/nr_dci.h"
|
||||
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
|
||||
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
|
||||
#include "fapi_nr_l1.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
@@ -55,9 +54,19 @@ static void nr_fill_indication(PHY_VARS_gNB *gNB,
|
||||
nfapi_nr_crc_t *crc,
|
||||
nfapi_nr_rx_data_pdu_t *pdu);
|
||||
|
||||
static void nr_fill_indication(PHY_VARS_gNB *gNB,
|
||||
int frame,
|
||||
int slot_rx,
|
||||
int ULSCH_id,
|
||||
uint8_t harq_pid,
|
||||
uint8_t crc_flag,
|
||||
int dtx_flag,
|
||||
nfapi_nr_crc_t *crc,
|
||||
nfapi_nr_rx_data_pdu_t *pdu);
|
||||
|
||||
int beam_index_allocation(bool das,
|
||||
int fapi_beam_index,
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_bf,
|
||||
const nfapi_nr_analog_beamforming_ve_t *analog_bf,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
@@ -93,10 +102,10 @@ int beam_index_allocation(bool das,
|
||||
return idx;
|
||||
}
|
||||
|
||||
void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_dl_tti_ssb_pdu ssb_pdu)
|
||||
void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu.ssb_pdu_rel15;
|
||||
const nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu->ssb_pdu_rel15;
|
||||
uint8_t ssb_index = pdu->SsbBlockIndex;
|
||||
LOG_D(PHY,"common_signal_procedures: frame %d, slot %d ssb index %d\n", frame, slot, ssb_index);
|
||||
|
||||
@@ -144,7 +153,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n
|
||||
fp->ssb_start_subcarrier);
|
||||
|
||||
LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n", frame, slot, ssb_start_symbol);
|
||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming;
|
||||
const nfapi_nr_tx_precoding_and_beamforming_t *pb = &pdu->precoding_and_beamforming;
|
||||
c16_t ***txdataF = gNB->common_vars.txdataF;
|
||||
int txdataF_offset = slot * fp->samples_per_slot_wCP;
|
||||
// beam number in a scenario with multiple concurrent beams
|
||||
@@ -182,7 +191,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_n
|
||||
#endif
|
||||
|
||||
nr_generate_pbch(gNB,
|
||||
&ssb_pdu,
|
||||
ssb_pdu,
|
||||
&txdataF[beam_nb][0][txdataF_offset],
|
||||
ssb_start_symbol,
|
||||
n_hf,
|
||||
@@ -202,12 +211,54 @@ void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot)
|
||||
}
|
||||
}
|
||||
|
||||
void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
static void nr_generate_csi_rs_gNB(PHY_VARS_gNB *gNB,
|
||||
int slot,
|
||||
const nfapi_nr_config_request_scf_t *cfg,
|
||||
const nfapi_nr_dl_tti_csi_rs_pdu *csi_rs_pdu)
|
||||
{
|
||||
const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csi_rs_pdu->csi_rs_pdu_rel15;
|
||||
if (csi_params->csi_type == 2) // ZP-CSI
|
||||
return;
|
||||
|
||||
csi_mapping_parms_t mapping_parms =
|
||||
get_csi_mapping_parms(csi_params->row, csi_params->freq_domain, csi_params->symb_l0, csi_params->symb_l1);
|
||||
const nfapi_nr_tx_precoding_and_beamforming_t *pb = &csi_params->precodingAndBeamforming;
|
||||
int csi_bitmap = 0;
|
||||
int lprime_num = mapping_parms.lprime + 1;
|
||||
for (int j = 0; j < mapping_parms.size; j++)
|
||||
csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j];
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
gNB->frame_parms.symbols_per_slot,
|
||||
csi_bitmap);
|
||||
|
||||
nr_generate_csi_rs(&gNB->frame_parms,
|
||||
&mapping_parms,
|
||||
gNB->TX_AMP,
|
||||
slot,
|
||||
csi_params->freq_density,
|
||||
csi_params->start_rb,
|
||||
csi_params->nr_of_rbs,
|
||||
csi_params->symb_l0,
|
||||
csi_params->symb_l1,
|
||||
csi_params->row,
|
||||
csi_params->scramb_id,
|
||||
csi_params->power_control_offset_ss,
|
||||
csi_params->cdm_type,
|
||||
gNB->common_vars.txdataF[beam_nb]);
|
||||
}
|
||||
|
||||
void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
|
||||
const nfapi_nr_dl_tti_request_t *DL_req,
|
||||
const nfapi_nr_tx_data_request_t *TX_req,
|
||||
const nfapi_nr_ul_dci_request_t *UL_dci_req,
|
||||
int frame,
|
||||
int slot,
|
||||
int do_meas)
|
||||
{
|
||||
PHY_VARS_gNB *gNB = msgTx->gNB;
|
||||
const NR_DL_FRAME_PARMS *fp = &gNB->frame_parms;
|
||||
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
|
||||
const int txdataF_offset = slot * fp->samples_per_slot_wCP;
|
||||
@@ -239,82 +290,41 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
|
||||
}
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1);
|
||||
for (int i = 0; i < fp->Lmax; i++) {
|
||||
if (msgTx->ssb[i].active) {
|
||||
nr_common_signal_procedures(gNB, frame, slot, msgTx->ssb[i].ssb_pdu);
|
||||
msgTx->ssb[i].active = false;
|
||||
for (int i = 0; i < UL_dci_req->numPdus; ++i)
|
||||
nr_generate_dci(gNB, &UL_dci_req->ul_dci_pdu_list[i].pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot);
|
||||
|
||||
int num_pdsch = 0;
|
||||
for (int i = 0; i < DL_req->dl_tti_request_body.nPDUs; ++i) {
|
||||
const nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i];
|
||||
switch (dl_tti_pdu->PDUType) {
|
||||
case NFAPI_NR_DL_TTI_SSB_PDU_TYPE:
|
||||
nr_common_signal_procedures(gNB, frame, slot, &dl_tti_pdu->ssb_pdu);
|
||||
break;
|
||||
case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE:
|
||||
nr_generate_dci(gNB, &dl_tti_pdu->pdcch_pdu.pdcch_pdu_rel15, txdataF_offset, &gNB->frame_parms, slot);
|
||||
break;
|
||||
case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE:
|
||||
nr_generate_csi_rs_gNB(gNB, slot, cfg, &dl_tti_pdu->csi_rs_pdu);
|
||||
break;
|
||||
case NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE: {
|
||||
int tx_data_idx = dl_tti_pdu->pdsch_pdu.pdsch_pdu_rel15.pduIndex;
|
||||
DevAssert(tx_data_idx < TX_req->Number_of_PDUs);
|
||||
// reuse dlsch variables, as there are multiple very large memory
|
||||
// buffers
|
||||
gNB->dlsch[num_pdsch].pdsch_pdu = &dl_tti_pdu->pdsch_pdu;
|
||||
gNB->dlsch[num_pdsch].pdu = (uint8_t *)TX_req->pdu_list[tx_data_idx].TLVs[0].value.direct;
|
||||
DevAssert(num_pdsch < gNB->max_nb_pdsch);
|
||||
num_pdsch++;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0);
|
||||
|
||||
int num_pdcch_pdus = msgTx->num_ul_pdcch + msgTx->num_dl_pdcch;
|
||||
|
||||
if (num_pdcch_pdus > 0) {
|
||||
LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL PDCCH PDUs %d/%d)\n",
|
||||
gNB->Mod_id, frame, slot, msgTx->num_ul_pdcch, msgTx->num_dl_pdcch);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1);
|
||||
|
||||
nr_generate_dci_top(msgTx, slot, txdataF_offset);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0);
|
||||
}
|
||||
msgTx->num_dl_pdcch = 0;
|
||||
msgTx->num_ul_pdcch = 0;
|
||||
|
||||
if (msgTx->num_pdsch_slot > 0) {
|
||||
if (num_pdsch > 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
|
||||
LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", msgTx->num_pdsch_slot,frame,slot);
|
||||
nr_generate_pdsch(msgTx, frame, slot);
|
||||
LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", num_pdsch, frame, slot);
|
||||
nr_generate_pdsch(gNB, num_pdsch, gNB->dlsch, frame, slot);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
|
||||
}
|
||||
msgTx->num_pdsch_slot = 0;
|
||||
|
||||
for (int i = 0; i < NR_SYMBOLS_PER_SLOT; i++){
|
||||
NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[i];
|
||||
if (csirs->active == 1) {
|
||||
LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot);
|
||||
nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params = &csirs->csirs_pdu.csi_rs_pdu_rel15;
|
||||
if (csi_params->csi_type == 2) { // ZP-CSI
|
||||
csirs->active = 0;
|
||||
return;
|
||||
}
|
||||
csi_mapping_parms_t mapping_parms = get_csi_mapping_parms(csi_params->row,
|
||||
csi_params->freq_domain,
|
||||
csi_params->symb_l0,
|
||||
csi_params->symb_l1);
|
||||
nfapi_nr_tx_precoding_and_beamforming_t *pb = &csi_params->precodingAndBeamforming;
|
||||
int csi_bitmap = 0;
|
||||
int lprime_num = mapping_parms.lprime + 1;
|
||||
for (int j = 0; j < mapping_parms.size; j++)
|
||||
csi_bitmap |= ((1 << lprime_num) - 1) << mapping_parms.loverline[j];
|
||||
int beam_nb = beam_index_allocation(gNB->enable_analog_das,
|
||||
pb->prgs_list[0].dig_bf_interface_list[0].beam_idx,
|
||||
&cfg->analog_beamforming_ve,
|
||||
&gNB->common_vars,
|
||||
slot,
|
||||
fp->symbols_per_slot,
|
||||
csi_bitmap);
|
||||
|
||||
nr_generate_csi_rs(&gNB->frame_parms,
|
||||
&mapping_parms,
|
||||
gNB->TX_AMP,
|
||||
slot,
|
||||
csi_params->freq_density,
|
||||
csi_params->start_rb,
|
||||
csi_params->nr_of_rbs,
|
||||
csi_params->symb_l0,
|
||||
csi_params->symb_l1,
|
||||
csi_params->row,
|
||||
csi_params->scramb_id,
|
||||
csi_params->power_control_offset_ss,
|
||||
csi_params->cdm_type,
|
||||
gNB->common_vars.txdataF[beam_nb]);
|
||||
csirs->active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//apply the OFDM symbol rotation here
|
||||
start_meas(&gNB->phase_comp_stats);
|
||||
@@ -1299,3 +1309,40 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0);
|
||||
return pusch_DTX;
|
||||
}
|
||||
|
||||
void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req)
|
||||
{
|
||||
DevAssert(gNB != NULL);
|
||||
DevAssert(UL_tti_req != NULL);
|
||||
|
||||
int frame = UL_tti_req->SFN;
|
||||
int slot = UL_tti_req->Slot;
|
||||
|
||||
for (int i = 0; i < UL_tti_req->n_pdus; i++) {
|
||||
int type = UL_tti_req->pdus_list[i].pdu_type;
|
||||
LOG_D(NR_PHY,
|
||||
"frame %d, slot %d got %s for %d.%d\n",
|
||||
frame,
|
||||
slot,
|
||||
txt_nfapi_nr_ul_config_pdu_type[type],
|
||||
UL_tti_req->SFN,
|
||||
UL_tti_req->Slot);
|
||||
switch (type) {
|
||||
case NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE:
|
||||
nr_fill_ulsch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pusch_pdu);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE:
|
||||
nr_fill_pucch(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].pucch_pdu);
|
||||
break;
|
||||
case NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE: {
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu;
|
||||
prach_item_t *prach = nr_schedule_rx_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
if (!prach)
|
||||
LOG_W(NR_PHY_RACH, "Error in scheduling rach\n");
|
||||
} break;
|
||||
case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE:
|
||||
nr_fill_srs(gNB, UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,17 @@
|
||||
#include "phy_frame_config_nr.h"
|
||||
|
||||
void nr_set_ssb_first_subcarrier(nfapi_nr_config_request_scf_t *cfg, NR_DL_FRAME_PARMS *fp);
|
||||
void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx, int frame_tx, int slot_tx, int do_meas);
|
||||
void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
|
||||
const nfapi_nr_dl_tti_request_t *DL_req,
|
||||
const nfapi_nr_tx_data_request_t *TX_req,
|
||||
const nfapi_nr_ul_dci_request_t *UL_dci_req,
|
||||
int frame,
|
||||
int slot,
|
||||
int do_meas);
|
||||
void nr_save_ul_tti_req(PHY_VARS_gNB *gNB, nfapi_nr_ul_tti_request_t *UL_tti_req);
|
||||
int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, NR_UL_IND_t *UL_INFO);
|
||||
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB, int frame, int slot, nfapi_nr_rach_indication_t *rach_ind);
|
||||
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_dl_tti_ssb_pdu ssb_pdu);
|
||||
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot, const nfapi_nr_dl_tti_ssb_pdu *ssb_pdu);
|
||||
void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
|
||||
void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa);
|
||||
void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
|
||||
@@ -49,7 +56,7 @@ void nr_phy_free_RU(RU_t *ru);
|
||||
void clear_slot_beamid(PHY_VARS_gNB *gNB, int slot);
|
||||
int beam_index_allocation(bool das,
|
||||
int fapi_beam_index,
|
||||
nfapi_nr_analog_beamforming_ve_t *analog_bf,
|
||||
const nfapi_nr_analog_beamforming_ve_t *analog_bf,
|
||||
NR_gNB_COMMON *common_vars,
|
||||
int slot,
|
||||
int symbols_per_slot,
|
||||
|
||||
@@ -439,10 +439,7 @@ int main(int argc, char **argv)
|
||||
nr_init_dl_harq_processes(UE->dl_harq_processes, 8, nb_rb);
|
||||
|
||||
unsigned char harq_pid = 0; //dlsch->harq_ids[subframe];
|
||||
processingData_L1tx_t msgDataTx;
|
||||
init_DLSCH_struct(gNB, &msgDataTx);
|
||||
NR_gNB_DLSCH_t *dlsch = &msgDataTx.dlsch[0][0];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
|
||||
NR_gNB_DLSCH_t *dlsch = &gNB->dlsch[0];
|
||||
//time_stats_t *rm_stats, *te_stats, *i_stats;
|
||||
unsigned int TBS = 8424;
|
||||
uint8_t nb_re_dmrs = 6; // No data in dmrs symbol
|
||||
@@ -459,19 +456,24 @@ int main(int argc, char **argv)
|
||||
TBS = nr_compute_tbs(mod_order,rate, nb_rb, nb_symb_sch, nb_re_dmrs*length_dmrs, 0, 0, Nl);
|
||||
printf("available bits %u TBS %u mod_order %d\n", available_bits, TBS, mod_order);
|
||||
//dlsch->harq_ids[subframe]= 0;
|
||||
rel15->rbSize = nb_rb;
|
||||
rel15->NrOfSymbols = nb_symb_sch;
|
||||
rel15->qamModOrder[0] = mod_order;
|
||||
rel15->nrOfLayers = Nl;
|
||||
rel15->TBSize[0] = TBS>>3;
|
||||
rel15->targetCodeRate[0] = rate;
|
||||
rel15->NrOfCodewords = 1;
|
||||
rel15->dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
|
||||
rel15->dlDmrsSymbPos = 4;
|
||||
rel15->mcsIndex[0] = Imcs;
|
||||
rel15->numDmrsCdmGrpsNoData = 1;
|
||||
rel15->maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm;
|
||||
rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate);
|
||||
nfapi_nr_dl_tti_pdsch_pdu pdsch_pdu = {
|
||||
.pdsch_pdu_rel15 = {
|
||||
.rbSize = nb_rb,
|
||||
.NrOfSymbols = nb_symb_sch,
|
||||
.qamModOrder[0] = mod_order,
|
||||
.nrOfLayers = Nl,
|
||||
.TBSize[0] = TBS >> 3,
|
||||
.targetCodeRate[0] = rate,
|
||||
.NrOfCodewords = 1,
|
||||
.dmrsConfigType = NFAPI_NR_DMRS_TYPE1,
|
||||
.dlDmrsSymbPos = 4,
|
||||
.mcsIndex[0] = Imcs,
|
||||
.numDmrsCdmGrpsNoData = 1,
|
||||
.maintenance_parms_v3.tbSizeLbrmBytes = Tbslbrm,
|
||||
.maintenance_parms_v3.ldpcBaseGraph = get_BG(TBS, rate),
|
||||
},
|
||||
};
|
||||
dlsch->pdsch_pdu = &pdsch_pdu;
|
||||
double modulated_input[16 * 68 * 384]; // [hna] 16 segments, 68*Zc
|
||||
short channel_output_fixed[16 * 68 * 384];
|
||||
//unsigned char *estimated_output;
|
||||
@@ -498,7 +500,7 @@ int main(int argc, char **argv)
|
||||
printf("harq process ue mcs = %d Qm = %d, symb %d\n", dlsch0_ue->dlsch_config.mcs, dlsch0_ue->dlsch_config.qamModOrder, nb_symb_sch);
|
||||
|
||||
uint8_t test_input[TBS / 8 + 4]; // + 3 for CRC + 1 additional byte, see nr_dlsch_encoding()
|
||||
dlsch->harq_process.pdu = test_input;
|
||||
dlsch->pdu = test_input;
|
||||
//unsigned char test_input[TBS / 8] __attribute__ ((aligned(16)));
|
||||
for (i = 0; i < TBS / 8; i++)
|
||||
test_input[i] = (unsigned char) rand();
|
||||
@@ -512,11 +514,10 @@ int main(int argc, char **argv)
|
||||
|
||||
//printf("crc32: [0]->0x%08x\n",crc24c(test_input, 32));
|
||||
// generate signal
|
||||
unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64)));
|
||||
unsigned char output[nb_rb * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * NR_MAX_NB_LAYERS] __attribute__((aligned(64)));
|
||||
bzero(output, sizeof(output));
|
||||
if (input_fd == NULL) {
|
||||
msgDataTx.num_pdsch_slot = 1;
|
||||
nr_dlsch_encoding(gNB, &msgDataTx, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
nr_dlsch_encoding(gNB, 1, dlsch, frame, slot, frame_parms, output, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
for (SNR = snr0; SNR < snr1 && !stop; SNR += snr_step) {
|
||||
@@ -622,8 +623,6 @@ int main(int argc, char **argv)
|
||||
|
||||
free_channel_desc_scm(gNB2UE);
|
||||
|
||||
reset_DLSCH_struct(gNB, &msgDataTx);
|
||||
|
||||
int nb_slots_to_set = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
|
||||
for (int i = 0; i < nb_slots_to_set; ++i)
|
||||
free(gNB->gNB_config.tdd_table.max_tdd_periodicity_list[i].max_num_of_symbol_per_slot_list);
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/phy_vars_nr_ue.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "SCHED_NR_UE/defs.h"
|
||||
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
|
||||
@@ -286,7 +285,6 @@ nrUE_params_t *get_nrUE_params(void) {
|
||||
return &nrUE_params;
|
||||
}
|
||||
|
||||
|
||||
void validate_input_pmi(nfapi_nr_config_request_scf_t *gNB_config,
|
||||
nr_pdsch_AntennaPorts_t pdsch_AntennaPorts,
|
||||
int nrOfLayers,
|
||||
@@ -974,13 +972,6 @@ int main(int argc, char **argv)
|
||||
int ret = 1;
|
||||
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
|
||||
initNotifiedFIFO(&gNB->L1_tx_out);
|
||||
// we create 2 threads for L1 tx processing
|
||||
processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t));
|
||||
init_DLSCH_struct(gNB, msgDataTx);
|
||||
msgDataTx->slot = slot;
|
||||
msgDataTx->frame = frame;
|
||||
memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
|
||||
gNB->msgDataTx = msgDataTx;
|
||||
|
||||
// Buffers to store internal memory of slot process
|
||||
int rx_size = (((14 * UE->frame_parms.N_RB_DL * 12 * sizeof(int32_t)) + 15) >> 4) << 4;
|
||||
@@ -1059,8 +1050,13 @@ int main(int argc, char **argv)
|
||||
n_false_positive = 0;
|
||||
if (n_trials== 1) num_rounds = 1;
|
||||
|
||||
NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
|
||||
NR_gNB_DLSCH_t *gNB_dlsch = &gNB->dlsch[0];
|
||||
memset(Sched_INFO, 0, sizeof(*Sched_INFO));
|
||||
Sched_INFO->sched_response_id = -1;
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body;
|
||||
// scheduler will place PDSCH second (after PDCCH), verification below
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
for (trial = 0; trial < n_trials && !stop; trial++) {
|
||||
|
||||
@@ -1082,11 +1078,9 @@ int main(int argc, char **argv)
|
||||
UE_harq_process->DLround = round;
|
||||
UE_harq_process->first_rx = 1;
|
||||
|
||||
memset(Sched_INFO, 0, sizeof(*Sched_INFO));
|
||||
Sched_INFO->sched_response_id = -1;
|
||||
|
||||
while (round < num_rounds && !UE_harq_process->decodeResult && !stop) {
|
||||
clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req);
|
||||
reset_sched_response(Sched_INFO, frame, slot, 0, 0);
|
||||
clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot);
|
||||
UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1);
|
||||
UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round;
|
||||
|
||||
@@ -1094,18 +1088,13 @@ int main(int argc, char **argv)
|
||||
NR_SCHED_LOCK(&gNB_mac->sched_lock);
|
||||
nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req);
|
||||
NR_SCHED_UNLOCK(&gNB_mac->sched_lock);
|
||||
Sched_INFO->module_id = 0;
|
||||
Sched_INFO->CC_id = 0;
|
||||
Sched_INFO->frame = frame;
|
||||
Sched_INFO->slot = slot;
|
||||
Sched_INFO->UL_dci_req.numPdus = 0;
|
||||
nr_schedule_response(Sched_INFO);
|
||||
|
||||
/* check that second message is indeed PDSCH */
|
||||
DevAssert(dl_tti_pdsch_pdu->PDUType == NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE);
|
||||
|
||||
/* PTRS values for DLSIM calculations */
|
||||
nfapi_nr_dl_tti_request_body_t *dl_req = &Sched_INFO->DL_req.dl_tti_request_body;
|
||||
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
|
||||
pdu_bit_map = pdsch_pdu_rel15->pduBitmap;
|
||||
// This is already in DL procedures??
|
||||
if(pdu_bit_map & 0x1) {
|
||||
set_ptrs_symb_idx(&dlPtrsSymPos,
|
||||
pdsch_pdu_rel15->NrOfSymbols,
|
||||
@@ -1113,16 +1102,12 @@ int main(int argc, char **argv)
|
||||
1<<pdsch_pdu_rel15->PTRSTimeDensity,
|
||||
pdsch_pdu_rel15->dlDmrsSymbPos);
|
||||
ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols);
|
||||
ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1) / rel15->PTRSFreqDensity);
|
||||
ptrsRePerSymb = ((pdsch_pdu_rel15->rbSize + pdsch_pdu_rel15->PTRSFreqDensity - 1) / pdsch_pdu_rel15->PTRSFreqDensity);
|
||||
LOG_D(PHY,"[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot, ptrsRePerSymb, ptrsSymbPerSlot * ptrsRePerSymb);
|
||||
}
|
||||
|
||||
msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.bchPayload=0x001234;
|
||||
msgDataTx->ssb[0].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
|
||||
msgDataTx->gNB = gNB;
|
||||
|
||||
start_meas(&gNB->phy_proc_tx);
|
||||
phy_procedures_gNB_TX(msgDataTx,frame,slot,1);
|
||||
phy_procedures_gNB_TX(gNB, &Sched_INFO->DL_req, &Sched_INFO->TX_req, &Sched_INFO->UL_dci_req, frame, slot, 1);
|
||||
stop_meas(&gNB->phy_proc_tx);
|
||||
|
||||
int txdataF_offset = slot * frame_parms->samples_per_slot_wCP;
|
||||
@@ -1197,9 +1182,9 @@ int main(int argc, char **argv)
|
||||
|
||||
double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size);
|
||||
//Compute AWGN variance
|
||||
sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
|
||||
sigma2_dB = 10 * log10((double)txlev_sum * ((double)UE->frame_parms.ofdm_symbol_size/(12*pdsch_pdu_rel15->rbSize))) - SNR;
|
||||
sigma2 = pow(10, sigma2_dB/10);
|
||||
if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize));
|
||||
if (n_trials==1) printf("sigma2 %f (%f dB), txlev_sum %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev_sum),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*pdsch_pdu_rel15->rbSize));
|
||||
|
||||
for (aa = 0; aa < n_rx; aa++) {
|
||||
bzero(r_re[aa], slot_length * sizeof(double));
|
||||
@@ -1241,22 +1226,22 @@ int main(int argc, char **argv)
|
||||
|
||||
int16_t *UE_llr = (int16_t*)UE->phy_sim_pdsch_llr;
|
||||
|
||||
TBS = dlsch0->dlsch_config.TBS;//rel15->TBSize[0];
|
||||
TBS = dlsch0->dlsch_config.TBS;
|
||||
uint16_t length_dmrs = get_num_dmrs(dlsch0->dlsch_config.dlDmrsSymbPos);
|
||||
uint16_t nb_rb = dlsch0->dlsch_config.number_rbs;
|
||||
uint8_t nb_re_dmrs = dlsch0->dlsch_config.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6*dlsch0->dlsch_config.n_dmrs_cdm_groups : 4*dlsch0->dlsch_config.n_dmrs_cdm_groups;
|
||||
uint8_t mod_order = dlsch0->dlsch_config.qamModOrder;
|
||||
uint8_t nb_symb_sch = dlsch0->dlsch_config.number_symbols;
|
||||
uint32_t unav_res = ptrsSymbPerSlot * ptrsRePerSymb;
|
||||
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, rel15->nrOfLayers);
|
||||
available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, unav_res, mod_order, pdsch_pdu_rel15->nrOfLayers);
|
||||
if (pdu_bit_map & 0x1) {
|
||||
if (trial == 0 && round == 0) {
|
||||
printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * rel15->nrOfLayers * mod_order));
|
||||
printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n", available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * pdsch_pdu_rel15->nrOfLayers * mod_order));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < available_bits; i++) {
|
||||
const uint8_t current_bit = (gNB_dlsch->harq_process.f[i / 8] & (1 << (i & 7))) >> (i & 7);
|
||||
const uint8_t current_bit = (gNB_dlsch->f[i / 8] & (1 << (i & 7))) >> (i & 7);
|
||||
if (((current_bit == 0) && (UE_llr[i] <= 0)) || ((current_bit == 1) && (UE_llr[i] >= 0))) {
|
||||
if (errors_scrambling[round] == 0) {
|
||||
LOG_D(PHY,"First bit in error in unscrambling = %d\n",i);
|
||||
@@ -1270,13 +1255,13 @@ int main(int argc, char **argv)
|
||||
} // round
|
||||
|
||||
if (test_input_bit == NULL) {
|
||||
test_input_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]);
|
||||
estimated_output_bit = (unsigned char *)malloc16(8 * rel15->TBSize[0]);
|
||||
test_input_bit = (unsigned char *)malloc16(8 * pdsch_pdu_rel15->TBSize[0]);
|
||||
estimated_output_bit = (unsigned char *)malloc16(8 * pdsch_pdu_rel15->TBSize[0]);
|
||||
}
|
||||
for (i = 0; i < TBS; i++) {
|
||||
|
||||
estimated_output_bit[i] = (UE->phy_sim_dlsch_b[i/8] & (1 << (i & 7))) >> (i & 7);
|
||||
test_input_bit[i] = (gNB_dlsch->harq_process.b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
|
||||
test_input_bit[i] = (gNB_dlsch->b[i / 8] & (1 << (i & 7))) >> (i & 7); // Further correct for multiple segments
|
||||
|
||||
if (estimated_output_bit[i] != test_input_bit[i]) {
|
||||
if(errors_bit == 0)
|
||||
@@ -1320,7 +1305,7 @@ int main(int argc, char **argv)
|
||||
printf("), Channel BER (%e", berStats[0]);
|
||||
for (int r = 1; r < num_rounds; r++)
|
||||
printf(",%e", berStats[r]);
|
||||
printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]);
|
||||
printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats, effRate, effRate / (8 * pdsch_pdu_rel15->TBSize[0]) * 100, 8 * pdsch_pdu_rel15->TBSize[0]);
|
||||
printf("*****************************************\n");
|
||||
printf("\n");
|
||||
// writing to csv file
|
||||
@@ -1328,7 +1313,7 @@ int main(int argc, char **argv)
|
||||
fprintf(csv_file,"%f,%d/%d,",SNR,n_false_positive,n_trials);
|
||||
for (int r = 0; r < num_rounds; r++)
|
||||
fprintf(csv_file,"%d/%d,%u/%u,%f,%e,",n_errors[r], round_trials[r], errors_scrambling[r], available_bits * round_trials[r],blerStats[r],berStats[r]);
|
||||
fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * rel15->TBSize[0]) * 100, 8 * rel15->TBSize[0]);
|
||||
fprintf(csv_file,"%.2f,%.4f,%.2f,%u\n", roundStats, effRate, effRate / (8 * pdsch_pdu_rel15->TBSize[0]) * 100, 8 * pdsch_pdu_rel15->TBSize[0]);
|
||||
}
|
||||
if (print_perf==1) {
|
||||
printf("\ngNB TX function statistics (per %d us slot, NPRB %d, mcs %d, C %d, block %d)\n",
|
||||
@@ -1336,7 +1321,7 @@ int main(int argc, char **argv)
|
||||
g_rbSize,
|
||||
g_mcsIndex,
|
||||
UE->dl_harq_processes[0][slot].C,
|
||||
8 * rel15->TBSize[0]);
|
||||
8 * pdsch_pdu_rel15->TBSize[0]);
|
||||
printDistribution(&gNB->phy_proc_tx,table_tx,"PHY proc tx");
|
||||
printStatIndent2(&gNB->dci_generation_stats, "DCI encoding time");
|
||||
printStatIndent2(&gNB->dlsch_encoding_stats,"DLSCH encoding time");
|
||||
@@ -1378,8 +1363,8 @@ int main(int argc, char **argv)
|
||||
const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15);
|
||||
for (int l = 0; l < g_nrOfLayers; l++) {
|
||||
for (int r = 0; r < n_rx; r++) {
|
||||
const int s = rel15->StartSymbolIndex;
|
||||
const int n = rel15->NrOfSymbols;
|
||||
const int s = pdsch_pdu_rel15->StartSymbolIndex;
|
||||
const int n = pdsch_pdu_rel15->NrOfSymbols;
|
||||
for (int i = s; i < s + n; i++) {
|
||||
const uint32_t dmrsBitMap = phy_data.dlsch[0].dlsch_config.dlDmrsSymbPos;
|
||||
const uint32_t dmrsCfg = phy_data.dlsch[0].dlsch_config.dmrsConfigType;
|
||||
@@ -1415,7 +1400,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
if (effRate >= (eff_tp_check * 8 * rel15->TBSize[0])) {
|
||||
if (effRate >= (eff_tp_check * 8 * pdsch_pdu_rel15->TBSize[0])) {
|
||||
printf("PDSCH test OK\n");
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
@@ -519,10 +519,10 @@ int main(int argc, char **argv)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
processingData_L1tx_t msgDataTx;
|
||||
// generate signal
|
||||
const uint32_t rxdataF_sz = UE->frame_parms.samples_per_slot_wCP;
|
||||
__attribute__ ((aligned(32))) c16_t rxdataF[UE->frame_parms.nb_antennas_rx][rxdataF_sz];
|
||||
nfapi_nr_dl_tti_ssb_pdu ssb_pdu[64] = {0};
|
||||
if (input_fd==NULL) {
|
||||
|
||||
for (i=0; i<frame_parms->Lmax; i++) {
|
||||
@@ -530,10 +530,10 @@ int main(int argc, char **argv)
|
||||
|
||||
const int sc_offset = frame_parms->freq_range == FR1 ? ssb_subcarrier_offset<<mu : ssb_subcarrier_offset;
|
||||
const int prb_offset = frame_parms->freq_range == FR1 ? gNB->gNB_config.ssb_table.ssb_offset_point_a.value<<mu : gNB->gNB_config.ssb_table.ssb_offset_point_a.value << (mu - 2);
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset;
|
||||
msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = prb_offset;
|
||||
ssb_pdu[i].ssb_pdu_rel15.bchPayload = 0x55dd33;
|
||||
ssb_pdu[i].ssb_pdu_rel15.SsbBlockIndex = i;
|
||||
ssb_pdu[i].ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset;
|
||||
ssb_pdu[i].ssb_pdu_rel15.ssbOffsetPointA = prb_offset;
|
||||
|
||||
start_symbol = nr_get_ssb_start_symbol(frame_parms,i);
|
||||
int slot = start_symbol/14;
|
||||
@@ -541,7 +541,7 @@ int main(int argc, char **argv)
|
||||
for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++)
|
||||
memset(gNB->common_vars.txdataF[0][aa], 0, frame_parms->samples_per_slot_wCP * sizeof(int32_t));
|
||||
|
||||
nr_common_signal_procedures (gNB,frame,slot,msgDataTx.ssb[i].ssb_pdu);
|
||||
nr_common_signal_procedures (gNB,frame,slot, &ssb_pdu[i]);
|
||||
|
||||
int samp = frame_parms->get_samples_slot_timestamp(slot, frame_parms, 0);
|
||||
for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
|
||||
@@ -744,7 +744,7 @@ int main(int argc, char **argv)
|
||||
gNB->gNB_config.ssb_table.ssb_subcarrier_offset.value,
|
||||
frame_parms->Lmax);
|
||||
int payload_ret = (result.xtra_byte == xtra_byte);
|
||||
nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &msgDataTx.ssb[ssb_index].ssb_pdu.ssb_pdu_rel15;
|
||||
nfapi_nr_dl_tti_ssb_pdu_rel15_t *pdu = &ssb_pdu[ssb_index].ssb_pdu_rel15;
|
||||
for (int i = 0; i < 3; i++)
|
||||
payload_ret += (result.decoded_output[i] == ((pdu->bchPayload >> (8 * i)) & 0xff));
|
||||
// printf("ret %d\n", payload_ret);
|
||||
|
||||
@@ -60,7 +60,6 @@
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/impl_defs_nr.h"
|
||||
#include "PHY/phy_vars_nr_ue.h"
|
||||
#include "SCHED_NR/fapi_nr_l1.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
#include "SCHED_NR_UE/defs.h"
|
||||
#include "SCHED_NR_UE/fapi_nr_ue_l1.h"
|
||||
@@ -727,11 +726,6 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
initNamedTpool(gNBthreads, &gNB->threadPool, true, "gNB-tpool");
|
||||
|
||||
processingData_L1tx_t *msgDataTx = malloc(sizeof(processingData_L1tx_t));
|
||||
msgDataTx->slot = -1;
|
||||
gNB->msgDataTx = msgDataTx;
|
||||
//gNB_config = &gNB->gNB_config;
|
||||
|
||||
NR_UL_IND_t UL_INFO = {0};
|
||||
UL_INFO.crc_ind.crc_list = UL_INFO.crc_pdu_list;
|
||||
UL_INFO.rx_ind.pdu_list = UL_INFO.rx_pdu_list;
|
||||
@@ -1284,6 +1278,9 @@ int main(int argc, char *argv[])
|
||||
srs_pdu->beamforming.prg_size = 1;
|
||||
}
|
||||
|
||||
/* load FAPI into RX of L1 */
|
||||
nr_save_ul_tti_req(gNB, &Sched_INFO->UL_tti_req);
|
||||
|
||||
/// UE UL PDUs
|
||||
|
||||
UE->ul_harq_processes[harq_pid].round = round;
|
||||
@@ -1291,9 +1288,6 @@ int main(int argc, char *argv[])
|
||||
UE_proc.frame_tx = frame;
|
||||
UE_proc.gNB_id = 0;
|
||||
|
||||
// prepare ULSCH/PUSCH reception
|
||||
nr_schedule_response(Sched_INFO);
|
||||
|
||||
// --------- setting parameters for UE --------
|
||||
nr_scheduled_response_t scheduled_response = {.ul_config = &ul_config, .phy_data = (void *)&phy_data};
|
||||
|
||||
|
||||
@@ -59,13 +59,7 @@ uint8_t nr_get_rv(int rel_round)
|
||||
return nr_rv_round_map[rel_round];
|
||||
}
|
||||
|
||||
void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
|
||||
int CC_idP,
|
||||
frame_t frameP,
|
||||
slot_t slotP,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req,
|
||||
nfapi_nr_ul_dci_request_t *UL_dci_req)
|
||||
void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, slot_t slotP)
|
||||
{
|
||||
/* called below and in simulators, so we assume a lock but don't require it */
|
||||
const int num_slots = gNB->frame_structure.numb_slots_frame;
|
||||
@@ -75,16 +69,8 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
|
||||
|
||||
gNB->pdu_index[CC_idP] = 0;
|
||||
|
||||
DL_req[CC_idP].SFN = frameP;
|
||||
DL_req[CC_idP].Slot = slotP;
|
||||
DL_req[CC_idP].dl_tti_request_body.nPDUs = 0;
|
||||
DL_req[CC_idP].dl_tti_request_body.nGroup = 0;
|
||||
memset(pdcch, 0, sizeof(*pdcch) * MAX_NUM_CORESET);
|
||||
|
||||
UL_dci_req[CC_idP].SFN = frameP;
|
||||
UL_dci_req[CC_idP].Slot = slotP;
|
||||
UL_dci_req[CC_idP].numPdus = 0;
|
||||
|
||||
/* advance last round's future UL_tti_req to be ahead of current frame/slot */
|
||||
const int size = gNB->UL_tti_req_ahead_size;
|
||||
const int prev_slot = frameP * num_slots + slotP + size - 1;
|
||||
@@ -100,8 +86,6 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
|
||||
future_ul_tti_req->n_ulsch = 0;
|
||||
future_ul_tti_req->n_ulcch = 0;
|
||||
future_ul_tti_req->n_group = 0;
|
||||
|
||||
TX_req[CC_idP].Number_of_PDUs = 0;
|
||||
}
|
||||
|
||||
static void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int slots_per_frame)
|
||||
@@ -191,7 +175,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, slot_t slo
|
||||
uint16_t *vrb_map_UL = cc[CC_id].vrb_map_UL[i];
|
||||
memcpy(&vrb_map_UL[prev_slot % size * MAX_BWP_SIZE], &gNB->ulprbbl, sizeof(uint16_t) * MAX_BWP_SIZE);
|
||||
}
|
||||
clear_nr_nfapi_information(gNB, CC_id, frame, slot, &sched_info->DL_req, &sched_info->TX_req, &sched_info->UL_dci_req);
|
||||
clear_nr_nfapi_information(gNB, CC_id, frame, slot);
|
||||
}
|
||||
|
||||
bool wait_prach_completed = gNB->num_scheduled_prach_rx >= NUM_PRACH_RX_FOR_NOISE_ESTIMATE;
|
||||
|
||||
@@ -67,13 +67,7 @@ int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs);
|
||||
|
||||
int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info);
|
||||
|
||||
void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
|
||||
int CC_idP,
|
||||
frame_t frameP,
|
||||
slot_t slotP,
|
||||
nfapi_nr_dl_tti_request_t *DL_req,
|
||||
nfapi_nr_tx_data_request_t *TX_req,
|
||||
nfapi_nr_ul_dci_request_t *UL_dci_req);
|
||||
void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, frame_t frameP, slot_t slotP);
|
||||
|
||||
void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot);
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "nfapi/oai_integration/gnb_ind_vars.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "nfapi_interface.h"
|
||||
#include "openair2/NR_PHY_INTERFACE/nr_sched_response.h"
|
||||
#include "openair2/PHY_INTERFACE/queue_t.h"
|
||||
#include "utils.h"
|
||||
#include "nfapi/oai_integration/nfapi_pnf.h"
|
||||
@@ -379,52 +378,25 @@ static void match_crc_rx_pdu(nfapi_nr_rx_data_indication_t *rx_ind, nfapi_nr_crc
|
||||
}
|
||||
}
|
||||
|
||||
extern void handle_nr_slot_ind(uint16_t sfn, uint16_t slot);
|
||||
static void pnf_send_slot_ind(module_id_t module_id, int CC_id, int frame, int slot)
|
||||
extern void handle_nr_slot_ind(uint16_t sfn, uint16_t slot, NR_Sched_Rsp_t *sched_response);
|
||||
static void pnf_send_slot_ind(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp)
|
||||
{
|
||||
(void)module_id;
|
||||
(void)CC_id;
|
||||
handle_nr_slot_ind(frame, slot);
|
||||
module_id_t module_id = 0;
|
||||
int CC_id = 0;
|
||||
reset_sched_response(rsp, ind->sfn, ind->slot, module_id, CC_id);
|
||||
handle_nr_slot_ind(ind->sfn, ind->slot, rsp);
|
||||
}
|
||||
|
||||
static void run_scheduler_monolithic(module_id_t module_id, int CC_id, int frame, int slot)
|
||||
static void run_scheduler_monolithic(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp)
|
||||
{
|
||||
NR_IF_Module_t *ifi = nr_if_inst[module_id];
|
||||
|
||||
LOG_D(NR_MAC, "Calling scheduler for %d.%d\n", frame, slot);
|
||||
NR_Sched_Rsp_t *sched_info = allocate_sched_response();
|
||||
|
||||
// clear UL DCI prior to handling ULSCH
|
||||
sched_info->UL_dci_req.numPdus = 0;
|
||||
gNB_dlsch_ulsch_scheduler(module_id, frame, slot, sched_info);
|
||||
ifi->CC_mask = 0;
|
||||
sched_info->module_id = module_id;
|
||||
sched_info->CC_id = CC_id;
|
||||
sched_info->frame = frame;
|
||||
sched_info->slot = slot;
|
||||
/*
|
||||
sched_info->DL_req = &mac->DL_req[CC_id];
|
||||
sched_info->UL_dci_req = &mac->UL_dci_req[CC_id];
|
||||
|
||||
sched_info->UL_tti_req = mac->UL_tti_req[CC_id];
|
||||
|
||||
sched_info->TX_req = &mac->TX_req[CC_id];
|
||||
*/
|
||||
#ifdef DUMP_FAPI
|
||||
dump_dl(sched_info);
|
||||
#endif
|
||||
|
||||
AssertFatal(ifi->NR_Schedule_response != NULL, "nr_schedule_response is null (mod %d, cc %d)\n", module_id, CC_id);
|
||||
ifi->NR_Schedule_response(sched_info);
|
||||
|
||||
LOG_D(NR_PHY,
|
||||
"NR_Schedule_response: SFN SLOT:%d %d dl_pdus:%d\n",
|
||||
sched_info->frame,
|
||||
sched_info->slot,
|
||||
sched_info->DL_req.dl_tti_request_body.nPDUs);
|
||||
module_id_t module_id = 0;
|
||||
int CC_id = 0;
|
||||
reset_sched_response(rsp, ind->sfn, ind->slot, module_id, CC_id);
|
||||
gNB_dlsch_ulsch_scheduler(rsp->module_id, ind->sfn, ind->slot, rsp);
|
||||
}
|
||||
|
||||
void NR_UL_indication(NR_UL_IND_t *UL_info) {
|
||||
static void NR_UL_indication(NR_UL_IND_t *UL_info)
|
||||
{
|
||||
AssertFatal(UL_info!=NULL,"UL_info is null\n");
|
||||
module_id_t module_id = UL_info->module_id;
|
||||
int CC_id = UL_info->CC_id;
|
||||
@@ -501,17 +473,47 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id) {
|
||||
|
||||
nr_if_inst[Mod_id]->CC_mask=0;
|
||||
nr_if_inst[Mod_id]->NR_UL_indication = NR_UL_indication;
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC)
|
||||
if (NFAPI_MODE == NFAPI_MONOLITHIC) {
|
||||
nr_if_inst[Mod_id]->NR_slot_indication = run_scheduler_monolithic;
|
||||
else if (NFAPI_MODE == NFAPI_MODE_PNF)
|
||||
} else if (NFAPI_MODE == NFAPI_MODE_PNF) {
|
||||
nr_if_inst[Mod_id]->NR_slot_indication = pnf_send_slot_ind;
|
||||
else // NFAPI_MODE_VNF
|
||||
NULL;
|
||||
} else { // NFAPI_MODE_VNF
|
||||
DevAssert(NFAPI_MODE == NFAPI_MODE_VNF || NFAPI_MODE == NFAPI_MODE_AERIAL);
|
||||
nr_if_inst[Mod_id]->NR_slot_indication = run_scheduler_monolithic;
|
||||
}
|
||||
AssertFatal(pthread_mutex_init(&nr_if_inst[Mod_id]->if_mutex,NULL)==0,
|
||||
"allocation of nr_if_inst[%d]->if_mutex fails\n",Mod_id);
|
||||
}
|
||||
|
||||
init_sched_response();
|
||||
|
||||
return nr_if_inst[Mod_id];
|
||||
}
|
||||
|
||||
void reset_sched_response(NR_Sched_Rsp_t *sched_response, int frame, int slot, int module_id, int CC_id)
|
||||
{
|
||||
sched_response->module_id = module_id;
|
||||
sched_response->CC_id = CC_id;
|
||||
sched_response->frame = frame;
|
||||
sched_response->slot = slot;
|
||||
|
||||
|
||||
nfapi_nr_dl_tti_request_t *DL_req = &sched_response->DL_req;
|
||||
DL_req->SFN = frame;
|
||||
DL_req->Slot = slot;
|
||||
DL_req->dl_tti_request_body.nPDUs = 0;
|
||||
DL_req->dl_tti_request_body.nGroup = 0;
|
||||
|
||||
nfapi_nr_ul_dci_request_t *UL_dci_req = &sched_response->UL_dci_req;
|
||||
UL_dci_req->SFN = frame;
|
||||
UL_dci_req->Slot = slot;
|
||||
UL_dci_req->numPdus = 0;
|
||||
|
||||
nfapi_nr_ul_tti_request_t *UL_tti_req = &sched_response->UL_tti_req;
|
||||
UL_tti_req->SFN = frame;
|
||||
UL_tti_req->Slot = slot;
|
||||
UL_tti_req->n_pdus = 0;
|
||||
|
||||
nfapi_nr_tx_data_request_t *TX_req = &sched_response->TX_req;
|
||||
TX_req->SFN = frame;
|
||||
TX_req->Slot = slot;
|
||||
TX_req->Number_of_PDUs = 0;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ typedef struct {
|
||||
// Downlink slot P7
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct NR_Sched_Rsp {
|
||||
/// the ID of this sched_response - used by sched_reponse memory management
|
||||
int sched_response_id;
|
||||
/// Module ID
|
||||
@@ -111,6 +111,7 @@ typedef struct {
|
||||
/// Pointers to DL SDUs
|
||||
nfapi_nr_tx_data_request_t TX_req;
|
||||
} NR_Sched_Rsp_t;
|
||||
void reset_sched_response(NR_Sched_Rsp_t *sched_response, int frame, int slot, int module_id, int CC_id);
|
||||
|
||||
typedef struct {
|
||||
uint8_t Mod_id;
|
||||
@@ -121,8 +122,7 @@ typedef struct {
|
||||
typedef struct NR_IF_Module_s {
|
||||
//define the function pointer
|
||||
void (*NR_UL_indication)(NR_UL_IND_t *UL_INFO);
|
||||
void (*NR_Schedule_response)(NR_Sched_Rsp_t *Sched_INFO);
|
||||
void (*NR_slot_indication)(module_id_t module_idP, int CC_id, int frame, int slot);
|
||||
void (*NR_slot_indication)(const nfapi_nr_slot_indication_scf_t *ind, NR_Sched_Rsp_t *rsp);
|
||||
void (*NR_PHY_config_req)(NR_PHY_Config_t *config_INFO);
|
||||
uint32_t CC_mask;
|
||||
uint16_t current_frame;
|
||||
@@ -136,9 +136,4 @@ NR_IF_Module_t *NR_IF_Module_init(int Mod_id);
|
||||
|
||||
void NR_IF_Module_kill(int Mod_id);
|
||||
|
||||
void NR_UL_indication(NR_UL_IND_t *UL_INFO);
|
||||
|
||||
/*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/
|
||||
void NR_Schedule_Response(NR_Sched_Rsp_t *Sched_INFO);
|
||||
|
||||
#endif /*_NFAPI_INTERFACE_NR_H_*/
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/* sched response memory management */
|
||||
|
||||
/* A system with reference counting is implemented.
|
||||
* It is needed because several threads will access the structure,
|
||||
* which has to be released only when all the threads are done with it.
|
||||
* So the main thread allocates a sched_response with allocate_sched_response()
|
||||
* which allocates a sched_response with a reference counter == 1
|
||||
* and then for each other thread that will access sched_response, a
|
||||
* call to inc_ref_sched_response() is done. When a thread has finished
|
||||
* using the sched_response, it calls deref_sched_response() which will
|
||||
* in turn call release_sched_response() when the reference counter becomes 0.
|
||||
*
|
||||
* The several threads in question are accessing the _same_ sched_response,
|
||||
* it has not to be confused with the various TX processes that may run in
|
||||
* parallel and which are accessing _different_ sched_response (the maximum
|
||||
* number of parallel processes is N_RESP).
|
||||
*/
|
||||
|
||||
#include "nr_sched_response.h"
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "NR_PHY_INTERFACE/NR_IF_Module.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/assertions.h"
|
||||
|
||||
#define N_RESP 3
|
||||
static NR_Sched_Rsp_t resp[N_RESP];
|
||||
static int resp_refcount[N_RESP];
|
||||
static int resp_freelist_next[N_RESP];
|
||||
static int resp_freelist_head;
|
||||
static pthread_mutex_t resp_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool resp_freelist_inited = false;
|
||||
|
||||
void init_sched_response(void)
|
||||
{
|
||||
/* init only once */
|
||||
if (pthread_mutex_lock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_lock failed\n");
|
||||
if (resp_freelist_inited) {
|
||||
if (pthread_mutex_unlock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_unlock failed\n");
|
||||
return;
|
||||
}
|
||||
resp_freelist_inited = true;
|
||||
if (pthread_mutex_unlock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_unlock failed\n");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < N_RESP - 1; i++)
|
||||
resp_freelist_next[i] = i + 1;
|
||||
resp_freelist_next[N_RESP - 1] = -1;
|
||||
resp_freelist_head = 0;
|
||||
}
|
||||
|
||||
NR_Sched_Rsp_t *allocate_sched_response(void)
|
||||
{
|
||||
NR_Sched_Rsp_t *ret;
|
||||
int new_head;
|
||||
|
||||
if (pthread_mutex_lock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_lock failed\n");
|
||||
|
||||
AssertFatal(resp_freelist_inited, "sched_response used before init\n");
|
||||
|
||||
if (resp_freelist_head == -1) {
|
||||
LOG_E(PHY, "fatal: sched_response cannot be allocated, increase N_RESP\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = &resp[resp_freelist_head];
|
||||
ret->sched_response_id = resp_freelist_head;
|
||||
resp_refcount[resp_freelist_head] = 1;
|
||||
|
||||
new_head = resp_freelist_next[resp_freelist_head];
|
||||
resp_freelist_next[resp_freelist_head] = -1;
|
||||
resp_freelist_head = new_head;
|
||||
|
||||
if (pthread_mutex_unlock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_unlock failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void release_sched_response(int sched_response_id)
|
||||
{
|
||||
LOG_D(NR_MAC,"Releasing sched_response %d\n",sched_response_id);
|
||||
resp_freelist_next[sched_response_id] = resp_freelist_head;
|
||||
resp_freelist_head = sched_response_id;
|
||||
}
|
||||
|
||||
void deref_sched_response(int sched_response_id)
|
||||
{
|
||||
/* simulators (ulsim/dlsim) deal with their own sched_response but call
|
||||
* functions that call this one, let's handle this case with a special
|
||||
* value -1 where we do nothing (yes it's a hack)
|
||||
*/
|
||||
if (sched_response_id == -1)
|
||||
return;
|
||||
|
||||
if (pthread_mutex_lock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_lock failed\n");
|
||||
|
||||
AssertFatal(resp_freelist_inited, "sched_response used before init\n");
|
||||
AssertFatal(resp_refcount[sched_response_id] > 0, "sched_reponse decreased too much\n");
|
||||
|
||||
LOG_D(NR_MAC,"resp_refcount[%d] %d\n",sched_response_id,resp_refcount[sched_response_id]);
|
||||
resp_refcount[sched_response_id]--;
|
||||
if (resp_refcount[sched_response_id] == 0)
|
||||
release_sched_response(sched_response_id);
|
||||
|
||||
if (pthread_mutex_unlock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_unlock failed\n");
|
||||
}
|
||||
|
||||
void inc_ref_sched_response(int sched_response_id)
|
||||
{
|
||||
/* simulators (ulsim/dlsim) deal with their own sched_response but call
|
||||
* functions that call this one, let's handle this case with a special
|
||||
* value -1 where we do nothing (yes it's a hack)
|
||||
*/
|
||||
if (sched_response_id == -1)
|
||||
return;
|
||||
|
||||
LOG_D(NR_MAC,"Incrementing sched_resp resp_refounct[%d] = %d\n",
|
||||
sched_response_id,resp_refcount[sched_response_id]);
|
||||
if (pthread_mutex_lock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_lock failed\n");
|
||||
|
||||
AssertFatal(resp_freelist_inited, "sched_response used before init\n");
|
||||
|
||||
resp_refcount[sched_response_id]++;
|
||||
|
||||
if (pthread_mutex_unlock(&resp_mutex))
|
||||
AssertFatal(0, "pthread_mutex_unlock failed\n");
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H
|
||||
#define OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H
|
||||
|
||||
#include "NR_IF_Module.h"
|
||||
|
||||
void init_sched_response(void);
|
||||
NR_Sched_Rsp_t *allocate_sched_response(void);
|
||||
void deref_sched_response(int sched_response_id);
|
||||
void inc_ref_sched_response(int sched_response_id);
|
||||
|
||||
#endif /* OPENAIR2_NR_PHY_INTERFACE_NR_SCHED_RESPONSE_H */
|
||||
@@ -22,6 +22,7 @@ RUs = ({
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [78];
|
||||
sl_ahead = 2;
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 125;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user