diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index f155d3061db9a80041b292432d8f90b18f210d45..6382bbea511bac0a348a83a989e76279a29bfa61 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1590,6 +1590,7 @@ add_library(PHY_COMMON ${PHY_SRC_COMMON}) add_dependencies(PHY_COMMON rrc_flag) add_dependencies(PHY_COMMON dfts) add_library(PHY ${PHY_SRC}) + add_dependencies(PHY rrc_flag) add_library(PHY_UE ${PHY_SRC_UE}) add_dependencies(PHY_UE rrc_flag) @@ -2481,6 +2482,7 @@ add_executable(lte-softmodem ${OPENAIR_TARGETS}/RT/USER/lte-ru.c ${OPENAIR_TARGETS}/RT/USER/ru_control.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/executables/softmodem-common.c ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c @@ -2516,6 +2518,43 @@ target_link_libraries (lte-softmodem pthread m ${CONFIG_LIB} rt crypt ${CRYPTO_L target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES}) target_link_libraries (lte-softmodem ${T_LIB}) + +add_executable(ocp-enb + ${OPENAIR_DIR}/executables/main-ocp.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/executables/softmodem-common.c + ${OPENAIR_DIR}/executables/main-fs6.c + ${OPENAIR_DIR}/executables/transport_split.c + ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c + ${OPENAIR_TARGETS}/COMMON/create_tasks.c + ${OPENAIR_TARGETS}/COMMON/create_tasks_mbms.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${OPENAIR_TARGETS}/ARCH/COMMON/record_player.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c + ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c + ${GTPU_need_ITTI} + ${XFORMSINTERFACE_SOURCE} + ${T_SOURCE} + ${CONFIG_SOURCES} + ${SHLIB_LOADER_SOURCES} + ) +add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer) + +target_link_libraries (ocp-enb + -Wl,--start-group + RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB + PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} + -Wl,--end-group z dl) +target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) + add_executable(cu_test ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/cu_test.c ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/proto_agent_handler.c @@ -2856,6 +2895,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr add_executable(${myExe} ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/system.c ${XFORMS_SOURCE} diff --git a/cmake_targets/phy_simulators/CMakeLists.txt b/cmake_targets/phy_simulators/CMakeLists.txt index b43f7dd389717774b6462cc2c0e4564dc0807b96..5f2d34883eea95e1905f177a53e44f82635ee7d3 100644 --- a/cmake_targets/phy_simulators/CMakeLists.txt +++ b/cmake_targets/phy_simulators/CMakeLists.txt @@ -1,13 +1,19 @@ cmake_minimum_required(VERSION 2.8) -set(PACKAGE_NAME "unitary_tests_simulators") -set(PHYSIM True) -set(RF_BOARD None) -set(XFORMS True) -set(ENABLE_ITTI True) -set(DEBUG_PHY False) -set(MU_RECIEVER False) -set(NAS_UE False) -set(MESSAGE_CHART_GENERATOR False) -set(RRC_ASN1_VERSION "Rel15") -set(T_TRACER True) -include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt) \ No newline at end of file +set ( CMAKE_BUILD_TYPE ) +set ( CFLAGS_PROCESSOR_USER "" ) +set ( UE_EXPANSION False ) +set ( PRE_SCD_THREAD False ) +set ( UESIM_EXPANSION False ) +set ( ENABLE_VCD_FIFO False ) +set ( RF_BOARD "OAI_USRP") +set ( TRANSP_PRO "None") +set ( PACKAGE_NAME "") +set ( DEADLINE_SCHEDULER "False" ) +set ( CPU_AFFINITY "False" ) +set ( T_TRACER True ) +set ( UE_AUTOTEST_TRACE False ) +set ( UE_DEBUG_TRACE False ) +set ( UE_TIMING_TRACE False ) +set ( USRP_REC_PLAY False ) +set ( SKIP_SHARED_LIB_FLAG False ) +include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt) diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 89e19074bf96a24c911b523a98c56bcf31612309..42c3828dc4536784d7cde66f468251828c204a65 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -7,6 +7,7 @@ #include <sys/eventfd.h> +extern "C" { #include <intertask_interface.h> #include <common/utils/system.h> @@ -35,7 +36,6 @@ typedef struct task_list_s { int timer_expired(int fd); task_list_t tasks[TASK_MAX]; -extern "C" { void *pool_buffer_init (void) { return 0; } @@ -86,6 +86,9 @@ extern "C" { temp->ittiMsgHeader.messageId = message_id; temp->ittiMsgHeader.originTaskId = origin_task_id; temp->ittiMsgHeader.ittiMsgSize = size; + temp->ittiMsgHeader.destinationTaskId=TASK_UNKNOWN; + temp->ittiMsgHeader.instance=0; + temp->ittiMsgHeader.lte_time={0}; return temp; //return itti_alloc_new_message_sized(origin_task_id, message_id, messages_info[message_id].size); } diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 52c733752de92d885a230330dce385d3e56f558e..265a57ca63712f48ed473e2f784e04a3ef60689f 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -275,7 +275,7 @@ typedef struct { //TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) //TASK_DEF(TASK_GTPV1_U, TASK_PRIORITY_MED, 1000,NULL, NULL) //TASK_DEF(TASK_UDP, TASK_PRIORITY_MED, 1000, NULL, NULL) - +void * rrc_enb_process_msg(void*); #define FOREACH_TASK(TASK_DEF) \ TASK_DEF(TASK_UNKNOWN, TASK_PRIORITY_MED, 50, NULL, NULL) \ TASK_DEF(TASK_TIMER, TASK_PRIORITY_MED, 10, NULL, NULL) \ @@ -288,7 +288,7 @@ typedef struct { TASK_DEF(TASK_PDCP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_DATA_FORWARDING, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_END_MARKER, TASK_PRIORITY_MED, 200, NULL, NULL) \ - TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL,NULL)\ + TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, rrc_enb_process_msg,NULL)\ TASK_DEF(TASK_RRC_GNB, TASK_PRIORITY_MED, 200, NULL,NULL)\ TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200, NULL, NULL) \ diff --git a/common/utils/system.c b/common/utils/system.c index 3a8fe7be3d82260448071d915af94bbc28eb2147..1bd5c7d39bc500d979bd8d258c8fa7dd16a52b95 100644 --- a/common/utils/system.c +++ b/common/utils/system.c @@ -243,6 +243,8 @@ void configure_linux(void) { // Set CPU frequency to it's maximum if ( 0 != system("for d in /sys/devices/system/cpu/cpu[0-9]*; do cat $d/cpufreq/cpuinfo_max_freq > $d/cpufreq/scaling_min_freq; done")) - LOG_W(HW,"Can't set cpu frequency\n"); - + LOG_E(HW,"Can't set cpu frequency\n"); + + mlockall(MCL_CURRENT | MCL_FUTURE); + } diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 9a2681a828ea312c57a4f79a6d6de37c0da7e52d..1b59fb158991a4e207c8c90dd3cbadd4f3f651f0 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -217,11 +217,11 @@ static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { notifiedFIFO_elt_t *msg= pullNotifiedFIFO(responseFifo); - + AssertFatal(t->traceFd, "Thread pool used while not initialized"); if (t->measurePerf) msg->returnTime=rdtsc(); - if (t->traceFd >= 0) + if (t->traceFd > 0) if(write(t->traceFd, msg, sizeof(*msg))); return msg; @@ -229,7 +229,7 @@ static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_ static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { notifiedFIFO_elt_t *msg= pollNotifiedFIFO(responseFifo); - + AssertFatal(t->traceFd, "Thread pool used while not initialized"); if (msg == NULL) return NULL; diff --git a/doc/SystemX-tutorial-design.md b/doc/SystemX-tutorial-design.md new file mode 100644 index 0000000000000000000000000000000000000000..371cb33a7512e67306d4bc0dae05867c630f34d4 --- /dev/null +++ b/doc/SystemX-tutorial-design.md @@ -0,0 +1,317 @@ +# OpenAirInterface for SystemX + +#Terminology + +****This document use the 5G terminology**** + +**Central Unit (CU): **It is a logical node that includes the gNB +functions like Transfer of user data, Mobility control, Radio access +network sharing, Positioning, Session Management etc., except those +functions allocated exclusively to the DU. CU controls the operation of +DUs over front-haul (Fs) interface. A central unit (CU) may also be +known as BBU/REC/RCC/C-RAN/V-RAN/VNF + +**Distributed Unit (DU):** This logical node includes a subset of the +gNB functions, depending on the functional split option. Its operation +is controlled by the CU. Distributed Unit (DU) also known with other +names like RRH/RRU/RE/RU/PNF. + +In OpenAir code, the terminology is often RU and BBU. + +# OpenAirUsage +##EPC and general environment +### OAI EPC + +Use the stable OAI EPC, that can run in one machine (VM or standalone) + +Draft description: +<https://open-cells.com/index.php/2017/08/22/all-in-one-openairinterface-august-22nd/> + +##Standalone 4G + +EPC+eNB on one machine, the UE can be commercial or OAI UE. +### USRP B210 + +Main current issue: traffic is good only on coaxial link between UE and +eNB (probably power management issue). + +### Simulated RF + +Running eNB+UE both OAI can be done over a virtual RF link. + +The UE current status is that threads synchronization is implicit in +some cases. As the RF simulator is very quick, a “sleep()†is required +in the UE main loop + +(line 1744, targets/RT/USER/lte-ue.c). + +Running also the UE in the same machine is possible with simulated RF. + +Running in same machine is simpler, offers about infinite speed for +virtual RF samples transmission. + +A specific configuration is required because the EPC Sgi interface has +the same IP tunnel end point as the UE. + +So, we have to create a network namespace for the UE and to route data +in/out of the namespace. +``` bash +ip netns delete aNameSpace 2> /dev/null + +ip link delete v-eth1 2> /dev/null + +ip netns add aNameSpace + +ip link add v-eth1 type veth peer name v-peer1 + +ip link set v-peer1 netns aNameSpace + +ip addr add 10.200.1.1/24 dev v-eth1 + +ip link set v-eth1 up + +iptables -t nat -A POSTROUTING -s 10.200.1.0/255.255.255.0 -o enp0s31f6 +-j MASQUERADE + +iptables -A FORWARD -i enp0s31f6 -o v-eth1 -j ACCEPT + +iptables -A FORWARD -o enp0s31f6 -i v-eth1 -j ACCEPT + +ip netns exec aNameSpace ip link set dev lo up + +ip netns exec aNameSpace ip addr add 10.200.1.2/24 dev v-peer1 + +ip netns exec aNameSpace ip link set v-peer1 up + +ip netns exec aNameSpace bash +``` + +After the last command, the Linux shell is in the new namespace, ready +to run the UE. + +To make user plan traffic, the traffic generator has to run in the same +namespace + +`ip netns exec aNameSpace bash +` + +The traffic genenrator has to specify the interface: + +`route add default oaitun_ue1 +` + +or specify the outgoing route in the traffic generator (like option “-I†+in ping command). + +## Split 6 DL 4G + +The contract describes to reuse the uplink existing if4p5 and to develop +is this work the downlink “functional split 6â€. + +The customer required after signature to develop also the uplink +functional split 6. This is accepted, as long as the whole work is +research with no delivery completeness warranty. +### Simulation + +To be able to verify the new features and to help in all future +developments, Open Cells added and improved the Rf board simulator +during this contract. + +We added the channel modeling simulation, that offer to simulate various +3GPP defined channels. +### Main loop + +The main log is in RF simulator is in + + targets/RT/USER/lte-ru.c and targets/RT/USER/lte-enb.c + +As this piece of SW is very complex and doesn’t meet our goals +(functional split 6), a cleaned version replaces these 2 files in +executables/ocp-main.c (openair1/SCHED/prach\_procedures.c is also +replaced by this new file as it only launching the RACH actual work in a +way not compatible with our FS6). + +The main loop cadences the I/Q samples reception, signal processing and +I/Q samples sending. + +The main loop uses extensively function pointers to call the right +processing function depending on the split case. + +A lot of OAI reduntant global variables contains the same semantic data: time,frame, subframe. +The reworked main loop take care of a uniq variable that comes directly from harware: RF board sampling number. + +To use OAI, we need to set all OAI variables that derivates from this timestamp value. The function setAllfromTS() implements this. + + +### Splitted main level +When FS6 is actived, a main loop for DU (du_fs6()) a main loop for CU case replaces the uniq eNB main loop. + +Each of these main loops calls initialization of OAI LTE data and the FS6 transport layer initialization. + +Then, it runs a infinite loop on: set time, call UL and DL. The time comes from the RF board, so the DU sends the time to the CU. + +This is enough for RF board dialog, but the FS6 is higher in SW layers, +we need to cut higher functions inside downlink and uplink procedures. + +As much as possible, the FS6 code is in the directory OPENAIR_DIR/executables. When a given OAI piece of code is small or need complex changes, it is reworked in the file fs6-main.c. The functions naming keeps the OAI function name, adding suffix _fromsplit() or _tosplit(). + +When this organization would lead to large code copy, it is better to insert modifications in OAI code. This is done in two files: + +- openair1/SCHED/phy_procedures_lte_eNb.c: to send signaling channels computation results + - the function sendFs6Ulharq() centralizes all signaling channels forwarding to CU +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c: to deal with FS6 user plane split + - sendFs6Ul() is used once to forward user plane to CU + + +### DownLink + +The main procedure is phy\_procedures\_eNB\_TX() + +This is building the common channels (beacon, multi-UE signaling). + +The FS6 split breaks this function into pieces: + +* The multi-UE signals, built by common\_signal\_procedures(), + subframe2harq\_pid(), generate\_dci\_top(), subframe2harq\_pid() + * These functions run in the DU, nevertheless all context has to be sent + (it is also needed partially for UL spitting) + * Run in the DU also to meet the requirement of pushing + in DU the data encoded with large redundancy (>3 redundancy) + +* the per UE data: pdsch\_procedures() needs further splitting: + + * dlsch\_encoding\_all() that makes the encoding: turbo code + and lte\_rate\_matching\_turbo() that will be in the DU (some + unlikely cases can reach redundancy up to x3, when MCS is very + low (negative SINR cases)). + + * dlsch\_encoding() output needs to be transmitted between the + DU and the CU for functional split 6. + * dlsch\_scrambling() that will go in the DU + * dlsch\_modulation() that will go in the DU + + The du user plane data is made of expanded bit in OAI at FS6 split level. 1 pair of functions compact back these bits into 8bits/byte before sending data and expand it again in the DU data reception (functions: fs6Dl(un)pack()). + +### Uplink + +The uplink require configuration that is part of the DL transmission. + +It interprets the signalling to extract the RACH and the per UE data +channels. + +Ocp-main.c:rxtx() calls directly the entry procedure +phy\_procedures\_eNB\_uespec\_RX() calls: + +* rx\_ulsch() that demodulate and extract soft bits per UE. + + * This function runs in the DU + * the output data will be processes in the DU, so it needs to be + transmitted to the DU +* ulsch\_decoding() that do lte\_rate\_matching\_turbo\_rx() + sub\_block\_deinterleaving\_turbo() + then turbo decode that is in the CU +* fill\_ulsch\_cqi\_indication() fill\_crc\_indication() , fill\_rx\_indication() + * DU performs the signal processing of each channel data, prepare and sent to the CU the computed result + +* Random access channel detection runs in the DU + * the DU reports to the CU only the detected temprary identifier for RACH response + + +### signaling data in each direction (UL and DL) + + +* each LTE channel needs to be propagated between CU and DU + * the simplest are the almost static data such as PSS/SSS, that need only static eNB parameters and primary information (frame numbering) + * all the other channels require data transmission CU to DU and DU to CU + * the general design push all the low level processing for these channels in the DU + * the CU interface transports only signal processing results (UL) or configuration to create the RF signal (DL case) +* HARQ is detected in the DU, then only the ACK or NACK is reported to CU + +* the CU have to control the power and MCS (modulation and coding scheme) + * the DU performs the signal processing and report only the decoded data like the CQI + * as the DU performas the modulation, scrambling and puncturing, each data packet is associated with the LTE parameters required for these features + * in DL, the CU associates the control parameters and the user plane data + * in UL, the CU sends upfront the scheduled UL data to the DU. So, the DU have the required knowledge to decode the next subframes in time. + +### UDP transport layer + +A general UDP transport layer is in executables/transport\_split.c + +Linux offers a UDP socket builtin timeout, that we use. + +In and out buffers are memory zones that contains compacted +(concatenated) UDP chunks. + +For output, sendSubFrame() sends each UDP chunk + +For input, receiveSubFrame() collects all UDP chunks for a group (a +subframe in OAI LTE case). It returns in the following cases: + +- all chunks are received +- a timeout expired +- a chunk from the next subframe already arrived + +### Functional split 6 usage + +The ocp cleaned main hale to be used: run ocp-softmodem instead of +lte-softmodem. + +The functionality and parameters is the same, enhanced with FS6 mode. + +The end line option “--split73†enables the fs6 (also called split 7.3) mode and decided to be cu or du. + +Example: + +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 cu:127.0.0.1 +` +Run the CU init of the split 6 eNB, that will call du on 127.0.0.1 address + +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 du:127.0.0.1 + +will run the du, calling the cu on 127.0.0.1 +` +If the CU and the DU are not on the same machine, the remote address of each side need to be specified as per this example + +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 du:192.168.1.55 +` +runs the functional split 6 DU + +`./lte-uesoftmodem -C 2685000000 -r 50 --rfsim --rfsimulator.serveraddr 192.168.1.1 -d +` + +Runs the UE (to have the UE signal scope, compile it with make uescope) + +CU+DU+UE can run with option --noS1 to avoid to use a EPC and/or with --rfsim to simulate RF board + + +##5G and F1 + +Today 5G achievement is limited to physical layer. + +The available modulation is 40MHz, that require one X310 or N300 for the +gNB and a X310 or N300 for the nrUE. + +### Usage with X310 + +Linux configuration: +<https://files.ettus.com/manual/page_usrp_x3x0_config.html> + +We included most of this configuration included in OAI source code. + +Remain to set the NIC (network interface card) MTU to 9000 (jumbo +frames). + +### Running 5G + +Usage with RFsimulator: + +gNB + +`sudo RFSIMULATOR=server ./nr-softmodem -O +../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +--parallel-config PARALLEL\_SINGLE\_THREAD` + +nrUE + +`sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C +3510000000 -d` diff --git a/executables/main-fs6.c b/executables/main-fs6.c new file mode 100644 index 0000000000000000000000000000000000000000..a10d96b556939a2d0790468cbbbc874eb275cff3 --- /dev/null +++ b/executables/main-fs6.c @@ -0,0 +1,1583 @@ +/* + Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX + copyleft: OpenAirInterface Software Alliance and it's licence +*/ +#include <stdint.h> +#include <common/utils/LOG/log.h> +#include <common/utils/system.h> +#include <common/config/config_userapi.h> +#include <targets/RT/USER/lte-softmodem.h> +#include <openair1/PHY/defs_eNB.h> +#include <openair1/PHY/phy_extern.h> +#include <nfapi/oai_integration/vendor_ext.h> +#include <openair1/SCHED/fapi_l1.h> +#include <openair1/PHY/INIT/phy_init.h> +#include <openair2/LAYER2/MAC/mac_extern.h> +#include <openair1/PHY/LTE_REFSIG/lte_refsig.h> +#include <nfapi/oai_integration/nfapi_pnf.h> +#include <executables/split_headers.h> +#include <nfapi/oai_integration/vendor_ext.h> +#include <openair1/PHY/INIT/lte_init.c> +#include <openair1/PHY/LTE_ESTIMATION/lte_estimation.h> +#include <executables/split_headers.h> +#include <openair1/PHY/CODING/coding_extern.h> +#include <threadPool/thread-pool.h> +#include <emmintrin.h> + +#define FS6_BUF_SIZE 1000*1000 +static UDPsock_t sockFS6; + +int sum(uint8_t *b, int s) { + int sum=0; + + for (int i=0; i < s; i++) + sum+=b[i]; + + return sum; +} + +static inline int cmpintRev(const void *a, const void *b) { + uint64_t *aa=(uint64_t *)a; + uint64_t *bb=(uint64_t *)b; + return (int)(*bb-*aa); +} + +static inline void printMeas2(char *txt, Meas *M, int period, bool MaxMin) { + if (M->iterations%period == 0 ) { + char txt2[512]; + sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " %s=%" + PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 "\n", + txt, + M->sum/M->iterations, + M->iterations, + MaxMin?"max":"min", + M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5], + M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]); +#if T_TRACER + LOG_W(PHY,"%s",txt2); +#else + printf("%s",txt2); +#endif + } +} + +static inline void updateTimesReset(uint64_t start, Meas *M, int period, bool MaxMin, char *txt) { + if (start!=0) { + uint64_t end=rdtsc(); + long long diff=(end-start)/(cpuf*1000); + M->maxArray[0]=diff; + M->sum+=diff; + M->iterations++; + + if ( MaxMin) + qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); + else + qsort(M->maxArray, 11, sizeof(uint64_t), cmpintRev); + + printMeas2(txt,M,period, MaxMin); + + if (M->iterations%period == 0 ) { + bzero(M,sizeof(*M)); + + if (!MaxMin) + for (int i=0; i<11; i++) + M->maxArray[i]=INT_MAX; + } + } +} + +static inline void measTransportTime(uint64_t DuSend, uint64_t CuMicroSec, Meas *M, int period, bool MaxMin, char *txt) { + if (DuSend!=0) { + uint64_t end=rdtsc(); + long long diff=(end-DuSend)/(cpuf*1000)-CuMicroSec; + M->maxArray[0]=diff; + M->sum+=diff; + M->iterations++; + + if ( MaxMin) + qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); + else + qsort(M->maxArray, 11, sizeof(uint64_t), cmpintRev); + + printMeas2(txt,M,period, MaxMin); + + if (M->iterations%period == 0 ) { + bzero(M,sizeof(*M)); + + if (!MaxMin) + for (int i=0; i<11; i++) + M->maxArray[i]=INT_MAX; + } + } +} + +#define ceil16_bytes(a) ((((a+15)/16)*16)/8) + +static void fs6Dlunpack(void *out, void *in, int szUnpacked) { + static uint64_t *lut=NULL; + + if (!lut) { + lut=(uint64_t *) malloc(sizeof(*lut)*256); + + for (int i=0; i <256; i++) + for (int j=0; j<8; j++) + ((uint8_t *)(lut+i))[7-j]=(i>>j)&1; + } + + int64_t *out_64 = (int64_t *)out; + int sz=ceil16_bytes(szUnpacked); + + for (int i=0; i<sz; i++) + out_64[i]=lut[((uint8_t *)in)[i]]; + + return; +} + + +static void fs6Dlpack(void *out, void *in, int szUnpacked) { + __m128i zeros=_mm_set1_epi8(0); + __m128i shuffle=_mm_set_epi8(8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7); + const int loop=ceil16_bytes(szUnpacked)/sizeof(uint16_t); + __m128i *iter=(__m128i *)in; + + for (int i=0; i < loop; i++) { + __m128i tmp=_mm_shuffle_epi8(_mm_cmpgt_epi8(*iter++,zeros),shuffle); + ((uint16_t *)out)[i]=(uint16_t)_mm_movemask_epi8(tmp); + } +} + +void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc) { + fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); + + if (is_prach_subframe(&eNB->frame_parms, proc->frame_prach,proc->subframe_prach)<=0) + return; + + RU_t *ru; + int aa=0; + int ru_aa; + + for (int i=0; i<eNB->num_RU; i++) { + ru=eNB->RU_list[i]; + + for (ru_aa=0,aa=0; ru_aa<ru->nb_rx; ru_aa++,aa++) { + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + int ce_level; + + for (ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[i]->prach_rxsigF_br[ce_level][ru_aa]; + } + } + + ocp_rx_prach(eNB, + proc, + eNB->RU_list[0], + header->max_preamble, + header->max_preamble_energy, + header->max_preamble_delay, + header->avg_preamble_energy, + proc->frame_prach, + 0, + false + ); + // run PRACH detection for CE-level 0 only for now when br_flag is set + /* fixme: seems not operational and may overwrite regular LTE prach detection + * OAI code can call is sequence + rx_prach(eNB, + eNB->RU_list[0], + header->max_preamble, + header->max_preamble_energy, + header->max_preamble_delay, + header->avg_preamble_energy, + frame, + 0, + true + ); + */ + LOG_D(PHY,"RACH detection index 0: max preamble: %u, energy: %u, delay: %u, avg energy: %u\n", + header->max_preamble[0], + header->max_preamble_energy[0], + header->max_preamble_delay[0], + header->avg_preamble_energy[0] + ); + return; +} + +void prach_eNB_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc) { + fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); + uint16_t *max_preamble=header->max_preamble; + uint16_t *max_preamble_energy=header->max_preamble_energy; + uint16_t *max_preamble_delay=header->max_preamble_delay; + uint16_t *avg_preamble_energy=header->avg_preamble_energy; + int subframe=proc->subframe_prach; + int frame=proc->frame_prach; + // Fixme: not clear why we call twice with "br" and without + int br_flag=0; + + if (br_flag==1) { + int prach_mask; + prach_mask = is_prach_subframe (&eNB->frame_parms, proc->frame_prach_br, proc->subframe_prach_br); + eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; + int ind = 0; + int ce_level = 0; + /* Save for later, it doesn't work + for (int ind=0,ce_level=0;ce_level<4;ce_level++) { + + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[ce_level]==1)&& + (prach_mask&(1<<(1+ce_level)) > 0) && // prach is active and CE level has finished its repetitions + (eNB->prach_vars_br.repetition_number[ce_level]== + eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) { + + */ + + if (eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[0] == 1) { + if ((eNB->prach_energy_counter == 100) && (max_preamble_energy[0] > eNB->measurements.prach_I0 + eNB->prach_DTX_threshold_emtc[0])) { + eNB->UL_INFO.rach_ind_br.rach_indication_body.number_of_preambles++; + eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind]; // + eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; + // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + subframe + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); + eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is + eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1 + ce_level; // CE Level + LOG_I (PHY, "Filling NFAPI indication for RACH %d CELevel %d (mask %x) : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + ind, + ce_level, + prach_mask, + eNB->preamble_list_br[ind].preamble_rel8.timing_advance, + eNB->preamble_list_br[ind].preamble_rel8.preamble, eNB->preamble_list_br[ind].preamble_rel8.rnti, eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type); + } + } + + /* + ind++; + } + } */// ce_level + } else if ((eNB->prach_energy_counter == 100) && + (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) { + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", + eNB->Mod_id, + eNB->CC_id, + frame, + subframe, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + max_preamble_delay[0]); + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 1; + eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = &eNB->preamble_list[0]; + eNB->UL_INFO.rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; + eNB->UL_INFO.rach_ind.header.message_id = NFAPI_RACH_INDICATION; + eNB->UL_INFO.rach_ind.sfn_sf = frame<<4 | subframe; + eNB->preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; + eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; + eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; + eNB->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; + eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // If NFAPI PNF then we need to send the message to the VNF + LOG_D(PHY,"Filling NFAPI indication for RACH : SFN_SF:%d TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf), + eNB->preamble_list[0].preamble_rel8.timing_advance, + eNB->preamble_list[0].preamble_rel8.preamble, + eNB->preamble_list[0].preamble_rel8.rnti, + eNB->preamble_list[0].preamble_rel13.rach_resource_type); + oai_nfapi_rach_ind(&eNB->UL_INFO.rach_ind); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 0; + } + + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + } // max_preamble_energy > prach_I0 + 100 + else { + eNB->measurements.prach_I0 = ((eNB->measurements.prach_I0*900)>>10) + ((avg_preamble_energy[0]*124)>>10); + + if (eNB->prach_energy_counter < 100) + eNB->prach_energy_counter++; + } +} + +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, + uint16_t rnti, + int32_t stat) { + static int current_fsf=-1; + int fsf=frame*16+subframe; + uint8_t *bufferZone=eNB->FS6bufferZone; + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + if ( current_fsf != fsf ) { + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_uci_t); + hULUEuci(newUDPheader)->type=fs6ULcch; + hULUEuci(newUDPheader)->nb_active_ue=0; + } else + for (int i=0; i < FirstUDPheader->nbBlocks-1; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + LOG_D(PHY,"FS6 du, block: %d: adding ul harq/sr: %d, rnti: %d, ueid: %d\n", + curBlock, type, rnti, UEid); + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(newUDPheader)+1); + tmp+=hULUEuci(newUDPheader)->nb_active_ue; + tmp->type=type; + tmp->UEid=UEid; + tmp->frame=frame; + tmp->subframe=subframe; + + if (uci != NULL) + memcpy(&tmp->uci, uci, sizeof(*uci)); + else + tmp->uci.ue_id=0xFFFF; + + if (harq_ack != NULL) + memcpy(tmp->harq_ack, harq_ack, 4); + + tmp->tdd_mapping_mode=tdd_mapping_mode; + tmp->tdd_multiplexing_mask=tdd_multiplexing_mask; + tmp->n0_subband_power_dB=eNB->measurements.n0_subband_power_dB[0][0]; + tmp->rnti=rnti; + tmp->stat=stat; + hULUEuci(newUDPheader)->nb_active_ue++; + newUDPheader->contentBytes+=sizeof(fs6_ul_uespec_uci_element_t); +} + + +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + uint8_t *bufferZone=eNB->FS6bufferZone; + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_t) + dataLen; + hULUE(newUDPheader)->type=fs6ULsch; + hULUE(newUDPheader)->UE_id=UE_id; + hULUE(newUDPheader)->harq_id=harq_pid; + memcpy(hULUE(newUDPheader)->ulsch_power, + eNB->pusch_vars[UE_id]->ulsch_power, + sizeof(int)*2); + hULUE(newUDPheader)->cqi_crc_status=eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status; + hULUE(newUDPheader)->O_ACK=eNB->ulsch[UE_id]->harq_processes[harq_pid]->O_ACK; + memcpy(hULUE(newUDPheader)->o_ACK, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK, + sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK)); + hULUE(newUDPheader)->ta=lte_est_timing_advance_pusch(eNB, UE_id); + hULUE(newUDPheader)->segment=segmentID; + memcpy(hULUE(newUDPheader)->o, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o, + sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o)); + memcpy(hULUE(newUDPheader)+1, data, dataLen); + hULUE(newUDPheader)->segLen=dataLen; + hULUE(newUDPheader)->r_offset=r_offset; + hULUE(newUDPheader)->G=eNB->ulsch[UE_id]->harq_processes[harq_pid]->G; +} + +void pusch_procedures_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { + uint32_t harq_pid; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; + + if (ulsch->ue_type > NOCE) + harq_pid = 0; + else + harq_pid= subframe2harq_pid(&eNB->frame_parms,frame,subframe); + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) + LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d active: %d handled:%d]\n", + i, harq_pid, frame,subframe,i,ulsch->rnti, + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->status, ulsch_harq->handled); + + if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + ((ulsch_harq->frame == frame) || (ulsch_harq->repetition_number >1) ) && + ((ulsch_harq->subframe == subframe) || (ulsch_harq->repetition_number >1) ) && + (ulsch_harq->handled == 0)) { + // UE has ULSCH scheduling + for (int rb=0; + rb<=ulsch_harq->nb_rb; + rb++) { + int rb2 = rb+ulsch_harq->first_rb; + eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + + LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", + eNB->Mod_id, frame, subframe, i); + uint8_t nPRS= fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]; + ulsch->cyclicShift = (ulsch_harq->n_DMRS2 + + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + + nPRS)%12; + AssertFatal(ulsch_harq->TBS>0,"illegal TBS %d\n",ulsch_harq->TBS); + LOG_D(PHY, + "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, Qm %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, ), O_ACK %d, beta_cqi %d \n", + eNB->Mod_id,harq_pid,frame,subframe, + ulsch_harq->dci_alloc, + ulsch_harq->rar_alloc, + ulsch_harq->round, + ulsch_harq->first_rb, + ulsch_harq->nb_rb, + ulsch_harq->Qm, + ulsch_harq->TBS, + ulsch_harq->rvidx, + ulsch->cyclicShift, + ulsch_harq->n_DMRS2, + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, + ulsch_harq->O_ACK, + ulsch->beta_offset_cqi_times8); + start_meas(&eNB->ulsch_demodulation_stats); + eNB->FS6bufferZone=bufferZone; + rx_ulsch(eNB, proc, i); + stop_meas(&eNB->ulsch_demodulation_stats); + // TBD: add datablock for transmission + start_meas(&eNB->ulsch_decoding_stats); + ulsch_decoding(eNB,proc, + i, + 0, // control_only_flag + ulsch_harq->V_UL_DAI, + ulsch_harq->nb_rb>20 ? 1 : 0); + stop_meas(&eNB->ulsch_decoding_stats); + } + } +} + +void phy_procedures_eNB_uespec_RX_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { + //RX processing for ue-specific resources + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + /* TODO: use correct rxdata */ + + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; + + LOG_D (PHY, "[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n", eNB->Mod_id, frame, subframe); + eNB->rb_mask_ul[0] = 0; + eNB->rb_mask_ul[1] = 0; + eNB->rb_mask_ul[2] = 0; + eNB->rb_mask_ul[3] = 0; + // Fix me here, these should be locked + eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus = 0; + eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs = 0; + // Call SRS first since all others depend on presence of SRS or lack thereof + srs_procedures (eNB, proc); + eNB->first_run_I0_measurements = 0; + uci_procedures (eNB, proc); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // If PNF or monolithic + pusch_procedures_tosplit(bufferZone, bufSize, eNB,proc); + } + + lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements); + int min_I0=1000,max_I0=0; + + if ((frame==0) && (subframe==4)) { + for (int i=0; i<eNB->frame_parms.N_RB_UL; i++) { + if (i==(eNB->frame_parms.N_RB_UL>>1) - 1) i+=2; + + if (eNB->measurements.n0_subband_power_tot_dB[i]<min_I0) + min_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; + + if (eNB->measurements.n0_subband_power_tot_dB[i]>max_I0) + max_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; + } + + LOG_I (PHY, "max_I0 %d, min_I0 %d\n", max_I0, min_I0); + } + + return; +} + + +void fill_rx_indication_from_split(uint8_t *bufferZone, PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe, ul_propagation_t *ul_propa) { + nfapi_rx_indication_pdu_t *pdu; + int timing_advance_update; + uint32_t harq_pid; + + if (eNB->ulsch[UE_id]->ue_type > 0) + harq_pid = 0; + else + harq_pid = subframe2harq_pid (&eNB->frame_parms, + frame, subframe); + + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rx_ind.sfn_sf = frame<<4| subframe; + eNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG; + pdu = &eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus]; + // pdu->rx_ue_information.handle = eNB->ulsch[UE_id]->handle; + pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; + pdu->rx_ue_information.rnti = eNB->ulsch[UE_id]->rnti; + pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; + pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; + pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->decodedBytes; + // estimate timing advance for MAC + timing_advance_update = ul_propa[UE_id].ta; + + // if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} + // if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} + switch (eNB->frame_parms.N_RB_DL) { + case 6: /* nothing to do */ + break; + + case 15: + timing_advance_update /= 2; + break; + + case 25: + timing_advance_update /= 4; + break; + + case 50: + timing_advance_update /= 8; + break; + + case 75: + timing_advance_update /= 12; + break; + + case 100: + timing_advance_update /= 16; + break; + + default: + abort (); + } + + // put timing advance command in 0..63 range + timing_advance_update += 31; + + if (timing_advance_update < 0) + timing_advance_update = 0; + + if (timing_advance_update > 63) + timing_advance_update = 63; + + pdu->rx_indication_rel8.timing_advance = timing_advance_update; + // estimate UL_CQI for MAC (from antenna port 0 only) + int SNRtimes10 = dB_fixed_times10(eNB->pusch_vars[UE_id]->ulsch_power[0]) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; + + if (SNRtimes10 < -640) + pdu->rx_indication_rel8.ul_cqi = 0; + else if (SNRtimes10 > 635) + pdu->rx_indication_rel8.ul_cqi = 255; + else + pdu->rx_indication_rel8.ul_cqi = (640 + SNRtimes10) / 5; + + LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d), timing_advance %d (update %d)\n", + harq_pid,frame,subframe,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,pdu->rx_indication_rel8.timing_advance, + timing_advance_update); + eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++; + eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe; + pthread_mutex_unlock(&eNB->UL_INFO_mutex); +} + +void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, ul_propagation_t *ul_propa) { + //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + uint32_t harq_pid; + uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); + + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; + + if (ulsch->ue_type > NOCE) harq_pid = 0; + else harq_pid=harq_pid0; + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) + LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", + i, harq_pid, frame,subframe,i,ulsch->rnti, + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + + if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 0)) { + // UE has ULSCH scheduling + for (int rb=0; + rb<=ulsch_harq->nb_rb; + rb++) { + int rb2 = rb+ulsch_harq->first_rb; + eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + + start_meas(&eNB->ulsch_decoding_stats); + // This is a new packet, so compute quantities regarding segmentation + ulsch_harq->B = ulsch_harq->TBS+24; + lte_segmentation(NULL, + NULL, + ulsch_harq->B, + &ulsch_harq->C, + &ulsch_harq->Cplus, + &ulsch_harq->Cminus, + &ulsch_harq->Kplus, + &ulsch_harq->Kminus, + &ulsch_harq->F); + ulsch_decoding_data(eNB, proc, i, harq_pid, + ulsch_harq->nb_rb>20 ? 1 : 0); + stop_meas(&eNB->ulsch_decoding_stats); + } // if ((ulsch) && + // (ulsch->rnti>0) && + // (ulsch_harq->status == ACTIVE)) + else if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 1)) { + // this harq process is stale, kill it, this 1024 frames later (10s), consider reducing that + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << harq_pid); + LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); + } + } // for (i=0; i<NUMBER_OF_UE_MAX; i++) + + while (proc->nbDecode > 0) { + notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool); + postDecode(proc, req); + delNotifiedFIFO_elt(req); + } +} + +void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagation_t *ul_propa) { + void *bufPtr=bufferZone; + + for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks + if ( ((commonUDP_t *)bufPtr)->contentBytes > sizeof(fs6_ul_t) ) { + int type=hULUE(bufPtr)->type; + + if ( type == fs6ULsch) { + LTE_eNB_ULSCH_t *ulsch =eNB->ulsch[hULUE(bufPtr)->UE_id]; + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hULUE(bufPtr)->harq_id]; + memcpy(ulsch_harq->eUL+hULUE(bufPtr)->r_offset, + hULUE(bufPtr)+1, + hULUE(bufPtr)->segLen); + memcpy(eNB->pusch_vars[hULUE(bufPtr)->UE_id]->ulsch_power, + hULUE(bufPtr)->ulsch_power, + sizeof(int)*2); + ulsch_harq->G=hULUE(bufPtr)->G; + ulsch_harq->cqi_crc_status=hULUE(bufPtr)->cqi_crc_status; + //ulsch_harq->O_ACK= hULUE(bufPtr)->O_ACK; + memcpy(ulsch_harq->o_ACK, hULUE(bufPtr)->o_ACK, + sizeof(ulsch_harq->o_ACK)); + memcpy(ulsch_harq->o,hULUE(bufPtr)->o, sizeof(ulsch_harq->o)); + ul_propa[hULUE(bufPtr)->UE_id].ta=hULUE(bufPtr)->ta; + LOG_D(PHY,"Received ulsch data for: rnti:%x, cqi_crc_status %d O_ACK: %d, segment: %d, seglen: %d \n", + ulsch->rnti, ulsch_harq->cqi_crc_status, ulsch_harq->O_ACK,hULUE(bufPtr)->segment, hULUE(bufPtr)->segLen); + } else if ( type == fs6ULcch ) { + int nb_uci=hULUEuci(bufPtr)->nb_active_ue; + fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); + + for (int j=0; j < nb_uci ; j++) { + LOG_D(PHY,"FS6 cu, block: %d/%d: received ul harq/sr: %d, rnti: %d, ueid: %d\n", + i, j, type, tmp->rnti, tmp->UEid); + eNB->measurements.n0_subband_power_dB[0][0]=tmp->n0_subband_power_dB; + + if (tmp->uci.ue_id != 0xFFFF) + memcpy(&eNB->uci_vars[tmp->UEid],&tmp->uci, sizeof(tmp->uci)); + + if ( tmp->type == fs6ULindicationHarq ) + fill_uci_harq_indication (tmp->UEid, eNB, &eNB->uci_vars[tmp->UEid], + tmp->frame, tmp->subframe, tmp->harq_ack, + tmp->tdd_mapping_mode, tmp->tdd_multiplexing_mask); + else if ( tmp->type == fs6ULindicationSr ) + fill_sr_indication(tmp->UEid, eNB,tmp->rnti,tmp->frame,tmp->subframe,tmp->stat); + else + LOG_E(PHY, "Split FS6: impossible UL harq type\n"); + + tmp++; + } + } else + LOG_E(PHY, "FS6 ul packet type impossible\n" ); + } + + bufPtr+=alignedSize(bufPtr); + } +} + +void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc) { + // The configuration arrived in Dl, so we can extract the UL data + ul_propagation_t ul_propa[NUMBER_OF_UE_MAX]; + recvFs6Ul(bufferZone, nbBlocks, eNB, ul_propa); + + // dirty memory allocation in OAI... + for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) + if ( eNB->uci_vars[i].frame == proc->frame_rx && + eNB->uci_vars[i].subframe == proc->subframe_rx ) + eNB->uci_vars[i].active=0; + + pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB, proc, ul_propa); +} + +void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, int subframe) { + void *bufPtr=bufferZone; + + for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks + if ( ((commonUDP_t *)bufPtr)->contentBytes > sizeof(fs6_dl_t) ) { + int type=hDLUE(bufPtr)->type; + + if ( type == fs6DlConfig) { + int curUE=hDLUE(bufPtr)->UE_id; + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[curUE][0]; + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[hDLUE(bufPtr)->harq_pid]; +#ifdef PHY_TX_THREAD + dlsch0->active[subframe] = 1; +#else + dlsch0->active = 1; +#endif + dlsch0->harq_ids[frame%2][subframe]=hDLUE(bufPtr)->harq_pid; + dlsch0->rnti=hDLUE(bufPtr)->rnti; + dlsch0->sqrt_rho_a=hDLUE(bufPtr)->sqrt_rho_a; + dlsch0->sqrt_rho_b=hDLUE(bufPtr)->sqrt_rho_b; + dlsch_harq->nb_rb=hDLUE(bufPtr)->nb_rb; + memcpy(dlsch_harq->rb_alloc, hDLUE(bufPtr)->rb_alloc, sizeof(hDLUE(bufPtr)->rb_alloc)); + dlsch_harq->Qm=hDLUE(bufPtr)->Qm; + dlsch_harq->Nl=hDLUE(bufPtr)->Nl; + dlsch_harq->pdsch_start=hDLUE(bufPtr)->pdsch_start; +#ifdef PHY_TX_THREAD + dlsch_harq->CEmode = hDLUE(bufPtr)->CEmode; + dlsch_harq->i0=hDLUE(bufPtr)->i0; + dlsch_harq->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; +#else + dlsch0->i0=hDLUE(bufPtr)->i0; + dlsch0->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; +#endif + fs6Dlunpack(dlsch_harq->eDL, + hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); + LOG_D(PHY,"received %d bits, in harq id: %di fsf: %d.%d, sum %d\n", + hDLUE(bufPtr)->dataLen, hDLUE(bufPtr)->harq_pid, frame, subframe, sum(dlsch_harq->eDL, hDLUE(bufPtr)->dataLen)); + } else if (type == fs6UlConfig) { + int nbUE=(((commonUDP_t *)bufPtr)->contentBytes - sizeof(fs6_dl_t)) / sizeof( fs6_dl_ulsched_t ) ; +#define cpyVal(a) memcpy(&ulsch_harq->a,&hTxULUE(bufPtr)->a, sizeof(ulsch_harq->a)) + + for ( int i=0; i < nbUE; i++ ) { + int curUE=hTxULUE(bufPtr)->UE_id; + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[curUE]; + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hTxULUE(bufPtr)->harq_pid]; + ulsch->ue_type=hTxULUE(bufPtr)->ue_type; + ulsch->harq_mask=hTxULUE(bufPtr)->harq_mask; + ulsch->Mlimit=hTxULUE(bufPtr)->Mlimit; + ulsch->max_turbo_iterations=hTxULUE(bufPtr)->max_turbo_iterations; + ulsch->bundling=hTxULUE(bufPtr)->bundling; + ulsch->beta_offset_cqi_times8=hTxULUE(bufPtr)->beta_offset_cqi_times8; + ulsch->beta_offset_ri_times8=hTxULUE(bufPtr)->beta_offset_ri_times8; + ulsch->beta_offset_harqack_times8=hTxULUE(bufPtr)->beta_offset_harqack_times8; + ulsch->Msg3_active=hTxULUE(bufPtr)->Msg3_active; + ulsch->cyclicShift=hTxULUE(bufPtr)->cyclicShift; + ulsch->cooperation_flag=hTxULUE(bufPtr)->cooperation_flag; + ulsch->num_active_cba_groups=hTxULUE(bufPtr)->num_active_cba_groups; + memcpy(ulsch->cba_rnti,hTxULUE(bufPtr)->cba_rnti,sizeof(ulsch->cba_rnti));//NUM_MAX_CBA_GROUP]; + ulsch->rnti=hTxULUE(bufPtr)->rnti; + ulsch_harq->nb_rb=hTxULUE(bufPtr)->nb_rb; + ulsch_harq->handled=0; + ulsch_harq->status = ACTIVE; + ulsch_harq->frame = frame; + ulsch_harq->subframe = subframe; + ulsch_harq->first_rb=hTxULUE(bufPtr)->first_rb; + ulsch_harq->O_RI=hTxULUE(bufPtr)->O_RI; + ulsch_harq->Or1=hTxULUE(bufPtr)->Or1; + ulsch_harq->Msc_initial=hTxULUE(bufPtr)->Msc_initial; + ulsch_harq->Nsymb_initial=hTxULUE(bufPtr)->Nsymb_initial; + ulsch_harq->V_UL_DAI=hTxULUE(bufPtr)->V_UL_DAI; + ulsch_harq->Qm=hTxULUE(bufPtr)->Qm; + ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; + ulsch_harq->TBS=hTxULUE(bufPtr)->TBS; + ulsch_harq->Nsymb_pusch=hTxULUE(bufPtr)->Nsymb_pusch; + cpyVal(dci_alloc); + cpyVal(rar_alloc); + cpyVal(status); + cpyVal(Msg3_flag); + cpyVal(phich_active); + cpyVal(phich_ACK); + cpyVal(previous_first_rb); + cpyVal(B); + cpyVal(G); + //cpyVal(o); + cpyVal(uci_format); + cpyVal(Or2); + cpyVal(o_RI); + cpyVal(o_ACK); + cpyVal(O_ACK); + //cpyVal(q); + cpyVal(o_RCC); + cpyVal(q_ACK); + cpyVal(q_RI); + cpyVal(RTC); + cpyVal(ndi); + cpyVal(round); + cpyVal(rvidx); + cpyVal(Nl); + cpyVal(n_DMRS); + cpyVal(previous_n_DMRS); + cpyVal(n_DMRS2); + cpyVal(delta_TF); + cpyVal(repetition_number ); + cpyVal(total_number_of_repetitions); + LOG_D(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d, O_ACK: %d\n", + ulsch->rnti, frame, subframe, ulsch_harq->O_ACK); + } + } else if ( type == fs6ULConfigCCH ) { + fs6_dl_uespec_ulcch_element_t *tmp=(fs6_dl_uespec_ulcch_element_t *)(hTxULcch(bufPtr)+1); + + for (int i=0; i< hTxULcch(bufPtr)->nb_active_ue; i++ ) + memcpy(&eNB->uci_vars[tmp->UE_id], &tmp->cch_vars, sizeof(tmp->cch_vars)); + } else + LOG_E(PHY, "Impossible block in fs6 DL\n"); + } + + bufPtr+=alignedSize(bufPtr); + } +} + +void phy_procedures_eNB_TX_fromsplit(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int subframe=proc->subframe_tx; + int frame=proc->frame_tx; + //LTE_UL_eNB_HARQ_t *ulsch_harq; + eNB->pdcch_vars[subframe&1].num_pdcch_symbols=hDL(bufferZone)->num_pdcch_symbols; + eNB->pdcch_vars[subframe&1].num_dci=hDL(bufferZone)->num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = hDL(bufferZone)->num_mdci; + eNB->pbch_configured=true; + memcpy(eNB->pbch_pdu,hDL(bufferZone)->pbch_pdu, 4); + + // Remove all scheduled DL, we will populate from the CU sending + for (int UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; + + if ( dlsch0 && dlsch0->rnti>0 ) { +#ifdef PHY_TX_THREAD + dlsch0->active[subframe] = 0; +#else + dlsch0->active = 0; +#endif + } + } + + rcvFs6DL(bufferZone, nbBlocks, eNB, frame, subframe); + + if (do_meas==1) { + start_meas(&eNB->phy_proc_tx); + start_meas(&eNB->dlsch_common_and_dci); + } + + // clear the transmit data array for the current subframe + for (int aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { + memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti)], + 0, fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + if (is_pmch_subframe(frame,subframe,fp)) { + pmch_procedures(eNB,proc); + } else { + // this is not a pmch subframe, so generate PSS/SSS/PBCH + common_signal_procedures(eNB,frame, subframe); + } + } + + // clear previous allocation information for all UEs + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + //if (eNB->dlsch[i][0]) + //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + for (int i=0; i< hDL(bufferZone)->num_dci; i++) + eNB->pdcch_vars[subframe&1].dci_alloc[i]=hDL(bufferZone)->dci_alloc[i]; + + LOG_D (PHY, "Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %" PRIu8 ")\n", frame, subframe, hDL(bufferZone)->num_dci); + generate_dci_top(hDL(bufferZone)->num_pdcch_symbols, + hDL(bufferZone)->num_dci, + &eNB->pdcch_vars[subframe&1].dci_alloc[0], + 0, + hDL(bufferZone)->amp, + fp, + eNB->common_vars.txdataF, + subframe); + + if (num_mdci > 0) { + LOG_D (PHY, "[eNB %" PRIu8 "] Frame %d, subframe %d: Calling generate_mdci_top (mpdcch) (num_dci %" PRIu8 ")\n", eNB->Mod_id, frame, subframe, num_mdci); + generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF); + } + } + + for (int UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; + LTE_eNB_DLSCH_t *dlsch1 = eNB->dlsch[UE_id][1]; + + if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 1) +#else + (dlsch0->active == 1) +#endif + ) { + uint64_t sum=0; + + for ( int i= subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti); + i< (subframe+1) * fp->ofdm_symbol_size * (fp->symbols_per_tti); + i++) + sum+=((int32_t *)(eNB->common_vars.txdataF[0]))[i]; + + LOG_D(PHY,"frame: %d, subframe: %d, sum of dlsch mod v1: %lx\n", frame, subframe, sum); + int harq_pid=dlsch0->harq_ids[frame%2][subframe]; + pdsch_procedures(eNB, + proc, + harq_pid, + dlsch0, + dlsch1); + } + } + + eNB->phich_vars[subframe&1]=hDL(bufferZone)->phich_vars; + generate_phich_top(eNB, + proc, + AMP); +} + +#define cpyToDu(a) hTxULUE(newUDPheader)->a=ulsch->a +#define cpyToDuHarq(a) hTxULUE(newUDPheader)->a=ulsch_harq->a +#define memcpyToDuHarq(a) memcpy(&hTxULUE(newUDPheader)->a,&ulsch_harq->a, sizeof(ulsch_harq->a)); + +void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE_eNB_ULSCH_t *ulsch, int frame, int subframe) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_ulsched_t); + // We skip the fs6 DL header, that is populated by caller + // This header will be duplicated during sending + hTxULUE(newUDPheader)->type=fs6UlConfig; + hTxULUE(newUDPheader)->UE_id=curUE; + int harq_pid; + + if (ulsch->ue_type > NOCE) + // LTE-M case + harq_pid = 0; + else + harq_pid = subframe2harq_pid(fp, frame, subframe); + + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[harq_pid]; + hTxULUE(newUDPheader)->harq_pid=harq_pid; + cpyToDu(ue_type); + cpyToDu(harq_mask); + cpyToDu(Mlimit); + cpyToDu(max_turbo_iterations); + cpyToDu(bundling); + cpyToDu(beta_offset_cqi_times8); + cpyToDu(beta_offset_ri_times8); + cpyToDu(beta_offset_harqack_times8); + cpyToDu(Msg3_active); + cpyToDu(cyclicShift); + cpyToDu(cooperation_flag); + cpyToDu(num_active_cba_groups); + memcpy(hTxULUE(newUDPheader)->cba_rnti,ulsch->cba_rnti,sizeof(ulsch->cba_rnti));//NUM_MAX_CBA_GROUP]; + cpyToDu(rnti); + cpyToDuHarq(nb_rb); + cpyToDuHarq(Msc_initial); + cpyToDuHarq(Nsymb_initial); + cpyToDuHarq(O_RI); + cpyToDuHarq(Or1); + cpyToDuHarq(first_rb); + cpyToDuHarq(V_UL_DAI); + cpyToDuHarq(Qm); + cpyToDuHarq(srs_active); + cpyToDuHarq(TBS); + cpyToDuHarq(Nsymb_pusch); + memcpyToDuHarq(dci_alloc); + memcpyToDuHarq(rar_alloc); + memcpyToDuHarq(status); + memcpyToDuHarq(Msg3_flag); + memcpyToDuHarq(phich_active); + memcpyToDuHarq(phich_ACK); + memcpyToDuHarq(previous_first_rb); + memcpyToDuHarq(B); + memcpyToDuHarq(G); + //memcpyToDuHarq(o); + memcpyToDuHarq(uci_format); + memcpyToDuHarq(Or2); + memcpyToDuHarq(o_RI); + memcpyToDuHarq(o_ACK); + memcpyToDuHarq(O_ACK); + //memcpyToDuHarq(q); + memcpyToDuHarq(o_RCC); + memcpyToDuHarq(q_ACK); + memcpyToDuHarq(q_RI); + memcpyToDuHarq(RTC); + memcpyToDuHarq(ndi); + memcpyToDuHarq(round); + memcpyToDuHarq(rvidx); + memcpyToDuHarq(Nl); + memcpyToDuHarq(n_DMRS); + memcpyToDuHarq(previous_n_DMRS); + memcpyToDuHarq(n_DMRS2); + memcpyToDuHarq(delta_TF); + memcpyToDuHarq(repetition_number ); + memcpyToDuHarq(total_number_of_repetitions); + LOG_D(PHY,"Added request to perform ulsch for: rnti:%x, fsf: %d/%d\n", ulsch->rnti, frame, subframe); +} + +void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_t harq_pid, LTE_eNB_DLSCH_t *dlsch0, LTE_DL_eNB_HARQ_t *harqData, int frame, int subframe) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + int UEdataLen= get_G(fp, + harqData->nb_rb, + harqData->rb_alloc, + harqData->Qm, + harqData->Nl, + harqData->pdsch_start, + frame,subframe, + 0); + AssertFatal(firstFreeByte+ceil16_bytes(UEdataLen)+sizeof(fs6_dl_t) <= bufferZone+FS6_BUF_SIZE, ""); + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) + ceil16_bytes(UEdataLen); + // We skip the fs6 DL header, that is populated by caller + // This header will be duplicated during sending + hDLUE(newUDPheader)->type=fs6DlConfig; + hDLUE(newUDPheader)->UE_id=UE_id; + hDLUE(newUDPheader)->harq_pid=harq_pid; + hDLUE(newUDPheader)->rnti=dlsch0->rnti; + hDLUE(newUDPheader)->sqrt_rho_a=dlsch0->sqrt_rho_a; + hDLUE(newUDPheader)->sqrt_rho_b=dlsch0->sqrt_rho_b; + hDLUE(newUDPheader)->nb_rb=harqData->nb_rb; + memcpy(hDLUE(newUDPheader)->rb_alloc, harqData->rb_alloc, sizeof(harqData->rb_alloc)); + hDLUE(newUDPheader)->Qm=harqData->Qm; + hDLUE(newUDPheader)->Nl=harqData->Nl; + hDLUE(newUDPheader)->pdsch_start=harqData->pdsch_start; +#ifdef PHY_TX_THREAD + hDLUE(newUDPheader)->CEmode=harqData->CEmode; + hDLUE(newUDPheader)->i0=harqData->i0; + hDLUE(newUDPheader)->sib1_br_flag=harqData->sib1_br_flag; +#else + hDLUE(newUDPheader)->i0=dlsch0->i0; + hDLUE(newUDPheader)->sib1_br_flag=dlsch0->sib1_br_flag; +#endif + hDLUE(newUDPheader)->dataLen=UEdataLen; + fs6Dlpack(hDLUE(newUDPheader)+1, harqData->eDL, UEdataLen); + LOG_D(PHY,"sending %d bits, in harq id: %di fsf: %d.%d, sum %d\n", + UEdataLen, harq_pid, frame, subframe, sum(harqData->eDL, UEdataLen)); + //for (int i=0; i < UEdataLen; i++) + //LOG_D(PHY,"buffer ei[%d]:%hhx\n", i, ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); +} + +void appendFs6DLUEcch(uint8_t *bufferZone, PHY_VARS_eNB *eNB, int frame, int subframe) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + bool first_UE=true; + + for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) { + LTE_eNB_UCI *uci = &(eNB->uci_vars[i]); + + if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) { + LOG_D(PHY,"Frame %d, subframe %d: adding uci procedures (type %d) for %d \n", + frame, + subframe, + uci->type, + i); + + if ( first_UE ) { + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_ulcch_t); + hTxULcch(newUDPheader)->type=fs6ULConfigCCH; + hTxULcch(newUDPheader)->nb_active_ue=0; + first_UE=false; + } + + fs6_dl_uespec_ulcch_element_t *tmp=(fs6_dl_uespec_ulcch_element_t *)(hTxULcch(newUDPheader)+1); + tmp+=hTxULcch(newUDPheader)->nb_active_ue; + tmp->UE_id=i; + memcpy(&tmp->cch_vars,uci, sizeof(tmp->cch_vars)); + hTxULcch(newUDPheader)->nb_active_ue++; + newUDPheader->contentBytes+=sizeof(fs6_dl_uespec_ulcch_element_t); + } + } +} + +void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { + int frame=proc->frame_tx; + int subframe=proc->subframe_tx; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + + if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL)) { + LOG_W(HW,"no sending in eNB_TX\n"); + return; + } + + // clear previous allocation information for all UEs + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + //if (eNB->dlsch[i][0]) + //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + } + + // Send to DU the UL scheduled for future UL subframe + for (int i=0; i<NUMBER_OF_UE_MAX; i++) { + int harq_pid; + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; + + if (ulsch->ue_type > NOCE) + harq_pid = 0; + else + harq_pid= subframe2harq_pid(&eNB->frame_parms,frame,subframe); + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) { + LOG_D(PHY,"check in UL scheduled harq %d: rnti %d, tx frame %d/%d, ulsch: %d, %d/%d (handled: %d)\n", + harq_pid, ulsch->rnti, frame, subframe, ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + } + + for (int k=0; k<8; k++) { + ulsch_harq = ulsch->harq_processes[k]; + + if (ulsch && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 0) + ) + appendFs6TxULUE(bufferZone, + fp, + i, + ulsch, + frame, + subframe + ); + } + } + + appendFs6DLUEcch(bufferZone, + eNB, + frame, + subframe + ); + uint8_t num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; + uint8_t num_dci = eNB->pdcch_vars[subframe&1].num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; + memcpy(hDL(bufferZone)->pbch_pdu,eNB->pbch_pdu,4); + + if ( num_dci <= 8 ) + LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); + else { + LOG_E(PHY, "Num dci too large for current FS6 implementation, reducing to 8 dci (was %d)\n", num_dci); + num_dci=8; + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + hDL(bufferZone)->num_pdcch_symbols=num_pdcch_symbols; + hDL(bufferZone)->num_dci=num_dci; + hDL(bufferZone)->num_mdci=num_mdci; + hDL(bufferZone)->amp=AMP; + + for (int i=0; i< hDL(bufferZone)->num_dci; i++) + hDL(bufferZone)->dci_alloc[i]=eNB->pdcch_vars[subframe&1].dci_alloc[i]; + + LOG_D(PHY, "pbch configured: %d\n", eNB->pbch_configured); + } + + if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci); + + if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); + + for (int UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; + + if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 1) +#else + (dlsch0->active == 1) +#endif + ) { + // get harq_pid + int harq_pid = dlsch0->harq_ids[frame%2][subframe]; + AssertFatal(harq_pid>=0,"harq_pid is negative\n"); + + if (harq_pid>=8) { + if (dlsch0->ue_type == NOCE) + LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x [ %1d.%1d.%1d.%1d.%1d.%1d.%1d.%1d\n", harq_pid,UE_id,frame,subframe,dlsch0->rnti, + dlsch0->harq_ids[frame%2][0], + dlsch0->harq_ids[frame%2][1], + dlsch0->harq_ids[frame%2][2], + dlsch0->harq_ids[frame%2][3], + dlsch0->harq_ids[frame%2][4], + dlsch0->harq_ids[frame%2][5], + dlsch0->harq_ids[frame%2][6], + dlsch0->harq_ids[frame%2][7]); + } else { + if (dlsch_procedures(eNB, + proc, + harq_pid, + dlsch0, + &eNB->UE_stats[(uint32_t)UE_id])) { + // data in: dlsch0 harq_processes[harq_pid]->e + /* length + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + dlsch_harq->Qm, + dlsch_harq->Nl, + dlsch_harq->pdsch_start, + frame,subframe, + 0) + need harq_pid + */ + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[harq_pid]; + appendFs6DLUE(bufferZone, + fp, + UE_id, + harq_pid, + dlsch0, + dlsch_harq, + frame, + subframe + ); + } + } + } else if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 0) +#else + (dlsch0->active == 0) +#endif + ) { + // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) + //dlsch0->subframe_tx[subframe]=0; + } + } + + hDL(bufferZone)->phich_vars=eNB->phich_vars[subframe&1]; + + if (do_meas==1) stop_meas(&eNB->dlsch_ue_specific); + + if (do_meas==1) stop_meas(&eNB->phy_proc_tx); + + // MBMS is not working in OAI + if (hDL(bufferZone)->num_mdci) abort(); + + return; +} + +void *DL_du_fs6(void *arg) { + RU_t *ru=(RU_t *)arg; + static uint64_t lastTS; + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + initStaticTime(begingWait); + initStaticTime(begingProcessing); + initRefTimes(fullLoop); + initRefTimes(DuHigh); + initRefTimes(DuLow); + initRefTimes(transportTime); + + while (1) { + for (int i=0; i<ru->num_eNB; i++) { + initBufferZone(bufferZone); + pickStaticTime(begingWait); + int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); + updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait CU"); + + if (nb_blocks > 0) { + if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti < hUDP(bufferZone)->timestamp) { + LOG_E(HW,"Missed a subframe: expecting: %lu, received %lu\n", + lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, + hUDP(bufferZone)->timestamp); + } else if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti > hUDP(bufferZone)->timestamp) { + LOG_E(HW,"Received a subframe in past time from CU (dropping it): expecting: %lu, received %lu\n", + lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, + hUDP(bufferZone)->timestamp); + } + + pickStaticTime(begingProcessing); + lastTS=hUDP(bufferZone)->timestamp; + setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1proc); + measTransportTime(hDL(bufferZone)->DuClock, hDL(bufferZone)->CuSpentMicroSec, + &transportTime, 1000, false, "Transport time, to CU + from CU for one subframe"); + phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1proc, 1); + updateTimesReset(begingProcessing, &DuHigh, 1000, false, "DU high layer1 processing for DL"); + } else + LOG_E(PHY,"DL not received for subframe\n"); + } + + pickStaticTime(begingProcessing); + feptx_prec(ru, L1proc.frame_tx,L1proc.subframe_tx ); + feptx_ofdm(ru, L1proc.frame_tx,L1proc.subframe_tx ); + ocp_tx_rf(ru, &L1proc); + updateTimesReset(begingProcessing, &DuLow, 1000, false, "DU low layer1 processing for DL"); + + if ( IS_SOFTMODEM_RFSIM ) + return NULL; + } + + return NULL; +} + +void UL_du_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { + initStaticTime(begingWait); + initRefTimes(fullLoop); + pickStaticTime(begingWait); + rx_rf(ru, proc); + updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait USRP"); + // front end processing: convert from time domain to frequency domain + // fills rxdataF buffer + fep_full(ru, proc->subframe_rx); + // Fixme: datamodel issue + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + + if (NFAPI_MODE==NFAPI_MODE_PNF) { + // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick + //add_subframe(&frame, &subframe, 4); + //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); + oai_subframe_ind(proc->frame_rx, proc->subframe_rx); + } + + initBufferZone(bufferZone); + hUDP(bufferZone)->timestamp=proc->timestamp_rx; + prach_eNB_tosplit(bufferZone, FS6_BUF_SIZE, eNB, proc ); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX_tosplit(bufferZone, FS6_BUF_SIZE, eNB, proc ); + } + + if (hUDP(bufferZone)->nbBlocks==0) { + hUDP(bufferZone)->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) + hUDP(bufferZone)->blockID=0; + hUDP(bufferZone)->contentBytes=sizeof(fs6_ul_t); + } + + for (int i=0; i<ru->num_eNB; i++) { + sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_ul_t), CTsentDUv0); + } +} + +void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t DuClock, uint64_t startCycle) { + initRefTimes(CUprocessing); + // Fixme: datamodel issue + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.frame = proc->frame_rx; + eNB->UL_INFO.subframe = proc->subframe_rx; + eNB->UL_INFO.module_id = eNB->Mod_id; + eNB->UL_INFO.CC_id = eNB->CC_id; + eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + initBufferZone(bufferZone); + phy_procedures_eNB_TX_tosplit(bufferZone, eNB, proc, 1, bufferZone, FS6_BUF_SIZE); + hUDP(bufferZone)->timestamp=proc->timestamp_tx; + + if (hUDP(bufferZone)->nbBlocks==0) { + hUDP(bufferZone)->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) + hUDP(bufferZone)->blockID=0; + hUDP(bufferZone)->contentBytes=sizeof(fs6_dl_t); + } + + hDL(bufferZone)->DuClock=DuClock; + hDL(bufferZone)->CuSpentMicroSec=(rdtsc()-startCycle)/(cpuf*1000); + updateTimesReset(startCycle, &CUprocessing, 1000, true,"CU entire processing from recv to send"); + sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); + return; +} + +void UL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t *TS, uint64_t *DuClock, uint64_t *startProcessing) { + initBufferZone(bufferZone); + initStaticTime(begingWait); + initRefTimes(fullLoop); + pickStaticTime(begingWait); + int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentDUv0 ); + * DuClock=hUDP(bufferZone)->senderClock; + * startProcessing=rdtsc(); + updateTimesReset(begingWait, &fullLoop, 1000, false, "CU wait DU"); + + if (nb_blocks ==0) { + LOG_W(PHY, "CU lost a subframe\n"); + return; + } + + if (nb_blocks != hUDP(bufferZone)->nbBlocks ) + LOG_W(PHY, "received %d blocks for %d expected\n", nb_blocks, hUDP(bufferZone)->nbBlocks); + + if ( *TS != hUDP(bufferZone)->timestamp ) { + LOG_W(HW, "CU received time: %lu instead of %lu expected\n", hUDP(bufferZone)->timestamp, *TS); + *TS=hUDP(bufferZone)->timestamp; + } + + setAllfromTS(hUDP(bufferZone)->timestamp, proc); + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + + if (is_prach_subframe(&eNB->frame_parms, proc->frame_prach,proc->subframe_prach)>0) + prach_eNB_fromsplit(bufferZone, sizeof(bufferZone), eNB, proc); + + release_UE_in_freeList(eNB->Mod_id); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX_fromsplit(bufferZone, nb_blocks, eNB, proc); + } +} + +void *cu_fs6(void *arg) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + RU_t *ru = (RU_t *)arg; + //RU_proc_t *proc = &ru->proc; + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + phy_init_RU(ru); + wait_sync("ru_thread"); + char remoteIP[1024]; + strncpy(remoteIP,get_softmodem_params()->split73+3, 1023); //three first char should be cu: or du: + char port_def[256]=DU_PORT; + for (int i=0; i <1000; i++) + if (remoteIP[i]==':') { + strncpy(port_def,remoteIP+i+1,255); + remoteIP[i]=0; + break; + } + + AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, port_def, &sockFS6), ""); + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + uint64_t timeStamp=0; + initStaticTime(begingWait); + initStaticTime(begingWait2); + initRefTimes(waitDUAndProcessingUL); + initRefTimes(makeSendDL); + initRefTimes(fullLoop); + uint64_t DuClock=0, startProcessing=0; + + while(1) { + timeStamp+=ru->frame_parms->samples_per_tti; + updateTimesReset(begingWait, &fullLoop, 1000, true, "CU for full SubFrame (must be less 1ms)"); + pickStaticTime(begingWait); + UL_cu_fs6(ru, &L1proc, &timeStamp, &DuClock, &startProcessing); + updateTimesReset(begingWait, &waitDUAndProcessingUL, 1000, true,"CU Time in wait Rx + Ul processing"); + pickStaticTime(begingWait2); + DL_cu_fs6(ru, &L1proc, DuClock, startProcessing); + updateTimesReset(begingWait2, &makeSendDL, 1000, true,"CU Time in DL build+send"); + } + + return NULL; +} + +void *du_fs6(void *arg) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + RU_t *ru = (RU_t *)arg; + //RU_proc_t *proc = &ru->proc; + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + phy_init_RU(ru); + init_rf(ru); + wait_sync("ru_thread"); + char remoteIP[1024]; + strncpy(remoteIP,get_softmodem_params()->split73+3,1023); //three first char should be cu: or du: + char port_def[256]=CU_PORT; + for (int i=0; i <1000; i++) + if (remoteIP[i]==':') { + strncpy(port_def,remoteIP+i+1,255); + remoteIP[i]=0; + break; + } + AssertFatal(createUDPsock(NULL, DU_PORT, remoteIP, port_def, &sockFS6), ""); + + if (ru->rfdevice.trx_start_func(&ru->rfdevice) != 0) + LOG_E(HW,"Could not start the RF device\n"); + else + LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + + initStaticTime(begingWait); + initRefTimes(waitRxAndProcessingUL); + initRefTimes(fullLoop); + pthread_t t; + + if ( !IS_SOFTMODEM_RFSIM ) + threadCreate(&t, DL_du_fs6, (void *)ru, "MainDuTx", -1, OAI_PRIORITY_RT_MAX); + + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + + while(!oai_exit) { + updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); + pickStaticTime(begingWait); + UL_du_fs6(ru, &L1proc); + + if ( IS_SOFTMODEM_RFSIM ) + DL_du_fs6((void *)ru); + + updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); + } + + ru->rfdevice.trx_end_func(&ru->rfdevice); + LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); + return NULL; +} diff --git a/executables/main-ocp.c b/executables/main-ocp.c new file mode 100644 index 0000000000000000000000000000000000000000..8171d78d5b9eac7ac0e7ee791636f0c9bd0abc78 --- /dev/null +++ b/executables/main-ocp.c @@ -0,0 +1,1379 @@ +/* + Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX + copyleft: OpenAirInterface Software Alliance and it's licence + * This file replaces + * targets/RT/USER/lte-softmodem.c + * targets/RT/USER/rt_wrapper.c + * targets/RT/USER/lte-ru.c + * targets/RT/USER/lte-enb.c + * targets/RT/USER/ru_control.c + * openair1/SCHED/prach_procedures.c + * The merger of OpenAir central code to this branch + * should check if these 3 files are modified and analyze if code code has to be copied in here + */ +#define _GNU_SOURCE +#include <pthread.h> + +#include <common/utils/LOG/log.h> +#include <common/utils/system.h> +#include <common/utils/assertions.h> +static int DEFBANDS[] = {7}; +static int DEFENBS[] = {0}; +#include <common/config/config_userapi.h> +#include <targets/RT/USER/lte-softmodem.h> +#include <openair1/PHY/defs_eNB.h> +#include <openair1/PHY/phy_extern.h> +#include <nfapi/oai_integration/vendor_ext.h> +#include <openair1/SCHED/fapi_l1.h> +#include <openair1/PHY/INIT/phy_init.h> +#include <openair2/LAYER2/MAC/mac_extern.h> +#include <openair1/PHY/LTE_REFSIG/lte_refsig.h> +#include <nfapi/oai_integration/nfapi_pnf.h> +#include <executables/split_headers.h> +#include <common/utils/threadPool/thread-pool.h> +#include <openair2/ENB_APP/NB_IoT_interface.h> +#include <common/utils/load_module_shlib.h> +#include <targets/COMMON/create_tasks.h> +#include <openair1/PHY/TOOLS/phy_scope_interface.h> +#include <openair2/UTIL/OPT/opt.h> +#include <openair1/SIMULATION/TOOLS/sim.h> +#include <openair1/PHY/phy_vars.h> +#include <openair1/SCHED/sched_common_vars.h> +#include <openair2/LAYER2/MAC/mac_vars.h> +#include <openair2/RRC/LTE/rrc_vars.h> + +pthread_cond_t nfapi_sync_cond; +pthread_mutex_t nfapi_sync_mutex; +int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex +pthread_cond_t sync_cond; +pthread_mutex_t sync_mutex; +int sync_var=-1; //!< protected by mutex \ref sync_mutex. +int config_sync_var=-1; +volatile int oai_exit = 0; +double cpuf; +uint16_t sf_ahead=4; +int otg_enabled; +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int split73; +char * split73_config; +int split73; + +static void *ru_thread( void *param ); +void kill_RU_proc(RU_t *ru) { +} +void kill_eNB_proc(int inst) { +} +void free_transport(PHY_VARS_eNB *eNB) { +} +void reset_opp_meas(void) { +} +extern void phy_free_RU(RU_t *); + +void exit_function(const char *file, const char *function, const int line, const char *s) { + if (s != NULL) { + printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); + } + + close_log_mem(); + oai_exit = 1; + + if (RC.ru == NULL) + exit(-1); // likely init not completed, prevent crash or hang, exit now... + + for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) { + if (RC.ru[ru_id] && RC.ru[ru_id]->rfdevice.trx_end_func) { + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + } + + if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) { + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + } + } + + sleep(1); //allow lte-softmodem threads to exit first + exit(1); +} + +// Fixme: there are many mistakes in the datamodel and in redondant variables +// TDD is also mode complex +void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc) { + for (int i=0; i < RC.nb_inst; i++) { + for (int j=0; j<RC.nb_CC[i]; j++) { + LTE_DL_FRAME_PARMS *fp=&RC.eNB[i][j]->frame_parms; + uint64_t TStx=TS+(sf_ahead)*fp->samples_per_tti; + uint64_t TSrach=TS;//-fp->samples_per_tti; + proc->timestamp_rx= TS; + proc->timestamp_tx= TStx; + proc->subframe_rx= (TS / fp->samples_per_tti)%10; + proc->subframe_prach=(TSrach / fp->samples_per_tti)%10; + proc->subframe_prach_br=(TSrach / fp->samples_per_tti)%10; + proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; + proc->frame_prach= (TSrach / (fp->samples_per_tti*10))&1023; + proc->frame_prach_br=(TSrach / (fp->samples_per_tti*10))&1023; + proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + proc->subframe_tx= (TStx / fp->samples_per_tti)%10; + } + } + + return; +} + +void init_RU_proc(RU_t *ru) { + pthread_t t; + + switch(split73) { + case SPLIT73_CU: + threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); + break; + case SPLIT73_DU: + threadCreate(&t, du_fs6, (void *)ru, "MainDuRx", -1, OAI_PRIORITY_RT_MAX); + break; + default: + threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); + } +} + +// Create per UE structures +void init_transport(PHY_VARS_eNB *eNB) { + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + LOG_I(PHY, "Initialise transport\n"); + + for (int i=0; i<NUMBER_OF_UE_MAX; i++) { + LOG_D(PHY,"Allocating Transport Channel Buffers for DLSCH, UE %d\n",i); + + for (int j=0; j<2; j++) { + AssertFatal( (eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp)) != NULL, + "Can't get eNB dlsch structures for UE %d \n", i); + eNB->dlsch[i][j]->rnti=0; + LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti); + } + + LOG_D(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); + AssertFatal((eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0)) != NULL, + "Can't get eNB ulsch structures\n"); + // this is the transmission mode for the signalling channels + // this will be overwritten with the real transmission mode by the RRC once the UE is connected + eNB->transmission_mode[i] = fp->nb_antenna_ports_eNB==1 ? 1 : 2; + } + + // ULSCH for RA + AssertFatal( (eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0)) !=NULL, + "Can't get eNB ulsch structures\n"); + eNB->dlsch_SI = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : SI %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_SI); + eNB->dlsch_ra = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : RA %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_ra); + eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : MCH %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_MCH); + eNB->rx_total_gain_dB=130; + + for(int i=0; i<NUMBER_OF_UE_MAX; i++) + eNB->mu_mimo_mode[i].dl_pow_off = 2; + + eNB->check_for_total_transmissions = 0; + eNB->check_for_MUMIMO_transmissions = 0; + eNB->FULL_MUMIMO_transmissions = 0; + eNB->check_for_SUMIMO_transmissions = 0; + fp->pucch_config_common.deltaPUCCH_Shift = 1; +} + +void init_eNB_afterRU(void) { + for (int inst=0; inst<RC.nb_inst; inst++) { + for (int CC_id=0; CC_id<RC.nb_CC[inst]; CC_id++) { + PHY_VARS_eNB *eNB = RC.eNB[inst][CC_id]; + phy_init_lte_eNB(eNB,0,0); + eNB->frame_parms.nb_antennas_rx = 0; + eNB->frame_parms.nb_antennas_tx = 0; + eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *)); + + for (int ce_level=0; ce_level<4; ce_level++) { + eNB->prach_vars_br.rxsigF[ce_level] = (int16_t **)malloc16(64*sizeof(int16_t *)); + } + + for (int ru_id=0,aa=0; ru_id<eNB->num_RU; ru_id++) { + eNB->frame_parms.nb_antennas_rx += eNB->RU_list[ru_id]->nb_rx; + eNB->frame_parms.nb_antennas_tx += eNB->RU_list[ru_id]->nb_tx; + AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL, + "RU %d : common.rxdataF is NULL\n", + eNB->RU_list[ru_id]->idx); + AssertFatal(eNB->RU_list[ru_id]->prach_rxsigF!=NULL, + "RU %d : prach_rxsigF is NULL\n", + eNB->RU_list[ru_id]->idx); + + for (int i=0; i<eNB->RU_list[ru_id]->nb_rx; aa++,i++) { + LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa); + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[i]; + + for (int ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i]; + + eNB->common_vars.rxdataF[aa] = eNB->RU_list[ru_id]->common.rxdataF[i]; + } + } + + AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); + AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); + LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); + init_transport(eNB); + //init_precoding_weights(RC.eNB[inst][CC_id]); + } + } +} + +void init_eNB(int single_thread_flag,int wait_for_sync) { + AssertFatal(RC.eNB != NULL,"RC.eNB must have been allocated\n"); + + for (int inst=0; inst<RC.nb_L1_inst; inst++) { + AssertFatal(RC.eNB[inst] != NULL,"RC.eNB[%d] must have been allocated\n", inst); + + for (int CC_id=0; CC_id<RC.nb_L1_CC[inst]; CC_id++) { + AssertFatal(RC.eNB[inst][CC_id] != NULL,"RC.eNB[%d][%d] must have been allocated\n", inst, CC_id); + PHY_VARS_eNB *eNB = RC.eNB[inst][CC_id]; + eNB->abstraction_flag = 0; + eNB->single_thread_flag = single_thread_flag; + AssertFatal((eNB->if_inst = IF_Module_init(inst))!=NULL,"Cannot register interface"); + eNB->if_inst->schedule_response = schedule_response; + eNB->if_inst->PHY_config_req = phy_config_request; + memset((void *)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO)); + memset((void *)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO)); + pthread_mutex_init( &eNB->UL_INFO_mutex, NULL); + LOG_I(PHY,"Setting indication lists\n"); + eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = eNB->rx_pdu_list; + eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list; + eNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = eNB->sr_pdu_list; + eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list; + eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_pdu_list = eNB->cqi_pdu_list; + eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list; + eNB->prach_energy_counter = 0; + } + } + + SET_LOG_DEBUG(PRACH); +} + +void stop_eNB(int nb_inst) { + for (int inst=0; inst<nb_inst; inst++) { + LOG_I(PHY,"Killing eNB %d processing threads\n",inst); + kill_eNB_proc(inst); + } +} + +// this is for RU with local RF unit +void fill_rf_config(RU_t *ru, char *rf_config_file) { + int i; + LTE_DL_FRAME_PARMS *fp = ru->frame_parms; + openair0_config_t *cfg = &ru->openair0_cfg; + //printf("////////////////numerology in config = %d\n",numerology); + int numerology = get_softmodem_params()->numerology; + + if(fp->N_RB_DL == 100) { + if(numerology == 0) { + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + } else if(numerology == 1) { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } else if(numerology == 2) { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } else { + LOG_E(PHY,"Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology); + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + } else if(fp->N_RB_DL == 50) { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } else if (fp->N_RB_DL == 25) { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 2.5e6; + cfg->rx_bw = 2.5e6; + } else if (fp->N_RB_DL == 6) { + cfg->sample_rate=1.92e6; + cfg->samples_per_frame = 19200; + cfg->tx_bw = 1.5e6; + cfg->rx_bw = 1.5e6; + } else AssertFatal(1==0,"Unknown N_RB_DL %d\n",fp->N_RB_DL); + + if (fp->frame_type==TDD) + cfg->duplex_mode = duplex_mode_TDD; + else //FDD + cfg->duplex_mode = duplex_mode_FDD; + + cfg->Mod_id = 0; + cfg->num_rb_dl=fp->N_RB_DL; + cfg->tx_num_channels=ru->nb_tx; + cfg->rx_num_channels=ru->nb_rx; + cfg->clock_source=get_softmodem_params()->clock_source; + + for (i=0; i<ru->nb_tx; i++) { + cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; + cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; + cfg->tx_gain[i] = (double)ru->att_tx; + cfg->rx_gain[i] = ru->max_rxgain-(double)ru->att_rx; + cfg->configFilename = rf_config_file; + LOG_I(PHY,"channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", + i, cfg->tx_gain[i], + cfg->rx_gain[i], + cfg->tx_freq[i], + cfg->rx_freq[i]); + } +} + +/* this function maps the RU tx and rx buffers to the available rf chains. + Each rf chain is is addressed by the card number and the chain on the card. The + rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple + antennas are mapped to successive RF chains on the same card. */ +int setup_RU_buffers(RU_t *ru) { + //uint16_t N_TA_offset = 0; + LTE_DL_FRAME_PARMS *frame_parms; + AssertFatal(ru, "ru is NULL"); + frame_parms = ru->frame_parms; + LOG_I(PHY,"setup_RU_buffers: frame_parms = %p\n",frame_parms); + + if (frame_parms->frame_type == TDD) { + if (frame_parms->N_RB_DL == 100) { + ru->N_TA_offset = 624; + } else if (frame_parms->N_RB_DL == 50) { + ru->N_TA_offset = 624/2; + ru->sf_extension /= 2; + ru->end_of_burst_delay /= 2; + } else if (frame_parms->N_RB_DL == 25) { + ru->N_TA_offset = 624/4; + ru->sf_extension /= 4; + ru->end_of_burst_delay /= 4; + } else { + LOG_E(PHY,"not handled, todo\n"); + exit(1); + } + } else { + ru->N_TA_offset = 0; + ru->sf_extension = 0; + ru->end_of_burst_delay = 0; + } + + return(0); +} + +void init_precoding_weights(PHY_VARS_eNB *eNB) { + int layer,ru_id,aa,re,ue,tb; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + RU_t *ru; + LTE_eNB_DLSCH_t *dlsch; + + // init precoding weigths + for (ue=0; ue<NUMBER_OF_UE_MAX; ue++) { + for (tb=0; tb<2; tb++) { + dlsch = eNB->dlsch[ue][tb]; + + for (layer=0; layer<4; layer++) { + int nb_tx=0; + + for (ru_id=0; ru_id<RC.nb_RU; ru_id++) { + ru = RC.ru[ru_id]; + nb_tx+=ru->nb_tx; + } + + dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(nb_tx*sizeof(int32_t *)); + + for (aa=0; aa<nb_tx; aa++) { + dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); + + for (re=0; re<fp->ofdm_symbol_size; re++) { + dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; + } + } + } + } + } +} + +void ocp_rx_prach(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + RU_t *ru, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t *avg_preamble_energy, + uint16_t Nf, + uint8_t tdd_mapindex, + uint8_t br_flag) { + int i; + int prach_mask=0; + + if (br_flag == 0) { + rx_prach0(eNB,ru,proc->frame_prach, proc->subframe_prach, + max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); + } else { // This is procedure for eMTC, basically handling the repetitions + prach_mask = is_prach_subframe(&eNB->frame_parms,proc->frame_prach_br,proc->subframe_prach_br); + + for (i=0; i<4; i++) { + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i]==1) && + ((prach_mask&(1<<(i+1))) > 0)) { // check that prach CE level is active now + + // if first reception in group of repetitions store frame for later (in RA-RNTI for Msg2) + if (eNB->prach_vars_br.repetition_number[i]==0) eNB->prach_vars_br.first_frame[i]=proc->frame_prach_br; + + // increment repetition number + eNB->prach_vars_br.repetition_number[i]++; + // do basic PRACH reception + rx_prach0(eNB,ru,proc->frame_prach, proc->subframe_prach_br, + max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); + + // if last repetition, clear counter + if (eNB->prach_vars_br.repetition_number[i] == eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[i]) { + eNB->prach_vars_br.repetition_number[i]=0; + } + } + } /* for i ... */ + } /* else br_flag == 0 */ +} + +void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int br_flag) { + uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4],avg_preamble_energy[4]; + RU_t *ru; + int aa=0; + int ru_aa; + + for (int i=0; i<eNB->num_RU; i++) { + ru=eNB->RU_list[i]; + + for (ru_aa=0,aa=0; ru_aa<ru->nb_rx; ru_aa++,aa++) { + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + int ce_level; + + if (br_flag==1) + for (ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[i]->prach_rxsigF_br[ce_level][ru_aa]; + } + } + + // run PRACH detection for CE-level 0 only for now when br_flag is set + ocp_rx_prach(eNB, + proc, + eNB->RU_list[0], + &max_preamble[0], + &max_preamble_energy[0], + &max_preamble_delay[0], + &avg_preamble_energy[0], + proc->frame_prach, + 0 + ,br_flag + ); + LOG_D(PHY,"RACH detection index 0: max preamble: %u, energy: %u, delay: %u, avg energy: %u\n", + max_preamble[0], + max_preamble_energy[0], + max_preamble_delay[0], + avg_preamble_energy[0] + ); + + if (br_flag==1) { + int prach_mask; + prach_mask = is_prach_subframe (&eNB->frame_parms, proc->frame_prach_br, proc->subframe_prach_br); + eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; + int ind = 0; + int ce_level = 0; + /* Save for later, it doesn't work + for (int ind=0,ce_level=0;ce_level<4;ce_level++) { + + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[ce_level]==1)&& + (prach_mask&(1<<(1+ce_level)) > 0) && // prach is active and CE level has finished its repetitions + (eNB->prach_vars_br.repetition_number[ce_level]== + eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) { + + */ + + if (eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[0] == 1) { + if ((eNB->prach_energy_counter == 100) && (max_preamble_energy[0] > eNB->measurements.prach_I0 + eNB->prach_DTX_threshold_emtc[0])) { + eNB->UL_INFO.rach_ind_br.rach_indication_body.number_of_preambles++; + eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind]; // + eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; + // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + proc->subframe_prach + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); + eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is + eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1 + ce_level; // CE Level + LOG_I (PHY, "Filling NFAPI indication for RACH %d CELevel %d (mask %x) : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + ind, + ce_level, + prach_mask, + eNB->preamble_list_br[ind].preamble_rel8.timing_advance, + eNB->preamble_list_br[ind].preamble_rel8.preamble, eNB->preamble_list_br[ind].preamble_rel8.rnti, eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type); + } + } + + /* + ind++; + } + } */// ce_level + } else if ((eNB->prach_energy_counter == 100) && + (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) { + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", + eNB->Mod_id, + eNB->CC_id, + proc->frame_prach, + proc->subframe_prach, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + max_preamble_delay[0]); + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 1; + eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = &eNB->preamble_list[0]; + eNB->UL_INFO.rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; + eNB->UL_INFO.rach_ind.header.message_id = NFAPI_RACH_INDICATION; + eNB->UL_INFO.rach_ind.sfn_sf = proc->frame_prach<<4 | proc->subframe_prach; + eNB->preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; + eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; + eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; + eNB->preamble_list[0].preamble_rel8.rnti = 1+proc->subframe_prach; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; + eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // If NFAPI PNF then we need to send the message to the VNF + LOG_D(PHY,"Filling NFAPI indication for RACH : SFN_SF:%d TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf), + eNB->preamble_list[0].preamble_rel8.timing_advance, + eNB->preamble_list[0].preamble_rel8.preamble, + eNB->preamble_list[0].preamble_rel8.rnti, + eNB->preamble_list[0].preamble_rel13.rach_resource_type); + oai_nfapi_rach_ind(&eNB->UL_INFO.rach_ind); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 0; + } + + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + } // max_preamble_energy > prach_I0 + 100 + else { + eNB->measurements.prach_I0 = ((eNB->measurements.prach_I0*900)>>10) + ((avg_preamble_energy[0]*124)>>10); + + if (eNB->prach_energy_counter < 100) + eNB->prach_energy_counter++; + } +} // else br_flag + +void prach_eNB(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int frame,int subframe) { + // check if we have to detect PRACH first + if (is_prach_subframe(&eNB->frame_parms, frame,subframe)>0) { + prach_procedures_ocp(eNB, proc, 0); + prach_procedures_ocp(eNB, proc, 1); + } +} + +static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) { + AssertFatal( eNB !=NULL, ""); + + if (NFAPI_MODE==NFAPI_MODE_PNF) { + // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick + //add_subframe(&frame, &subframe, 4); + //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); + oai_subframe_ind(proc->frame_rx, proc->subframe_rx); + } + + AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF && + eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), ""); + prach_eNB(eNB,proc,proc->frame_rx,proc->subframe_rx); + release_UE_in_freeList(eNB->Mod_id); + + // UE-specific RX processing for subframe n + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX(eNB, proc); + } + + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.frame = proc->frame_rx; + eNB->UL_INFO.subframe = proc->subframe_rx; + eNB->UL_INFO.module_id = eNB->Mod_id; + eNB->UL_INFO.CC_id = eNB->CC_id; + eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + phy_procedures_eNB_TX(eNB, proc, 1); + return(0); +} + +void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { + LTE_DL_FRAME_PARMS *fp = ru->frame_parms; + void *rxp[ru->nb_rx]; + unsigned int rxs; + int i; + openair0_timestamp ts=0, timestamp_rx; + static openair0_timestamp old_ts=0; + + for (i=0; i<ru->nb_rx; i++) + //receive in the next slot + rxp[i] = (void *)&ru->common.rxdata[i][((proc->subframe_rx+1)%10)*fp->samples_per_tti]; + + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &ts, + rxp, + fp->samples_per_tti, + ru->nb_rx); + timestamp_rx = ts-ru->ts_offset; + + // AssertFatal(rxs == fp->samples_per_tti, + // "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); + if(rxs != fp->samples_per_tti) { + LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); +#if defined(USRP_REC_PLAY) + exit_fun("Exiting IQ record/playback"); +#else + //exit_fun( "problem receiving samples" ); + LOG_E(PHY, "problem receiving samples"); +#endif + } + + if (old_ts != 0 && timestamp_rx - old_ts != fp->samples_per_tti) { + LOG_E(HW,"impossible shift in rx stream, rx: %ld, previous rx distance: %ld, should be %d\n", timestamp_rx, proc->timestamp_rx - old_ts, fp->samples_per_tti); + //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); + //proc->timestamp_rx = ts-ru->ts_offset; + } + + old_ts=timestamp_rx; + setAllfromTS(timestamp_rx, proc); +} + +void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { + LTE_DL_FRAME_PARMS *fp = ru->frame_parms; + void *txp[ru->nb_tx]; + int i; + lte_subframe_t SF_type = subframe_select(fp,proc->subframe_tx%10); + lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10); + int sf_extension = 0; + + if ((SF_type == SF_DL) || + (SF_type == SF_S)) { + int siglen=fp->samples_per_tti,flags=1; + + if (SF_type == SF_S) { + /* end_of_burst_delay is used to stop TX only "after a while". + * If we stop right after effective signal, with USRP B210 and + * B200mini, we observe a high EVM on the S subframe (on the + * PSS). + * A value of 400 (for 30.72MHz) solves this issue. This is + * the default. + */ + siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + + (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples) + + ru->end_of_burst_delay; + flags=3; // end of burst + } + + if (fp->frame_type == TDD && + SF_type == SF_DL && + prevSF_type == SF_UL) { + flags = 2; // start of burst + sf_extension = ru->sf_extension; + } + +#if defined(__x86_64) || defined(__i386__) +#ifdef __AVX2__ + sf_extension = (sf_extension)&0xfffffff8; +#else + sf_extension = (sf_extension)&0xfffffffc; +#endif +#elif defined(__arm__) + sf_extension = (sf_extension)&0xfffffffc; +#endif + + for (i=0; i<ru->nb_tx; i++) + txp[i] = (void *)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension]; + + /* add fail safe for late command end */ + // prepare tx buffer pointers + ru->rfdevice.trx_write_func(&ru->rfdevice, + proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, subframe %d\n",ru->idx, + (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->subframe_tx); + } + + return; +} + +static void *ru_thread( void *param ) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + RU_t *ru = (RU_t *)param; + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + + if (ru->if_south == LOCAL_RF) { // configure RF parameters only + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(ru->frame_parms,1); + phy_init_RU(ru); + init_rf(ru); + } + + AssertFatal(setup_RU_buffers(ru)==0, "Exiting, cannot initialize RU Buffers\n"); + LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); + wait_sync("ru_thread"); + + // Start RF device if any + if (ru->rfdevice.trx_start_func(&ru->rfdevice) != 0) + LOG_E(HW,"Could not start the RF device\n"); + else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + // synchronization on input FH interface, acquire signals/data and block + rx_rf(ru, &L1proc); + // do RX front-end processing (frequency-shift, dft) if needed + fep_full(ru, L1proc.subframe_rx); + + // At this point, all information for subframe has been received on FH interface + // If this proc is to provide synchronization, do so + // Fixme: not used + // wakeup_slaves(proc); + for (int i=0; i<ru->num_eNB; i++) { + char string[20]; + sprintf(string,"Incoming RU %d",ru->idx); + + if (rxtx(ru->eNB_list[i],&L1proc,string) < 0) + LOG_E(PHY,"eNB %d CC_id %d failed during execution\n", + ru->eNB_list[i]->Mod_id,ru->eNB_list[i]->CC_id); + } + + // do TX front-end processing if needed (precoding and/or IDFTs) + feptx_prec(ru, L1proc.frame_tx, L1proc.subframe_tx); + // do OFDM if needed + feptx_ofdm(ru, L1proc.frame_tx, L1proc.subframe_tx); + // do outgoing fronthaul (south) if needed + ocp_tx_rf(ru, &L1proc); + } + + LOG_W(PHY,"Exiting ru_thread \n"); + ru->rfdevice.trx_end_func(&ru->rfdevice); + LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); + return NULL; +} + +int init_rf(RU_t *ru) { + char name[256]; + pthread_getname_np(pthread_self(),name, 255); + pthread_setname_np(pthread_self(),"UHD for OAI"); + int ret=openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + pthread_setname_np(pthread_self(),name); + return ret; +} + +void init_RU(char *rf_config_file, int send_dmrssync) { + RU_t *ru; + PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL; + int i; + int CC_id; + // read in configuration file) + LOG_I(PHY,"configuring RU from file\n"); + LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n", + RC.nb_L1_inst,RC.nb_RU,get_nprocs()); + + if (RC.nb_CC != 0) + for (i=0; i<RC.nb_L1_inst; i++) + for (CC_id=0; CC_id<RC.nb_CC[i]; CC_id++) + RC.eNB[i][CC_id]->num_RU=0; + + LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); + + for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) { + LOG_D(PHY,"Process RC.ru[%d]\n",ru_id); + ru = RC.ru[ru_id]; + ru->rf_config_file = rf_config_file; + ru->idx = ru_id; + ru->ts_offset = 0; + + if (ru->is_slave == 1) { + ru->in_synch = 0; + ru->generate_dmrs_sync = 0; + } else { + ru->in_synch = 1; + ru->generate_dmrs_sync=send_dmrssync; + } + + ru->cmd = EMPTY; + ru->south_out_cnt= 0; + + // ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0; + if (ru->generate_dmrs_sync == 1) { + generate_ul_ref_sigs(); + ru->dmrssync = (int16_t *)malloc16_clear(ru->frame_parms->ofdm_symbol_size*2*sizeof(int16_t)); + } + + ru->wakeup_L1_sleeptime = 2000; + ru->wakeup_L1_sleep_cnt_max = 3; + + if (ru->num_eNB > 0) { + LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", + __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file); + AssertFatal(ru->eNB_list[0], "ru->eNB_list is not initialized\n"); + } else { + LOG_E(PHY,"Wrong data model, assigning eNB 0, carrier 0 to RU 0\n"); + ru->eNB_list[0] = RC.eNB[0][0]; + ru->num_eNB=1; + } + + eNB0 = ru->eNB_list[0]; + // datamodel error in regular OAI: a RU uses one single eNB carrier parameters! + ru->frame_parms = &eNB0->frame_parms; + + for (i=0; i<ru->num_eNB; i++) { + eNB0 = ru->eNB_list[i]; + int ruIndex=eNB0->num_RU++; + eNB0->RU_list[ruIndex] = ru; + } + } // for ru_id +} + +void stop_RU(int nb_ru) { + for (int inst = 0; inst < nb_ru; inst++) { + LOG_I(PHY, "Stopping RU %d processing threads\n", inst); + kill_RU_proc(RC.ru[inst]); + } +} + +/* --------------------------------------------------------*/ +/* from here function to use configuration module */ +static int DEFBFW[] = {0x00007fff}; +void RCconfig_RU(void) { + paramdef_t RUParams[] = RUPARAMS_DESC; + paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; + config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL); + + if ( RUParamList.numelt == 0 ) { + LOG_W(PHY, "Calling RCconfig_RU while no ru\n"); + RC.nb_RU = 0; + return; + } // setting != NULL + + if ( RC.ru != NULL ) { + LOG_W(PHY, "Calling RCconfig_RU twice (nb ru=%d), ignoring the second call data structure is %p\n", + RUParamList.numelt,RC.ru); + return; + } + + RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); + + for (int j = 0; j < RC.nb_RU; j++) { + RC.ru[j] = (RU_t *)calloc(sizeof(RU_t), 1); + RC.ru[j]->idx = j; + LOG_I(PHY,"Creating RC.ru[%d]:%p\n", j, RC.ru[j]); + RC.ru[j]->if_timing = synch_to_ext_device; + paramdef_t *vals=RUParamList.paramarray[j]; + + if (RC.nb_L1_inst >0) + RC.ru[j]->num_eNB = vals[RU_ENB_LIST_IDX].numelt; + else + RC.ru[j]->num_eNB = 0; + + for (int i=0; i<RC.ru[j]->num_eNB; i++) + RC.ru[j]->eNB_list[i] = RC.eNB[vals[RU_ENB_LIST_IDX].iptr[i]][0]; + + if (config_isparamset(vals, RU_SDR_ADDRS)) { + RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(vals[RU_SDR_ADDRS].strptr)); + } + + if (config_isparamset(vals, RU_SDR_CLK_SRC)) { + char *paramVal=*(vals[RU_SDR_CLK_SRC].strptr); + LOG_D(PHY, "RU clock source set as %s\n", paramVal); + + if (strcmp(paramVal, "internal") == 0) { + RC.ru[j]->openair0_cfg.clock_source = internal; + } else if (strcmp(paramVal, "external") == 0) { + RC.ru[j]->openair0_cfg.clock_source = external; + } else if (strcmp(paramVal, "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.clock_source = gpsdo; + } else { + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", paramVal); + } + } + + if (strcmp(*(vals[RU_LOCAL_RF_IDX].strptr), "yes") == 0) { + if ( !(config_isparamset(vals,RU_LOCAL_IF_NAME_IDX)) ) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = eNodeB_3GPP; + LOG_I(PHY, "Setting function for RU %d to eNodeB_3GPP\n",j); + } else { + RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); + } + + RC.ru[j]->max_pdschReferenceSignalPower = *(vals[RU_MAX_RS_EPRE_IDX].uptr);; + RC.ru[j]->max_rxgain = *(vals[RU_MAX_RXGAIN_IDX].uptr); + RC.ru[j]->num_bands = vals[RU_BAND_LIST_IDX].numelt; + /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ + RC.ru[j]->sf_extension = *(vals[RU_SF_EXTENSION_IDX].uptr); + RC.ru[j]->end_of_burst_delay = *(vals[RU_END_OF_BURST_DELAY_IDX].uptr); + + for (int i=0; i<RC.ru[j]->num_bands; i++) RC.ru[j]->band[i] = vals[RU_BAND_LIST_IDX].iptr[i]; + } else { + LOG_I(PHY,"RU %d: Transport %s\n",j,*(vals[RU_TRANSPORT_PREFERENCE_IDX].strptr)); + RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); + } /* strcmp(local_rf, "yes") != 0 */ + + RC.ru[j]->nb_tx = *(vals[RU_NB_TX_IDX].uptr); + RC.ru[j]->nb_rx = *(vals[RU_NB_RX_IDX].uptr); + RC.ru[j]->att_tx = *(vals[RU_ATT_TX_IDX].uptr); + RC.ru[j]->att_rx = *(vals[RU_ATT_RX_IDX].uptr); + }// j=0..num_rus + + return; +} + + +static void get_options(void) { + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + get_common_options(SOFTMODEM_ENB_BIT); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); + + if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) { + memset((void *)&RC,0,sizeof(RC)); + /* Read RC configuration file */ + RCConfig(); + NB_eNB_INST = RC.nb_inst; + printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU); + + if (!IS_SOFTMODEM_NONBIOT) { + load_NB_IoT(); + printf(" nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n", + RC.nb_nb_iot_rrc_inst, RC.nb_nb_iot_L1_inst, RC.nb_nb_iot_macrlc_inst); + } else { + printf("All Nb-IoT instances disabled\n"); + RC.nb_nb_iot_rrc_inst=RC.nb_nb_iot_L1_inst=RC.nb_nb_iot_macrlc_inst=0; + } + } +} + +void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { + int CC_id; + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) malloc(sizeof(LTE_DL_FRAME_PARMS)); + /* Set some default values that may be overwritten while reading options */ + frame_parms[CC_id]->frame_type = FDD; + frame_parms[CC_id]->tdd_config = 3; + frame_parms[CC_id]->tdd_config_S = 0; + frame_parms[CC_id]->N_RB_DL = 100; + frame_parms[CC_id]->N_RB_UL = 100; + frame_parms[CC_id]->Ncp = NORMAL; + frame_parms[CC_id]->Ncp_UL = NORMAL; + frame_parms[CC_id]->Nid_cell = 0; + frame_parms[CC_id]->num_MBSFN_config = 0; + frame_parms[CC_id]->nb_antenna_ports_eNB = 1; + frame_parms[CC_id]->nb_antennas_tx = 1; + frame_parms[CC_id]->nb_antennas_rx = 1; + frame_parms[CC_id]->nushift = 0; + frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; + frame_parms[CC_id]->phich_config_common.phich_duration = normal; + // UL RS Config + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; + // downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31. + // downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0]; + // downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0]; + // downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0]; + //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); + frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0]; + } +} + +void init_pdcp(void) { + if (!NODE_IS_DU(RC.rrc[0]->node_type)) { + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + + if (IS_SOFTMODEM_NOS1) + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; + + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT; + + if ( split73!=SPLIT73_DU) + pdcp_module_init(pdcp_initmask); + + if (NODE_IS_CU(RC.rrc[0]->node_type)) { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + } else { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); + } + } else { + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); + } +} + +static void wait_nfapi_init(char *thread_name) { + printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name); + pthread_mutex_lock( &nfapi_sync_mutex ); + + while (nfapi_sync_var<0) + pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex ); + + pthread_mutex_unlock(&nfapi_sync_mutex); + printf( "NFAPI: got sync (%s)\n", thread_name); +} + +void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) { + LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n", + itti_get_task_name(from), from, itti_get_task_name(to), to); + MessageDef *msg; + msg = itti_alloc_new_message (from, TERMINATE_MESSAGE); + itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); +} + +int stop_L1L2(module_id_t enb_id) { + LOG_W(ENB_APP, "stopping lte-softmodem\n"); + + if (!RC.ru) { + LOG_UI(ENB_APP, "no RU configured\n"); + return -1; + } + + /* these tasks need to pick up new configuration */ + terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB); + oai_exit = 1; + LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id); + kill_RU_proc(RC.ru[enb_id]); + LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id); + kill_eNB_proc(enb_id); + oai_exit = 0; + + for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) { + free_transport(RC.eNB[enb_id][cc_id]); + phy_free_lte_eNB(RC.eNB[enb_id][cc_id]); + } + + phy_free_RU(RC.ru[enb_id]); + free_lte_top(); + return 0; +} + +/* + * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2() + */ +int restart_L1L2(module_id_t enb_id) { + RU_t *ru = RC.ru[enb_id]; + MessageDef *msg_p = NULL; + LOG_W(ENB_APP, "restarting lte-softmodem\n"); + /* block threads */ + pthread_mutex_lock(&sync_mutex); + sync_var = -1; + pthread_mutex_unlock(&sync_mutex); + RC.ru_mask |= (1 << ru->idx); + /* copy the changed frame parameters to the RU */ + /* TODO this should be done for all RUs associated to this eNB */ + memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS)); + /* reset the list of connected UEs in the MAC, since in this process with + * loose all UEs (have to reconnect) */ + init_UE_info(&RC.mac[enb_id]->UE_info); + LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); + /* pass a reconfiguration request which will configure everything down to + * RC.eNB[i][j]->frame_parms, too */ + msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ); + RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; + itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); + /* TODO XForms might need to be restarted, but it is currently (09/02/18) + * broken, so we cannot test it */ + init_RU_proc(ru); + ru->rf_map.card = 0; + ru->rf_map.chain = 0; /* CC_id + chain_offset;*/ + init_eNB_afterRU(); + printf("Sending sync to all threads\n"); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + return 0; +} + +int main ( int argc, char **argv ) { + int i; + int CC_id = 0; + int node_type = ngran_eNB; + AssertFatal(load_configmodule(argc,argv,0), "[SOFTMODEM] Error, configuration module init failed\n"); + logInit(); + printf("Reading in command-line options\n"); + get_options (); + AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n"); + EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; +#if T_TRACER + T_Config_Init(); +#endif + configure_linux(); + cpuf=get_cpu_freq_GHz(); + set_taus_seed (0); + + if (opp_enabled ==1) + reset_opp_meas(); + + itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + init_opt(); +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + + /* Read configuration */ + if (RC.nb_inst > 0) { + // Allocate memory from RC variable + read_config_and_init(); + } else { + printf("RC.nb_inst = 0, Initializing L1\n"); + RCconfig_L1(); + } + + /* We need to read RU configuration before FlexRAN starts so it knows what + * splits to report. Actual RU start comes later. */ + if (RC.nb_RU > 0 && NFAPI_MODE != NFAPI_MODE_VNF) { + RCconfig_RU(); + LOG_I(PHY, + "number of L1 instances %d, number of RU %d, number of CPU cores %d\n", + RC.nb_L1_inst, RC.nb_RU, get_nprocs()); + } + + if ( strlen(get_softmodem_params()->split73) > 0 ) { + char tmp[1024]={0}; + strncpy(tmp,get_softmodem_params()->split73, 1023); + tmp[2]=0; + if ( strncasecmp(tmp,"cu", 2)==0 ) + split73=SPLIT73_CU; + else if ( strncasecmp(tmp,"du", 2)==0 ) + split73=SPLIT73_DU; + else + AssertFatal(false,"split73 syntax: <cu|du>:<remote ip addr>[:<ip port>] (string found: %s) \n",get_softmodem_params()->split73); + } + + if (RC.nb_inst > 0) { + /* Start the agent. If it is turned off in the configuration, it won't start */ + for (i = 0; i < RC.nb_inst; i++) { + flexran_agent_start(i); + } + + /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks + * for monolithic/F1 modes */ + init_pdcp(); + AssertFatal(create_tasks(1)==0,"cannot create ITTI tasks\n"); + + for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) { + MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ); + RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; + itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); + } + + node_type = RC.rrc[0]->node_type; + } + + if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) { + protocol_ctxt_t ctxt; + ctxt.module_id = 0 ; + ctxt.instance = 0; + ctxt.rnti = 0; + ctxt.enb_flag = 1; + ctxt.frame = 0; + ctxt.subframe = 0; + pdcp_run(&ctxt); + } + + /* start threads if only L1 or not a CU */ + if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) { + // init UE_PF_PO and mutex lock + pthread_mutex_init(&ue_pf_po_mutex, NULL); + memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs); + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + + if (NFAPI_MODE!=NFAPI_MONOLITHIC) { + LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n"); + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + } + + if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF +#if defined(PRE_SCD_THREAD) + init_ru_vnf(); // ru pointer is necessary for pre_scd. +#endif + wait_nfapi_init("main?"); + } + + LOG_I(ENB_APP,"START MAIN THREADS\n"); + // start the main threads + number_of_cards = 1; + printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst); + + if (RC.nb_L1_inst > 0) { + printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", + get_softmodem_params()->single_thread_flag, + get_softmodem_params()->wait_for_sync); + init_eNB(get_softmodem_params()->single_thread_flag, + get_softmodem_params()->wait_for_sync); + } + + for (int x=0; x < RC.nb_L1_inst; x++) + for (int CC_id=0; CC_id<RC.nb_L1_CC[x]; CC_id++) { + L1_rxtx_proc_t *L1proc= &RC.eNB[x][CC_id]->proc.L1_proc; + L1proc->threadPool=(tpool_t *)malloc(sizeof(tpool_t)); + L1proc->respEncode=(notifiedFIFO_t *) malloc(sizeof(notifiedFIFO_t)); + L1proc->respDecode=(notifiedFIFO_t *) malloc(sizeof(notifiedFIFO_t)); + + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) + initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true); + else + initTpool("n", L1proc->threadPool, true); + + initNotifiedFIFO(L1proc->respEncode); + initNotifiedFIFO(L1proc->respDecode); + } + } + + printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); + + // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator. + // but RU thread deals with pre_scd and this is necessary in VNF and simulator. + // some initialization is necessary and init_ru_vnf do this. + if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) { + printf("Initializing RU threads\n"); + init_RU(get_softmodem_params()->rf_config_file, + get_softmodem_params()->send_dmrs_sync); + + for (int ru_id=0; ru_id<RC.nb_RU; ru_id++) { + RC.ru[ru_id]->rf_map.card=0; + RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); + LOG_I(PHY,"Starting ru_thread %d\n",ru_id); + init_RU_proc(RC.ru[ru_id]); + } + + config_sync_var=0; + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF + wait_nfapi_init("main?"); + } + + LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU); + // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) + printf("ALL RUs ready - init eNBs\n"); + + if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) { + LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n"); + init_eNB_afterRU(); + } else { + LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n"); + } + + LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n"); + // connect the TX/RX buffers + sleep(1); /* wait for thread activation */ + LOG_I(ENB_APP,"Sending sync to all threads\n"); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); + } + + create_tasks_mbms(1); + // wait for end of program + LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n"); + // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file + fflush(stdout); + fflush(stderr); + + // end of CI modifications + //getchar(); + if(IS_SOFTMODEM_DOFORMS) + load_softscope("enb"); + + itti_wait_tasks_end(); + oai_exit=1; + LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit); + // stop threads + + if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) { + if(IS_SOFTMODEM_DOFORMS) + end_forms(); + + LOG_I(ENB_APP,"stopping MODEM threads\n"); + stop_eNB(NB_eNB_INST); + stop_RU(RC.nb_RU); + + /* release memory used by the RU/eNB threads (incomplete), after all + * threads have been stopped (they partially use the same memory) */ + for (int inst = 0; inst < NB_eNB_INST; inst++) { + for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) { + free_transport(RC.eNB[inst][cc_id]); + phy_free_lte_eNB(RC.eNB[inst][cc_id]); + } + } + + for (int inst = 0; inst < RC.nb_RU; inst++) { + phy_free_RU(RC.ru[inst]); + } + + free_lte_top(); + end_configmodule(); + pthread_cond_destroy(&sync_cond); + pthread_mutex_destroy(&sync_mutex); + pthread_cond_destroy(&nfapi_sync_cond); + pthread_mutex_destroy(&nfapi_sync_mutex); + pthread_mutex_destroy(&ue_pf_po_mutex); + + for(int ru_id=0; ru_id<RC.nb_RU; ru_id++) { + if (RC.ru[ru_id]->rfdevice.trx_end_func) { + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + } + + if (RC.ru[ru_id]->ifdevice.trx_end_func) { + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + } + } + } + + terminate_opt(); + logClean(); + printf("Bye.\n"); + return 0; +} diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index afac4e0c54f81b6c9413f3d02902555c430af5ff..9003f6835778ce51024d387ac2cfef93f86d7362 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -185,8 +185,8 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx); } */ - // Call the scheduler + pthread_mutex_lock(&gNB->UL_INFO_mutex); gNB->UL_INFO.frame = frame_rx; gNB->UL_INFO.slot = slot_rx; @@ -324,7 +324,7 @@ static void *gNB_L1_thread( void *param ) { gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc; //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; char thread_name[100]; - + // set default return value // set default return value gNB_thread_rxtx_status = 0; @@ -421,7 +421,7 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot int waitret = 0, ret = 0, time_ns = 1000*1000; struct timespec now, abstime; - + // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1); time_ns = time_ns/gNB->frame_parms.slots_per_subframe; @@ -443,27 +443,27 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0); if (waitret == ETIMEDOUT) { - LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); + LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); + gNB->proc.RU_mask_tx = 0; + AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); + proc->instance_cnt_RUs = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); + + return(-1); + } - return(-1); - } - for(int i=0; i<gNB->num_RU; i++) { ru = gNB->RU_list[i]; ru_proc = &ru->proc; - + if (ru_proc->instance_cnt_gNBs == 0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1); @@ -484,10 +484,10 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs); - LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); + LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); // the thread can now be woken up AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0, - "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); + "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret); } @@ -505,7 +505,7 @@ int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_t AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); - while(L1_proc_tx->instance_cnt == 0){ + while(L1_proc_tx->instance_cnt == 0) { pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex); } @@ -521,7 +521,7 @@ int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_t VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0); - + // the thread can now be woken up // the thread can now be woken up AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n"); @@ -541,11 +541,11 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { int time_ns = 50000; AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); - for (i=0;i<gNB->num_RU;i++) { + for (i=0; i<gNB->num_RU; i++) { if (ru == gNB->RU_list[i]) { if ((proc->RU_mask&(1<<i)) > 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); + LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", + gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); proc->RU_mask |= (1<<i); } } @@ -572,16 +572,16 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret); if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); - LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); - return(-1); + AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); + LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); + return(-1); } - + ++L1_proc->instance_cnt; - - // 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 + // 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+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti, // and proc->slot_tx = proc->slot_rx+sf_ahead @@ -601,7 +601,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { exit_fun( "ERROR pthread_cond_signal" ); return(-1); } - + return(0); } /* @@ -705,9 +705,9 @@ static void* gNB_thread_prach( void* param ) { extern void init_td_thread(PHY_VARS_gNB *); extern void init_te_thread(PHY_VARS_gNB *); -static void* process_stats_thread(void* param) { +static void *process_stats_thread(void *param) { - PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)param; + PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; reset_meas(&gNB->dlsch_encoding_stats); reset_meas(&gNB->dlsch_scrambling_stats); diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 337502d6cb2aa84c73b8c935fcb78dd78982499d..a6970973a648fd0c368123814f55d10ddd952c3c 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -91,7 +91,7 @@ unsigned short config_frames[4] = {2,9,11,13}; static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; static int DEFBFW[] = {0x00007fff}; - + //static int DEFNRBANDS[] = {7}; //static int DEFGNBS[] = {0}; @@ -711,7 +711,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; nfapi_nr_config_request_scf_t *cfg = &ru->gNB_list[0]->gNB_config; @@ -882,7 +882,7 @@ void *ru_thread_prach( void *param ) { 0,0 ); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; } @@ -1109,16 +1109,16 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { } } else if(N_RB == 106) { if (fp->threequarter_fs) { - cfg->sample_rate=46.08e6; - cfg->samples_per_frame = 460800; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; } else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; } } else { AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); @@ -1240,7 +1240,7 @@ void *ru_stats_thread(void *param) { if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); - if (ru->feptx_ofdm){ + if (ru->feptx_ofdm) { print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL); print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); @@ -1249,7 +1249,7 @@ void *ru_stats_thread(void *param) { if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); - print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); + print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); if (ru->fh_north_out) { print_meas(&ru->compression,"compression",NULL,NULL); print_meas(&ru->transport,"transport",NULL,NULL); @@ -1380,7 +1380,7 @@ void *ru_thread_tx( void *param ) { L1_proc->instance_cnt_RUs = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, - "ERROR pthread_cond_signal for gNB_L1_thread\n"); + "ERROR pthread_cond_signal for gNB_L1_thread\n"); } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); @@ -2293,7 +2293,7 @@ void RCconfig_RU(void) } } else { - RC.ru[j]->openair0_cfg.clock_source = unset; + RC.ru[j]->openair0_cfg.clock_source = unset; } if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 1146d281b02cf8c76470223ebe1f669ec0be670f..6dd3807f3cc1f5a92ff0aee0b30b9e3d80fe4806 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -106,7 +106,7 @@ static int wait_for_sync = 0; unsigned int mmapped_dma=0; int single_thread_flag=1; -static int8_t threequarter_fs=0; +int8_t threequarter_fs=0; uint64_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; @@ -169,6 +169,10 @@ uint32_t target_ul_mcs = 20; uint32_t timing_advance = 0; uint64_t num_missed_slots=0; // counter for the number of missed slots +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} extern void reset_opp_meas(void); extern void print_opp_meas(void); @@ -719,13 +723,9 @@ int restart_L1L2(module_id_t gnb_id) { memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id]->frame_parms, sizeof(NR_DL_FRAME_PARMS)); set_function_spec_param(RC.ru[gnb_id]); LOG_I(GNB_APP, "attempting to create ITTI tasks\n"); - - if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { - LOG_E(RRC, "Create task for RRC eNB failed\n"); - return -1; - } else { - LOG_I(RRC, "Re-created task for RRC gNB successfully\n"); - } + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) { LOG_E(PDCP, "Create task for L2L1 failed\n"); @@ -768,23 +768,23 @@ static void wait_nfapi_init(char *thread_name) { void init_pdcp(void) { //if (!NODE_IS_DU(RC.rrc[0]->node_type)) { - pdcp_layer_init(); - uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? - (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; - if (IS_SOFTMODEM_NOS1){ - printf("IS_SOFTMODEM_NOS1 option enabled \n"); - pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; - } + if (IS_SOFTMODEM_NOS1) { + printf("IS_SOFTMODEM_NOS1 option enabled \n"); + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; + } - pdcp_module_init(pdcp_initmask); + pdcp_module_init(pdcp_initmask); - /*if (NODE_IS_CU(RC.rrc[0]->node_type)) { - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); - } else {*/ - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); - pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); - //} + /*if (NODE_IS_CU(RC.rrc[0]->node_type)) { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + } else {*/ + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); + //} /*} else { pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); }*/ @@ -838,7 +838,7 @@ int main( int argc, char **argv ) MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); -init_opt(); + init_opt(); #ifdef PDCP_USE_NETLINK @@ -855,7 +855,7 @@ if(!IS_SOFTMODEM_NOS1) LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); if(IS_SOFTMODEM_NOS1) - init_pdcp(); + init_pdcp(); if (RC.nb_nr_inst > 0) { // don't create if node doesn't connect to RRC/S1/GTP @@ -985,27 +985,27 @@ if(!IS_SOFTMODEM_NOS1) printf("oai_exit=%d\n",oai_exit); // stop threads -/*#ifdef XFORMS + /*#ifdef XFORMS - printf("waiting for XFORMS thread\n"); + printf("waiting for XFORMS thread\n"); - if (do_forms==1) { - pthread_join(forms_thread,&status); - fl_hide_form(form_stats->stats_form); - fl_free_form(form_stats->stats_form); + if (do_forms==1) { + pthread_join(forms_thread,&status); + fl_hide_form(form_stats->stats_form); + fl_free_form(form_stats->stats_form); - fl_hide_form(form_stats_l2->stats_form); - fl_free_form(form_stats_l2->stats_form); + fl_hide_form(form_stats_l2->stats_form); + fl_free_form(form_stats_l2->stats_form); - for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) { - for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { - fl_hide_form(form_enb[CC_id][UE_id]->phy_scope_gNB); - fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB); - } - } - } + for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) { + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + fl_hide_form(form_enb[CC_id][UE_id]->phy_scope_gNB); + fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB); + } + } + } -#endif*/ + #endif*/ printf("stopping MODEM threads\n"); // cleanup stop_gNB(NB_gNB_INST); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 131710ee0208f5c3dab6c59dc055269c28d37d53..a0251b26dffae81cb2dd09ac059d087c7e0f81eb 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -146,7 +146,7 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, ue->Mod_id = UE_id; ue->mac_enabled = 1; - + // initialize all signal buffers // initialize all signal buffers init_nr_ue_signal(ue,1,abstraction_flag); // intialize transport @@ -471,7 +471,7 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { } } - + // no UL for now // no UL for now /* if (UE->mac_enabled==1) { @@ -508,7 +508,7 @@ void UE_processing(void *arg) { PHY_VARS_NR_UE *UE = rxtxD->UE; uint8_t gNB_id = 0; - + // params for UL time alignment procedure // params for UL time alignment procedure NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &UE->ul_time_alignment[gNB_id]; uint8_t numerology = UE->frame_parms.numerology_index; @@ -521,9 +521,9 @@ void UE_processing(void *arg) { // then timing advance is processed and set to be applied in the next UL transmission */ if (UE->mac_enabled == 1) { - if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot){ + if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) { LOG_D(PHY,"Applying timing advance -- frame %d -- slot %d\n", frame_tx, slot_tx); - + //if (nfapi_mode!=3){ //if (nfapi_mode!=3){ nr_process_timing_advance(UE->Mod_id, UE->CC_id, ul_time_alignment->ta_command, numerology, bwp_ul_NB_RB); ul_time_alignment->ta_frame = -1; @@ -590,8 +590,8 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { - LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); - void *dummy_tx[UE->frame_parms.nb_antennas_tx]; + LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); + void *dummy_tx[UE->frame_parms.nb_antennas_tx]; *timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms); for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { @@ -753,7 +753,7 @@ void *UE_thread(void *arg) { #ifdef OAI_ADRV9371_ZC706 /*uint32_t total_gain_dB_prev = 0; if (total_gain_dB_prev != UE->rx_total_gain_dB) { - total_gain_dB_prev = UE->rx_total_gain_dB; + total_gain_dB_prev = UE->rx_total_gain_dB; openair0_cfg[0].rx_gain[0] = UE->rx_total_gain_dB; UE->rfdevice.trx_set_gains_func(&UE->rfdevice,&openair0_cfg[0]); }*/ diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 09b2c943be05404e3237f850f2e636745c190015..9b2b704833fb878ed5f9796892bb8f9811584f5a 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -213,7 +213,7 @@ int emulate_rf = 0; tpool_t *Tpool; #ifdef UE_DLSCH_PARALLELISATION -tpool_t *Tpool_dl; + tpool_t *Tpool_dl; #endif @@ -309,8 +309,8 @@ static void *scope_thread(void *arg) { while (!oai_exit) { phy_scope_nrUE(form_nrue[0], - PHY_vars_UE_g[0][0], - 0,0,1); + PHY_vars_UE_g[0][0], + 0,0,1); usleep(100*1000); } @@ -381,9 +381,9 @@ static void get_options(void) { int tddflag=0, nonbiotflag, vcdflag=0; char *loopfile=NULL; int dumpframe=0; - //uint32_t noS1; //uint32_t nokrnmod; + //uint32_t nokrnmod; paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC_UE ; config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); @@ -527,12 +527,12 @@ void init_openair0(void) { else { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; - } + } } else { LOG_E(PHY,"Unsupported numerology!\n"); exit(-1); } - }else if(frame_parms[0]->N_RB_DL == 273) { + } else if(frame_parms[0]->N_RB_DL == 273) { if (numerology==1) { if (frame_parms[0]->threequarter_fs) { AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); @@ -540,12 +540,12 @@ void init_openair0(void) { else { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; - } + } } else { LOG_E(PHY,"Unsupported numerology!\n"); exit(-1); } - }else if(frame_parms[0]->N_RB_DL == 106) { + } else if(frame_parms[0]->N_RB_DL == 106) { if (numerology==0) { if (frame_parms[0]->threequarter_fs) { openair0_cfg[card].sample_rate=23.04e6; @@ -554,15 +554,15 @@ void init_openair0(void) { openair0_cfg[card].sample_rate=30.72e6; openair0_cfg[card].samples_per_frame = 307200; } - } else if (numerology==1) { + } else if (numerology==1) { if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=46.08e6; - openair0_cfg[card].samples_per_frame = 460800; + openair0_cfg[card].sample_rate=46.08e6; + openair0_cfg[card].samples_per_frame = 460800; } else { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } + openair0_cfg[card].sample_rate=61.44e6; + openair0_cfg[card].samples_per_frame = 614400; + } } else if (numerology==2) { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; @@ -638,7 +638,7 @@ void init_pdcp(void) { pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT; /*if (rlc_module_init() != 0) { - LOG_I(RLC, "Problem at RLC initiation \n"); + LOG_I(RLC, "Problem at RLC initiation \n"); } pdcp_layer_init(); nr_ip_over_LTE_DRB_preconfiguration();*/ @@ -648,6 +648,11 @@ void init_pdcp(void) { LOG_I(PDCP, "Before getting out from init_pdcp() \n"); } +// Stupid function addition because UE itti messages queues definition is common with eNB +void *rrc_enb_process_msg(void *notUsed) { + return NULL; +} + int main( int argc, char **argv ) { //uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; @@ -675,12 +680,12 @@ int main( int argc, char **argv ) { set_taus_seed (0); tpool_t pool; Tpool = &pool; - char params[]="-1,-1"; + char params[]="-1,-1"; initTpool(params, Tpool, false); #ifdef UE_DLSCH_PARALLELISATION tpool_t pool_dl; Tpool_dl = &pool_dl; - char params_dl[]="-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1"; + char params_dl[]="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"; initTpool(params_dl, Tpool_dl, false); #endif cpuf=get_cpu_freq_GHz(); diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index f714fa2bd4b0612f503259938c4430336d7b0a9b..04a58413b5a1b9f29a6d6c4626b3d648d9f4128e 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -81,8 +81,8 @@ char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr) { } void get_common_options(uint32_t execmask) { - uint32_t online_log_messages; - uint32_t glog_level ; + uint32_t online_log_messages=0; + uint32_t glog_level=0 ; uint32_t start_telnetsrv = 0; uint32_t noS1 = 0, nokrnmod = 0, nonbiot = 0; uint32_t rfsim = 0, basicsim = 0, do_forms = 0; @@ -145,27 +145,27 @@ void get_common_options(uint32_t execmask) { if(worker_config != NULL) set_worker_conf(worker_config); } void softmodem_printresources(int sig, telnet_printfunc_t pf) { - struct rusage usage; - struct timespec stop; - - clock_gettime(CLOCK_BOOTTIME, &stop); - - uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds - - - int st = getrusage(RUSAGE_SELF,&usage); - if (!st) { - pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600))); - pf("\tTime executing user inst.: %lds %ldus\n",(long)usage.ru_utime.tv_sec,(long)usage.ru_utime.tv_usec); - pf("\tTime executing system inst.: %lds %ldus\n",(long)usage.ru_stime.tv_sec,(long)usage.ru_stime.tv_usec); - pf("\tMax. Phy. memory usage: %ldkB\n",(long)usage.ru_maxrss); - pf("\tPage fault number (no io): %ld\n",(long)usage.ru_minflt); - pf("\tPage fault number (requiring io): %ld\n",(long)usage.ru_majflt); - pf("\tNumber of file system read: %ld\n",(long)usage.ru_inblock); - pf("\tNumber of filesystem write: %ld\n",(long)usage.ru_oublock); - pf("\tNumber of context switch (process origin, io...): %ld\n",(long)usage.ru_nvcsw); - pf("\tNumber of context switch (os origin, priority...): %ld\n",(long)usage.ru_nivcsw); - } + struct rusage usage; + struct timespec stop; + + clock_gettime(CLOCK_BOOTTIME, &stop); + + uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds + + + int st = getrusage(RUSAGE_SELF,&usage); + if (!st) { + pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600))); + pf("\tTime executing user inst.: %lds %ldus\n",(long)usage.ru_utime.tv_sec,(long)usage.ru_utime.tv_usec); + pf("\tTime executing system inst.: %lds %ldus\n",(long)usage.ru_stime.tv_sec,(long)usage.ru_stime.tv_usec); + pf("\tMax. Phy. memory usage: %ldkB\n",(long)usage.ru_maxrss); + pf("\tPage fault number (no io): %ld\n",(long)usage.ru_minflt); + pf("\tPage fault number (requiring io): %ld\n",(long)usage.ru_majflt); + pf("\tNumber of file system read: %ld\n",(long)usage.ru_inblock); + pf("\tNumber of filesystem write: %ld\n",(long)usage.ru_oublock); + pf("\tNumber of context switch (process origin, io...): %ld\n",(long)usage.ru_nvcsw); + pf("\tNumber of context switch (os origin, priority...): %ld\n",(long)usage.ru_nivcsw); + } } void signal_handler(int sig) { @@ -180,9 +180,9 @@ void signal_handler(int sig) { backtrace_symbols_fd(array, size, 2); exit(-1); } else { - if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL) - softmodem_printresources(sig,(telnet_printfunc_t)printf); - if (sig != SOFTMODEM_RTSIGNAL) { + if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL) + softmodem_printresources(sig,(telnet_printfunc_t)printf); + if (sig != SOFTMODEM_RTSIGNAL) { printf("Linux signal %s...\n",strsignal(sig)); exit_function(__FILE__, __FUNCTION__, __LINE__,"softmodem starting exit procedure\n"); } @@ -192,7 +192,7 @@ void signal_handler(int sig) { void set_softmodem_sighandler(void) { - struct sigaction act,oldact; + struct sigaction act,oldact; clock_gettime(CLOCK_BOOTTIME, &start); memset(&act,0,sizeof(act)); act.sa_handler=signal_handler; @@ -201,6 +201,6 @@ void set_softmodem_sighandler(void) { signal(SIGSEGV, signal_handler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); - signal(SIGABRT, signal_handler); + signal(SIGABRT, signal_handler); } diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 2fac7d825e170adb9b2bfda261f1eed532a0c91b..0ac7b6449e553ed8fce94dc99ff6d35bed579815 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -38,6 +38,11 @@ extern "C" #endif /* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ #define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" +#define CONFIG_HLP_SPLIT73 "Split 7.3 (below rate matching) option: <cu|du>:<remote ip address>:<remote port>" +#define CONFIG_HLP_TPOOL "Thread pool configuration: \n\ + default no pool (runs in calling thread),\n\ + list of cores, comma separated (negative value is no core affinity)\n\ + example: -1,3 launches two working threads one floating, the second set on core 3" #define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n" #define CONFIG_HLP_CALUER "set UE RX calibration\n" #define CONFIG_HLP_CALUERM "" @@ -89,6 +94,8 @@ extern "C" /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------------------*/ #define RF_CONFIG_FILE softmodem_params.rf_config_file +#define SPLIT73 softmodem_params.split73 +#define TP_CONFIG softmodem_params.threadPoolConfig #define PHY_TEST softmodem_params.phy_test #define WAIT_FOR_SYNC softmodem_params.wait_for_sync #define SINGLE_THREAD_FLAG softmodem_params.single_thread_flag @@ -104,6 +111,8 @@ extern "C" #define CMDLINE_PARAMS_DESC { \ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\ + {"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)},\ + {"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \ {"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ @@ -193,6 +202,8 @@ typedef struct { uint64_t optmask; //THREAD_STRUCT thread_struct; char rf_config_file[1024]; + char split73[1024]; + char threadPoolConfig[1024]; int phy_test; uint8_t usim_test; int emulate_rf; diff --git a/executables/split_headers.h b/executables/split_headers.h new file mode 100644 index 0000000000000000000000000000000000000000..62293c73697497b243d834b39750d954585db55b --- /dev/null +++ b/executables/split_headers.h @@ -0,0 +1,309 @@ +/* + Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX + copyleft: OpenAirInterface Software Alliance and it's licence +*/ +#ifndef __SPLIT_HEADERS_H +#define __SPLIT_HEADERS_H + +#include <stdint.h> +#include <stdbool.h> +#include <openair1/PHY/defs_eNB.h> + +#define CU_PORT "7878" +#define DU_PORT "8787" +#define SPLIT73_CU 1 +#define SPLIT73_DU 2 +extern int split73; + +#define MTU 65536 +#define UDP_TIMEOUT 900000L // in micro second (struct timeval, NOT struct timespec) +// linux may timeout for a much longer time (up to 10ms) +#define blockAlign 32 //bytes to align memory for SIMD copy (256 bits vectors) + +// FS6 transport configuration and handler +typedef struct { + char *sourceIP; + char *sourcePort; + char *destIP; + char *destPort; + struct addrinfo *destAddr; + int sockHandler; +} UDPsock_t; + +#define CTsentCUv0 0xA500 +#define CTsentDUv0 0x5A00 + +// Main FS6 transport layer header +// All packets starts with this header +typedef struct commonUDP_s { + uint64_t timestamp; // id of the group (subframe for LTE) + uint16_t nbBlocks; // total number of blocks for this timestamp + uint16_t blockID; // id: 0..nbBocks-1 + uint16_t contentType; // defines the content format + uint16_t contentBytes; // will be sent in a UDP packet, so must be < 2^16 bytes + uint64_t senderClock; +} commonUDP_t; + +// FS6 UL common header (DU to CU) +// gives the RACH detection data and is always sent to inform the CU that a subframe arrived +typedef struct { + uint16_t max_preamble[4]; + uint16_t max_preamble_energy[4]; + uint16_t max_preamble_delay[4]; + uint16_t avg_preamble_energy[4]; +} fs6_ul_t; + +// FS6 DL common header (CU to DU) +// gives the DCI configuration from each subframe +typedef struct { + uint8_t pbch_pdu[4]; + int num_pdcch_symbols; + int num_dci; + DCI_ALLOC_t dci_alloc[8]; + int num_mdci; + int amp; + LTE_eNB_PHICH phich_vars; + uint64_t DuClock; + uint64_t CuSpentMicroSec; +} fs6_dl_t; + +// a value to type all sub packets, +// to detect errors, and to be able to extend to other versions +// the first byte of each sub structure should match one of these values +enum pckType { + fs6UlConfig=25, + fs6DlConfig=26, + fs6ULConfigCCH=27, + fs6ULsch=28, + fs6ULcch=29, + fs6ULindicationHarq=40, + fs6ULindicationSr=41, +}; + +// CU to DU definition of a future UL subframe decode +// defines a UE future data plane +typedef struct { + enum pckType type:8; + uint16_t UE_id; + int8_t harq_pid; + UE_type_t ue_type; + + uint8_t dci_alloc; + uint8_t rar_alloc; + SCH_status_t status; + uint8_t Msg3_flag; + uint8_t subframe; + uint32_t frame; + uint8_t handled; + uint8_t phich_active; + uint8_t phich_ACK; + uint16_t previous_first_rb; + uint32_t B; + uint32_t G; + UCI_format_t uci_format; + uint8_t Or2; + uint8_t o_RI[2]; + uint8_t o_ACK[4]; + uint8_t O_ACK; + uint8_t o_RCC; + int16_t q_ACK[MAX_ACK_PAYLOAD]; + int16_t q_RI[MAX_RI_PAYLOAD]; + uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; + uint8_t ndi; + uint8_t round; + uint8_t rvidx; + uint8_t Nl; + uint8_t n_DMRS; + uint8_t previous_n_DMRS; + uint8_t n_DMRS2; + int32_t delta_TF; + uint32_t repetition_number ; + uint32_t total_number_of_repetitions; + + uint16_t harq_mask; + uint16_t nb_rb; + uint8_t Qm; + uint16_t first_rb; + uint8_t O_RI; + uint8_t Or1; + uint16_t Msc_initial; + uint8_t Nsymb_initial; + uint8_t V_UL_DAI; + uint8_t srs_active; + uint32_t TBS; + uint8_t Nsymb_pusch; + uint8_t Mlimit; + uint8_t max_turbo_iterations; + uint8_t bundling; + uint16_t beta_offset_cqi_times8; + uint16_t beta_offset_ri_times8; + uint16_t beta_offset_harqack_times8; + uint8_t Msg3_active; + uint16_t rnti; + uint8_t cyclicShift; + uint8_t cooperation_flag; + uint8_t num_active_cba_groups; + uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP]; +} fs6_dl_ulsched_t; + +// CU to DU defintion of a DL packet for a given UE +// The data itself is padded at the end of this structure +typedef struct { + enum pckType type:8; + int UE_id; + int8_t harq_pid; + uint16_t rnti; + int16_t sqrt_rho_a; + int16_t sqrt_rho_b; + CEmode_t CEmode:8; + uint16_t nb_rb; + uint8_t Qm; + int8_t Nl; + uint8_t pdsch_start; + uint8_t sib1_br_flag; + uint16_t i0; + uint32_t rb_alloc[4]; + int dataLen; +} fs6_dl_uespec_t; + +// CU to DU definition of CCH channel +typedef struct { + int16_t UE_id; + LTE_eNB_UCI cch_vars; +} fs6_dl_uespec_ulcch_element_t; + +// header to group all UE CCH channels definitions in one UDP packet +typedef struct { + enum pckType type:8; + int16_t nb_active_ue; +} fs6_dl_uespec_ulcch_t; + +// code internal, not transmitted as this +typedef struct { + int ta; +} ul_propagation_t; + +// One UE UL data, data plane, UE data appended after the header +typedef struct { + enum pckType type:8; + short UE_id; + uint8_t harq_id; + uint8_t segment; + int segLen; + int r_offset; + int G; + int ulsch_power[2]; + uint8_t o_ACK[4]; + uint8_t O_ACK; + int ta; + uint8_t o[MAX_CQI_BYTES]; + uint8_t cqi_crc_status; +} fs6_ul_uespec_t; + +// UL UCI (control plane), per UE +typedef struct { + enum pckType type:8; + int UEid; + int frame; + int subframe; + LTE_eNB_UCI uci; + uint8_t harq_ack[4]; + uint8_t tdd_mapping_mode; + uint16_t tdd_multiplexing_mask; + unsigned short n0_subband_power_dB; + uint16_t rnti; + int32_t stat; +} fs6_ul_uespec_uci_element_t; + +// all segments UCI grouped in one UDP packet +typedef struct { + enum pckType type:8; + int16_t nb_active_ue; +} fs6_ul_uespec_uci_t; + + +bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); +int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType); +int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType); + +#define initBufferZone(xBuf) \ + uint8_t xBuf[FS6_BUF_SIZE]; \ + ((commonUDP_t *)xBuf)->nbBlocks=0; + +#define hUDP(xBuf) ((commonUDP_t *)xBuf) +#define hDL(xBuf) ((fs6_dl_t*)(((commonUDP_t *)xBuf)+1)) +#define hUL(xBuf) ((fs6_ul_t*)(((commonUDP_t *)xBuf)+1)) +#define hDLUE(xBuf) ((fs6_dl_uespec_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hTxULUE(xBuf) ((fs6_dl_ulsched_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hTxULcch(xBuf) ((fs6_dl_uespec_ulcch_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hULUE(xBuf) ((fs6_ul_uespec_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hULUEuci(xBuf) ((fs6_ul_uespec_uci_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1)) + +static inline size_t alignedSize(uint8_t *ptr) { + commonUDP_t *header=(commonUDP_t *) ptr; + return ((header->contentBytes+sizeof(commonUDP_t)+blockAlign-1)/blockAlign)*blockAlign; +} + +static inline void *commonUDPdata(uint8_t *ptr) { + return (void *) (((commonUDP_t *)ptr)+1); +} + +void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc); +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, + uint16_t rnti, int32_t stat); +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset); +void *cu_fs6(void *arg); +void *du_fs6(void *arg); +void fill_rf_config(RU_t *ru, char *rf_config_file); +int init_rf(RU_t *ru); +void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc); +void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); +void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); +void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); +bool dlsch_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int harq_pid, + LTE_eNB_DLSCH_t *dlsch, + LTE_eNB_UE_stats *ue_stats) ; +void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req); +void pdsch_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int harq_pid, + LTE_eNB_DLSCH_t *dlsch, + LTE_eNB_DLSCH_t *dlsch1); +void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); +void uci_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc); +void ocp_rx_prach(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + RU_t *ru, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t *avg_preamble_energy, + uint16_t Nf, + uint8_t tdd_mapindex, + uint8_t br_flag); +void rx_prach0(PHY_VARS_eNB *eNB, + RU_t *ru, + int frame_prach, + int subframe, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t *avg_preamble_energy, + uint16_t Nf, + uint8_t tdd_mapindex, + uint8_t br_flag, + uint8_t ce_level + ); +void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); + +// mistakes in main OAI +void phy_init_RU(RU_t *); +void fep_full(RU_t *ru, int subframe); +void feptx_prec(RU_t *ru,int frame,int subframe); +void feptx_ofdm(RU_t *ru, int frame, int subframe); +void oai_subframe_ind(uint16_t sfn, uint16_t sf); +extern uint16_t sf_ahead; +#endif diff --git a/executables/transport_split.c b/executables/transport_split.c new file mode 100644 index 0000000000000000000000000000000000000000..7a1ee3e85ea0e4c703e45c26a2b97c32d6db5a01 --- /dev/null +++ b/executables/transport_split.c @@ -0,0 +1,174 @@ +/* + Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX + copyleft: OpenAirInterface Software Alliance and it's licence +*/ +#include <executables/split_headers.h> +#include <sys/types.h> /* See NOTES */ +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/udp.h> +#include <netdb.h> +#include <targets/RT/USER/lte-softmodem.h> + +bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result) { + struct addrinfo hints= {0}, *servinfo, *p; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; + int status; + + if ((status = getaddrinfo(sourceIP, sourcePort, &hints, &servinfo)) != 0) { + LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); + return false; + } + + // loop through all the results and bind to the first we can + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((result->sockHandler = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + LOG_W(GTPU,"socket: %s\n", strerror(errno)); + continue; + } + + if (bind(result->sockHandler, p->ai_addr, p->ai_addrlen) == -1) { + close(result->sockHandler); + LOG_W(GTPU,"bind: %s\n", strerror(errno)); + continue; + } + + break; // if we get here, we must have connected successfully + } + + if (p == NULL) { + // looped off the end of the list with no successful bind + LOG_E(GTPU,"failed to bind socket: %s %s \n",sourceIP,sourcePort); + return false; + } + + freeaddrinfo(servinfo); // all done with this structure + + if ((status = getaddrinfo(destIP, destPort, &hints, &servinfo)) != 0) { + LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); + return false; + } + + if (servinfo) { + result->destAddr=servinfo; + } else { + LOG_E(PHY,"No valid UDP addr: %s:%s\n",destIP, destPort); + return false; + } + + int enable=1; + AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); + struct timeval tv= {0,UDP_TIMEOUT}; + + if (IS_SOFTMODEM_RFSIM) + tv.tv_sec=2; //debug: wait 2 seconds for human understanding + + AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); + // Make a send/recv buffer larger than a a couple of subframe + // so the kernel will store for us in and out paquets + int buff=1000*1000*10; + AssertFatal ( setsockopt(result->sockHandler, SOL_SOCKET, SO_SNDBUF, &buff, sizeof(buff)) == 0, ""); + AssertFatal ( setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVBUF, &buff, sizeof(buff)) == 0, ""); + return true; +} + +// sock: udp socket +// bufferZone: a reception area of bufferSize +int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType) { + int rcved=0; + commonUDP_t *bufOrigin=(commonUDP_t *)bufferZone; + static uint8_t crossData[65536]; + static int crossDataSize=0; + + if (crossDataSize) { + LOG_D(HW,"copy a block received in previous subframe\n"); + memcpy(bufferZone, crossData, crossDataSize); + rcved=1; + bufferZone+=crossDataSize; + crossDataSize=0; + } + + do { + //read all subframe data from the control unit + int ret=recv(sock->sockHandler, bufferZone, bufferSize, 0); + + if ( ret==-1) { + if ( errno == EWOULDBLOCK || errno== EINTR ) { + LOG_I(HW,"Received: Timeout, subframe incomplete\n"); + return rcved; + } else { + LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno)); + return -1; + } + } else { + if (hUDP(bufferZone)->contentType != contentType) + abort(); + + if (rcved && bufOrigin->timestamp != hUDP(bufferZone)->timestamp ) { + if ( hUDP(bufferZone)->timestamp > bufOrigin->timestamp ) { + LOG_W(HW,"Received data for TS: %lu before end of TS : %lu completion\n", + hUDP(bufferZone)->timestamp, + bufOrigin->timestamp); + memcpy(crossData, bufferZone, ret ); + crossDataSize=ret; + return rcved; + } else { + LOG_W(HW,"Dropping late packet\n"); + continue; + } + } + + rcved++; + bufferZone+=ret; + } + + LOG_D(HW,"Received: blocks: %d/%d, size %d, TS: %lu\n", + rcved, bufOrigin->nbBlocks, ret, bufOrigin->timestamp); + } while ( rcved == 0 || rcved < bufOrigin->nbBlocks ); + + return rcved; +} + +int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType) { + commonUDP_t *UDPheader=(commonUDP_t *)bufferZone ; + UDPheader->contentType=contentType; + UDPheader->senderClock=rdtsc(); + int nbBlocks=UDPheader->nbBlocks; + int blockId=0; + + if (nbBlocks <= 0 ) { + LOG_E(PHY,"FS6: can't send blocks: %d\n", nbBlocks); + return 0; + } + + do { + if (blockId > 0 ) { + commonUDP_t *currentHeader=(commonUDP_t *)bufferZone; + currentHeader->timestamp=UDPheader->timestamp; + currentHeader->nbBlocks=UDPheader->nbBlocks; + currentHeader->blockID=blockId; + currentHeader->contentType=UDPheader->contentType; + memcpy(commonUDPdata((void *)currentHeader), commonUDPdata(bufferZone), secondHeaderSize); + } + + blockId++; + int sz=alignedSize(bufferZone); + // Let's use the first address returned by getaddrinfo() + int ret=sendto(sock->sockHandler, bufferZone, sz, 0, + sock->destAddr->ai_addr, sock->destAddr->ai_addrlen); + + if ( ret != sz ) + LOG_W(HW,"Wrote socket doesn't return size %d (val: %d, errno:%d, %s)\n", + sz, ret, errno, strerror(errno)); + + LOG_D(HW,"Sent: TS: %lu, blocks %d/%d, block size : %d \n", + UDPheader->timestamp, UDPheader->nbBlocks-nbBlocks, UDPheader->nbBlocks, sz); + bufferZone+=sz; + nbBlocks--; + } while (nbBlocks); + + return 0; +} diff --git a/nfapi/oai_integration/nfapi.c b/nfapi/oai_integration/nfapi.c index 4fc35fd951309bae126a53bf4818cfc7ccdf1352..86d1ae3127d33c13c71977c43c950830feb1ecdd 100644 --- a/nfapi/oai_integration/nfapi.c +++ b/nfapi/oai_integration/nfapi.c @@ -29,7 +29,7 @@ typedef struct { nfapi_mode_t nfapi_mode; } nfapi_params_t; -static nfapi_params_t nfapi_params; +static nfapi_params_t nfapi_params = {0}; void set_thread_priority(int priority) { //printf("%s(priority:%d)\n", __FUNCTION__, priority); diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index 481c4105616d2cfa9746e36e055fa47ab58a9f20..59857659c13fe506714210bca0212a4079c5caf0 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -691,13 +691,14 @@ void pnf_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) { free(header); } -int pnf_phy_hi_dci0_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { +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) LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); //phy_info* phy = (phy_info*)(pnf_p7->user_data); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; + if (proc ==NULL) + proc = &eNB->proc.L1_proc; for (int i=0; i<req->hi_dci0_request_body.number_of_dci + req->hi_dci0_request_body.number_of_hi; i++) { //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); @@ -718,7 +719,7 @@ int pnf_phy_hi_dci0_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t * return 0; } -int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { +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.ru == 0) { return -1; } @@ -739,7 +740,8 @@ int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request int sfn = NFAPI_SFNSF2SFN(req->sfn_sf); int sf = NFAPI_SFNSF2SF(req->sfn_sf); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; + if (proc==NULL) + proc = &eNB->proc.L1_proc; nfapi_dl_config_request_pdu_t *dl_config_pdu_list = req->dl_config_request_body.dl_config_pdu_list; LTE_eNB_PDCCH *pdcch_vars = &eNB->pdcch_vars[sf&1]; pdcch_vars->num_pdcch_symbols = req->dl_config_request_body.number_pdcch_ofdm_symbols; @@ -796,7 +798,7 @@ int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request uint8_t *dlsch_sdu = tx_pdus[UE_id][harq_pid]; memcpy(dlsch_sdu, tx_pdu->segments[0].segment_data, tx_pdu->segments[0].segment_length); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols); - handle_nfapi_dlsch_pdu( eNB, sfn,sf, &eNB->proc.L1_proc, &dl_config_pdu_list[i], rel8_pdu->transport_blocks-1, dlsch_sdu); + handle_nfapi_dlsch_pdu( eNB, sfn,sf, proc, &dl_config_pdu_list[i], rel8_pdu->transport_blocks-1, dlsch_sdu); } else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), rel8_pdu->pdu_index); } @@ -836,7 +838,7 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { return 0; } -int pnf_phy_ul_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { +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__, NFAPI_SFNSF2DEC(req->sfn_sf), @@ -865,7 +867,8 @@ int pnf_phy_ul_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request uint16_t curr_sfn = NFAPI_SFNSF2SFN(req->sfn_sf); uint16_t curr_sf = NFAPI_SFNSF2SF(req->sfn_sf); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; + if (proc==NULL) + proc = &eNB->proc.L1_proc; nfapi_ul_config_request_pdu_t *ul_config_pdu_list = req->ul_config_request_body.ul_config_pdu_list; for (int i=0; i<req->ul_config_request_body.number_of_pdus; i++) { diff --git a/nfapi/oai_integration/nfapi_pnf.h b/nfapi/oai_integration/nfapi_pnf.h index e213d785f14ef1c94a41cb61a058d25e7982b6e4..2c8201737c8642a9b25bf9238c70465b1d4fdb7e 100644 --- a/nfapi/oai_integration/nfapi_pnf.h +++ b/nfapi/oai_integration/nfapi_pnf.h @@ -23,5 +23,5 @@ #define NFAPI_PNF_H__ int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); void configure_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); #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h index 5fe1c53a54622d3db9e85bc391b2ff141a8ba805..650bda4f780138874f71ee40ee3b5098fb0d81e1 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h @@ -10,6 +10,7 @@ #define _NFAPI_NR_INTERFACE_H_ #include "nfapi_interface.h" +#include <nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h> #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 #define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 diff --git a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h index 8d17416a418a98a822494726b1f1261aa1f66e54..d169177d6b182eeae05d4290c1fa88e3248cd1c7 100644 --- a/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h +++ b/nfapi/open-nFAPI/pnf/public_inc/nfapi_pnf_interface.h @@ -24,6 +24,7 @@ extern "C" { #include "nfapi_interface.h" #include "debug.h" +#include <openair2/PHY_INTERFACE/IF_Module.h> #include <sys/types.h> @@ -619,21 +620,21 @@ typedef struct nfapi_pnf_p7_config * \param req A pointer to the dl config request message structure * \return not currently used */ - int (*dl_config_req)(nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req); + int (*dl_config_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_dl_config_request_t* req); /*! A callback for the UL_CONFIG.request * \param config A poiner to the PNF P7 config * \param req A pointer to the ul config request message structure * \return not currently used */ - int (*ul_config_req)(nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req); + int (*ul_config_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_ul_config_request_t* req); /*! A callback for the HI_DCI0.request * \param config A poiner to the PNF P7 config * \param req A pointer to the hi dci0 request message structure * \return not currently used */ - int (*hi_dci0_req)(nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); + int (*hi_dci0_req)(L1_rxtx_proc_t *proc,nfapi_pnf_p7_config_t* config, nfapi_hi_dci0_request_t* req); /*! A callback for the TX_REQ.request * \param config A poiner to the PNF P7 config diff --git a/nfapi/open-nFAPI/pnf/src/pnf_interface.c b/nfapi/open-nFAPI/pnf/src/pnf_interface.c index 7310fc0c66c57209bcedac7cc326ab4b19d4229a..dda0d0fdc60ce5f632b12962ac502877c72e9aff 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_interface.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_interface.c @@ -39,7 +39,7 @@ nfapi_pnf_config_t* nfapi_pnf_config_create() _this->_public.codec_config.allocate = &malloc; _this->_public.codec_config.deallocate = &free; - return &(_this->_public); + return (nfapi_pnf_config_t* )_this; } void nfapi_pnf_config_destory(nfapi_pnf_config_t* config) diff --git a/nfapi/open-nFAPI/pnf/src/pnf_p7.c b/nfapi/open-nFAPI/pnf/src/pnf_p7.c index 944673037500c6f8478b3352f0998f28e840cc07..5ba912e059f73b5c15b3d8e5a4e490ddc2000cd6 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf_p7.c +++ b/nfapi/open-nFAPI/pnf/src/pnf_p7.c @@ -576,20 +576,20 @@ void send_dummy_subframe(pnf_p7_t* pnf_p7, uint16_t sfn_sf) { pnf_p7->_public.dummy_subframe.dl_config_req->sfn_sf = sfn_sf; //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - enter\n"); - (pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req); + (pnf_p7->_public.dl_config_req)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req); //NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy dl_config_req - exit\n"); } if(pnf_p7->_public.ul_config_req && pnf_p7->_public.dummy_subframe.ul_config_req) { pnf_p7->_public.dummy_subframe.ul_config_req->sfn_sf = sfn_sf; NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy ul_config_req - enter\n"); - (pnf_p7->_public.ul_config_req)(&pnf_p7->_public, pnf_p7->_public.dummy_subframe.ul_config_req); + (pnf_p7->_public.ul_config_req)(NULL, &pnf_p7->_public, pnf_p7->_public.dummy_subframe.ul_config_req); } if(pnf_p7->_public.hi_dci0_req && pnf_p7->_public.dummy_subframe.hi_dci0_req) { pnf_p7->_public.dummy_subframe.hi_dci0_req->sfn_sf = sfn_sf; NFAPI_TRACE(NFAPI_TRACE_INFO, "Dummy hi_dci0 - enter\n"); - (pnf_p7->_public.hi_dci0_req)(&pnf_p7->_public, pnf_p7->_public.dummy_subframe.hi_dci0_req); + (pnf_p7->_public.hi_dci0_req)(NULL, &pnf_p7->_public, pnf_p7->_public.dummy_subframe.hi_dci0_req); } if(pnf_p7->_public.lbt_dl_config_req && pnf_p7->_public.dummy_subframe.lbt_dl_config_req) { @@ -699,7 +699,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(tx_subframe_buffer->dl_config_req != 0) { if(pnf_p7->_public.dl_config_req) - (pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), tx_subframe_buffer->dl_config_req); + (pnf_p7->_public.dl_config_req)(NULL, &(pnf_p7->_public), tx_subframe_buffer->dl_config_req); //deallocate_nfapi_dl_config_request(subframe_buffer->dl_config_req, pnf_p7); } @@ -709,14 +709,14 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(pnf_p7->_public.dl_config_req && pnf_p7->_public.dummy_subframe.dl_config_req) { pnf_p7->_public.dummy_subframe.dl_config_req->sfn_sf = sfn_sf_tx; - (pnf_p7->_public.dl_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req); + (pnf_p7->_public.dl_config_req)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_subframe.dl_config_req); } } if(tx_subframe_buffer->hi_dci0_req != 0) { if(pnf_p7->_public.hi_dci0_req) - (pnf_p7->_public.hi_dci0_req)(&(pnf_p7->_public), tx_subframe_buffer->hi_dci0_req); + (pnf_p7->_public.hi_dci0_req)(NULL, &(pnf_p7->_public), tx_subframe_buffer->hi_dci0_req); //deallocate_nfapi_hi_dci0_request(subframe_buffer->hi_dci0_req, pnf_p7); } @@ -726,7 +726,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(pnf_p7->_public.hi_dci0_req && pnf_p7->_public.dummy_subframe.hi_dci0_req) { pnf_p7->_public.dummy_subframe.hi_dci0_req->sfn_sf = sfn_sf_tx; - (pnf_p7->_public.hi_dci0_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.hi_dci0_req); + (pnf_p7->_public.hi_dci0_req)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_subframe.hi_dci0_req); } } @@ -777,7 +777,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(subframe_buffer->ul_config_req != 0) { if(pnf_p7->_public.ul_config_req) - (pnf_p7->_public.ul_config_req)(&(pnf_p7->_public), subframe_buffer->ul_config_req); + (pnf_p7->_public.ul_config_req)(NULL, &(pnf_p7->_public), subframe_buffer->ul_config_req); //deallocate_nfapi_ul_config_request(subframe_buffer->ul_config_req, pnf_p7); } @@ -787,7 +787,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf) if(pnf_p7->_public.ul_config_req && pnf_p7->_public.dummy_subframe.ul_config_req) { pnf_p7->_public.dummy_subframe.ul_config_req->sfn_sf = sfn_sf; - (pnf_p7->_public.ul_config_req)(&(pnf_p7->_public), pnf_p7->_public.dummy_subframe.ul_config_req); + (pnf_p7->_public.ul_config_req)(NULL, &(pnf_p7->_public), pnf_p7->_public.dummy_subframe.ul_config_req); } } diff --git a/nfapi/open-nFAPI/vnf/src/vnf_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_interface.c index 0aba0a29f5e0c9a6d74ef1e361f7c135a875e31b..59d7f3eb4fb1dd17ae8331b9ec5b020849053000 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_interface.c @@ -55,7 +55,7 @@ nfapi_vnf_config_t* nfapi_vnf_config_create() _this->_public.codec_config.deallocate = &free; - return &(_this->_public); + return (nfapi_vnf_config_t* )_this; } void nfapi_vnf_config_destory(nfapi_vnf_config_t* config) diff --git a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c index 35bd5e4c1b8352ce7fe1329b25127e6f02b3eb74..a0efeeb5f4dbff9f123c5715bd02266efcccfecb 100644 --- a/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c +++ b/nfapi/open-nFAPI/vnf/src/vnf_p7_interface.c @@ -47,7 +47,7 @@ nfapi_vnf_p7_config_t* nfapi_vnf_p7_config_create() _this->_public.codec_config.deallocate = &free; - return &(_this->_public); + return (nfapi_vnf_p7_config_t*)_this; } void nfapi_vnf_p7_config_destory(nfapi_vnf_p7_config_t* config) diff --git a/openair1/PHY/CODING/TESTBENCH/ldpctest.c b/openair1/PHY/CODING/TESTBENCH/ldpctest.c index 552af99c41e78e3de1ddf114c3a90fcc13d33e57..ce6f9996dede49d94e4f1c645455e18a3158588a 100644 --- a/openair1/PHY/CODING/TESTBENCH/ldpctest.c +++ b/openair1/PHY/CODING/TESTBENCH/ldpctest.c @@ -529,7 +529,7 @@ int main(int argc, char *argv[]) time_stats_t time_optim[10], time_decoder[10]; n_iter_stats_t dec_iter[3]; - short BG=0,Zc,Kb; + short BG=0,Zc,Kb=0; while ((c = getopt (argc, argv, "q:r:s:S:l:n:d:i:t:u:h")) != -1) switch (c) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c index 43c0350efb138dd9302d2c0f70ed77ee0c2d9e2b..2331e253d5f2a703b355dccbe557b15fe3d9a506 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c @@ -43,7 +43,7 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, uint8_t pilot0,pilot1,pilot2,pilot3; short ch[2], *pil, *rxF, *dl_bf_ch, *dl_bf_ch_prev; - short *fl, *fm, *fr, *fl_dc, *fm_dc, *fr_dc, *f1, *f2l, *f2r; + short *fl=NULL, *fm=NULL, *fr=NULL, *fl_dc=NULL, *fm_dc=NULL, *fr_dc=NULL, *f1, *f2l=NULL, *f2r=NULL; unsigned int *rballoc; int **rxdataF; @@ -58,10 +58,10 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) || - ((frame_parms->Ncp == EXTENDED) && (symbol>=6))) - rballoc = dlsch0_harq->rb_alloc_odd; + ((frame_parms->Ncp == EXTENDED) && (symbol>=6))) + rballoc = dlsch0_harq->rb_alloc_odd; else - rballoc = dlsch0_harq->rb_alloc_even; + rballoc = dlsch0_harq->rb_alloc_even; rxdataF = phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[Ns>>1]].rxdataF; @@ -69,56 +69,56 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0; if (phy_vars_ue->high_speed_flag == 0) // use second channel estimate position for temporary storage - ch_offset = frame_parms->ofdm_symbol_size; + ch_offset = frame_parms->ofdm_symbol_size; else - ch_offset = frame_parms->ofdm_symbol_size*symbol; + ch_offset = frame_parms->ofdm_symbol_size*symbol; + - uespec_nushift = frame_parms->Nid_cell%3; subframe = Ns>>1; - - //generate ue specific pilots - lprime = symbol/3-1; - lte_dl_ue_spec_rx(phy_vars_ue,uespec_pilot,Ns,5,lprime,0,dlsch0_harq->nb_rb); - //LOG_M("uespec_pilot_rx.m","uespec_pilot",uespec_pilot,300,1,1); - - if (frame_parms->Ncp==0){ - if (symbol==3 || symbol==6 || symbol==9 || symbol==12) - uespec_pilots = 1; - } else{ - if (symbol==4 || symbol==7 || symbol==10) - uespec_pilots = 1; - } - - if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7)) - uespec_poffset = 2; - - if (phy_vars_ue->frame_parms.Ncp == 0) { // normal prefix - pilot0 = 3; - pilot1 = 6; - pilot2 = 9; - pilot3 = 12; - } else { // extended prefix - pilot0 = 4; - pilot1 = 7; - pilot2 = 10; - } - //define the filter - pil_offset = (uespec_nushift+uespec_poffset)%3; - // printf("symbol=%d,pil_offset=%d\n",symbol,pil_offset); - switch (pil_offset) { - case 0: - fl = filt16_l0; - fm = filt16_m0; - fr = filt16_r0; - fl_dc = filt16_l0; - fm_dc = filt16_m0; - fr_dc = filt16_r0; - f1 = filt16_1; - f2l = filt16_2l0; - f2r = filt16_2r0; + //generate ue specific pilots + lprime = symbol/3-1; + lte_dl_ue_spec_rx(phy_vars_ue,uespec_pilot,Ns,5,lprime,0,dlsch0_harq->nb_rb); + //LOG_M("uespec_pilot_rx.m","uespec_pilot",uespec_pilot,300,1,1); + + if (frame_parms->Ncp==0){ + if (symbol==3 || symbol==6 || symbol==9 || symbol==12) + uespec_pilots = 1; + } else{ + if (symbol==4 || symbol==7 || symbol==10) + uespec_pilots = 1; + } + + if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7)) + uespec_poffset = 2; + + if (phy_vars_ue->frame_parms.Ncp == 0) { // normal prefix + pilot0 = 3; + pilot1 = 6; + pilot2 = 9; + pilot3 = 12; + } else { // extended prefix + pilot0 = 4; + pilot1 = 7; + pilot2 = 10; + } + + //define the filter + pil_offset = (uespec_nushift+uespec_poffset)%3; + // printf("symbol=%d,pil_offset=%d\n",symbol,pil_offset); + switch (pil_offset) { + case 0: + fl = filt16_l0; + fm = filt16_m0; + fr = filt16_r0; + fl_dc = filt16_l0; + fm_dc = filt16_m0; + fr_dc = filt16_r0; + f1 = filt16_1; + f2l = filt16_2l0; + f2r = filt16_2r0; break; case 1: diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c index 2e4f3e60361eeb564e376435a34fcd8b9443982c..880c056578e6a4a0dc2fe7f7b108e798cacbb204 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c @@ -1029,7 +1029,7 @@ void lte_ue_measurements(PHY_VARS_UE *ue, int N_RB_DL = frame_parms->N_RB_DL; - int rank_tm3_tm4; + int rank_tm3_tm4=-1; ue->measurements.nb_antennas_rx = frame_parms->nb_antennas_rx; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index f5543eda52ec8f39eabc75ab50e7c18c90583365..7caaf07406b0355d970165fd8a1eb793f9710197 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -50,8 +50,11 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, int32_t **ul_ch_estimates_time = (eNB!=NULL) ? pusch_vars->drs_ch_estimates_time : calibration->drs_ch_estimates_time; AssertFatal(ul_ch_estimates_time != NULL, "ul_ch_estimates_time is null\n"); int32_t **rxdataF_ext = (eNB!=NULL) ? pusch_vars->rxdataF_ext : calibration->rxdataF_ext; - int subframe = (eNB!=NULL) ? proc->subframe_rx : ru->proc.tti_rx; - uint8_t harq_pid; + + int subframe = proc->subframe_rx; + + uint8_t harq_pid; + int16_t delta_phase = 0; int16_t *ru1 = ru_90; int16_t *ru2 = ru_90; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 6595158f1a856cf5b7205f3069bc7bdee46000dd..15eb5206a196530371d121b960144945d17afe68 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -20,15 +20,15 @@ */ /*! \file PHY/LTE_TRANSPORT/dlsch_coding.c -* \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 -* \author R. Knopp -* \date 2011 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr -* \note -* \warning -*/ + * \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 + * \author R. Knopp + * \date 2011 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr + * \note + * \warning + */ #include "PHY/defs_eNB.h" #include "PHY/phy_extern.h" @@ -42,22 +42,23 @@ #include "common/utils/LOG/log.h" #include "targets/RT/USER/lte-softmodem.h" #include <syscall.h> -#include "executables/thread-common.h" +#include "targets/RT/USER/rt_wrapper.h" +#include <common/utils/threadPool/thread-pool.h> //#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_FREE 1 /* -#define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \ + #define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \ ((pilots==1)&&(first_pilot==1)&&(((re>2)&&(re<6))||((re>8)&&(re<12)))) || \ ((pilots==1)&&(first_pilot==0)&&(((re<3))||((re>5)&&(re<9)))) \ */ #define is_not_pilot(pilots,first_pilot,re) (1) /*extern void thread_top_init(char *thread_name, - int affinity, - uint64_t runtime, - uint64_t deadline, - uint64_t period);*/ + int affinity, + uint64_t runtime, + uint64_t deadline, + uint64_t period);*/ extern volatile int oai_exit; @@ -83,11 +84,6 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) { free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); dlsch->harq_processes[i]->c[r] = NULL; } - - if (dlsch->harq_processes[i]->d[r]) { - free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); - dlsch->harq_processes[i]->d[r] = NULL; - } } free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t)); @@ -108,26 +104,26 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, LTE_DL_FRAME_PARMS *frame_parms) { LTE_eNB_DLSCH_t *dlsch; - unsigned char exit_flag = 0,i,j,r,aa,layer; + unsigned char exit_flag = 0,i,r,aa,layer; int re; unsigned char bw_scaling =1; switch (N_RB_DL) { - case 6: - bw_scaling =16; - break; + case 6: + bw_scaling =16; + break; - case 25: - bw_scaling =4; - break; + case 25: + bw_scaling =4; + break; - case 50: - bw_scaling =2; - break; + case 50: + bw_scaling =2; + break; - default: - bw_scaling =1; - break; + default: + bw_scaling =1; + break; } dlsch = (LTE_eNB_DLSCH_t *)malloc16(sizeof(LTE_eNB_DLSCH_t)); @@ -153,11 +149,11 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, // NOTE: THIS HAS TO BE REVISED FOR RU, commenting to remove memory leak !!!!! /* - dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); - for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { - dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); + dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); + for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { + dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - }*/ + }*/ for (i=0; i<20; i++) dlsch->harq_ids[i/10][i%10] = Mdlharq; @@ -183,7 +179,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) { // account for filler in first segment and CRCs for multiple segment case dlsch->harq_processes[i]->c[r] = (uint8_t *)malloc16(((r==0)?8:0) + 3+ 768); - dlsch->harq_processes[i]->d[r] = (uint8_t *)malloc16((96+12+3+(3*6144))); if (dlsch->harq_processes[i]->c[r]) { bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768); @@ -191,13 +186,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, printf("Can't get c\n"); exit_flag=2; } - - if (dlsch->harq_processes[i]->d[r]) { - bzero(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); - } else { - printf("Can't get d\n"); - exit_flag=2; - } } } } else { @@ -209,13 +197,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, if (exit_flag==0) { for (i=0; i<Mdlharq; i++) { dlsch->harq_processes[i]->round=0; - - for (j=0; j<96; j++) - for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) { - // printf("dlsch->harq_processes[%d]->d[%d] %p\n",i,r,dlsch->harq_processes[i]->d[r]); - if (dlsch->harq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = LTE_NULL; - } } return(dlsch); @@ -231,7 +212,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo, void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) { unsigned char Mdlharq; - unsigned char i,j,r; + unsigned char i; if (dlsch) { Mdlharq = dlsch->Mdlharq; @@ -255,307 +236,17 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) { dlsch->harq_processes[i]->status = 0; dlsch->harq_processes[i]->round = 0; - for (j=0; j<96; j++) - for (r=0; r<MAX_NUM_DLSCH_SEGMENTS; r++) - if (dlsch->harq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = LTE_NULL; } } } } - -int dlsch_encoding_2threads0(te_params *tep) { - LTE_eNB_DLSCH_t *dlsch = tep->dlsch; - unsigned int G = tep->G; - unsigned char harq_pid = tep->harq_pid; - unsigned int total_worker = tep->total_worker; - unsigned int current_worker = tep->current_worker; - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_IN); - - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - for (r=(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*current_worker; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) { - if (r<dlsch->harq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - } - } - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - - for (r=0,r_offset=0; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) { - if(r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker)) { - int Nl=dlsch->harq_processes[harq_pid]->Nl; - int Qm=dlsch->harq_processes[harq_pid]->Qm; - int C = dlsch->harq_processes[harq_pid]->C; - int Gp = G/Nl/Qm; - int GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - r_offset += Nl*Qm * (Gp/C); - else - r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - } else { - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_OUT); - return(0); -} - - void *te_thread(void *param) { - te_params *tep = (te_params *)param; - - //wait_sync("te_thread"); - - while (!oai_exit) { - if (wait_on_condition(&tep->mutex_te,&tep->cond_te,&tep->instance_cnt_te,"te thread")<0) break; - - if(oai_exit) break; - - dlsch_encoding_2threads0(tep); - - if (release_thread(&tep->mutex_te,&tep->instance_cnt_te,"te thread")<0) break; - - if (pthread_cond_signal(&tep->cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(NULL); - } - - /*if(opp_enabled == 1 && te_wakeup_stats0->p_time>50*3000){ - print_meas_now(te_wakeup_stats0,"coding_wakeup",stderr); - printf("te_thread0 delay for waking up in frame_rx: %d subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx); - }*/ - } - return(NULL); } - -int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, - unsigned char *a, - uint8_t num_pdcch_symbols, - LTE_eNB_DLSCH_t *dlsch, - int frame, - uint8_t subframe, - time_stats_t *rm_stats, - time_stats_t *te_stats, - time_stats_t *te_wait_stats, - time_stats_t *te_main_stats, - time_stats_t *te_wakeup_stats0, - time_stats_t *te_wakeup_stats1, - time_stats_t *i_stats, - int worker_num) { - //start_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; - L1_proc_t *proc = &eNB->proc; - unsigned int G; - unsigned int crc=1; - unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe]; - if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) { - LOG_E(PHY,"dlsch_encoding_2threads illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__); - return(-1); - } - - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int A; - unsigned char mod_order; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - A = dlsch->harq_processes[harq_pid]->TBS; //6228 - mod_order = dlsch->harq_processes[harq_pid]->Qm; - G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe, - dlsch->harq_processes[harq_pid]->mimo_mode==TM7?7:0); - - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - start_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a, - A)>>8; - stop_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - a[A>>3] = ((uint8_t *)&crc)[2]; - a[1+(A>>3)] = ((uint8_t *)&crc)[1]; - a[2+(A>>3)] = ((uint8_t *)&crc)[0]; - dlsch->harq_processes[harq_pid]->B = A+24; - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); - //stop_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - start_meas(&eNB->dlsch_turbo_encoding_segmentation_stats); - - if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->Cplus, - &dlsch->harq_processes[harq_pid]->Cminus, - &dlsch->harq_processes[harq_pid]->Kplus, - &dlsch->harq_processes[harq_pid]->Kminus, - &dlsch->harq_processes[harq_pid]->F)<0) - return(-1); - - stop_meas(&eNB->dlsch_turbo_encoding_segmentation_stats); - start_meas(&eNB->dlsch_turbo_encoding_signal_stats); - - for(int i=0; i<worker_num; i++) { - proc->tep[i].eNB = eNB; - proc->tep[i].dlsch = dlsch; - proc->tep[i].G = G; - proc->tep[i].harq_pid = harq_pid; - proc->tep[i].total_worker = worker_num; - proc->tep[i].current_worker = i; - pthread_mutex_lock( &proc->tep[i].mutex_te ); - - if (proc->tep[i].instance_cnt_te==0) { - printf("[eNB] TE thread busy\n"); - exit_fun("TE thread busy"); - pthread_mutex_unlock( &proc->tep[i].mutex_te ); - return(-1); - } - - ++proc->tep[i].instance_cnt_te; - - // wakeup worker to do segments - if (pthread_cond_signal(&proc->tep[i].cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread %d exit\n",i); - exit_fun( "ERROR pthread_cond_signal" ); - return (-1); - } - - pthread_mutex_unlock( &proc->tep[i].mutex_te ); - } - - stop_meas(&eNB->dlsch_turbo_encoding_signal_stats); - start_meas(te_main_stats); - - for (r=(dlsch->harq_processes[harq_pid]->C/(worker_num+1))*worker_num; r<dlsch->harq_processes[harq_pid]->C; r++) { - if (r<dlsch->harq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; - start_meas(te_stats); - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - stop_meas(te_stats); - start_meas(i_stats); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - stop_meas(i_stats); - } - } else { - for(int i=0; i<worker_num; i++) { - proc->tep[i].eNB = eNB; - proc->tep[i].dlsch = dlsch; - proc->tep[i].G = G; - proc->tep[i].total_worker = worker_num; - proc->tep[i].current_worker = i; - - if (pthread_cond_signal(&proc->tep[i].cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return (-1); - } - } - } - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - for (r=0,r_offset=0; r<dlsch->harq_processes[harq_pid]->C; r++) { - // get information for E for the segments that are handled by the worker thread - if (r<(dlsch->harq_processes[harq_pid]->C/(worker_num+1))*worker_num) { - int Nl=dlsch->harq_processes[harq_pid]->Nl; - int Qm=dlsch->harq_processes[harq_pid]->Qm; - int C = dlsch->harq_processes[harq_pid]->C; - int Gp = G/Nl/Qm; - int GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - r_offset += Nl*Qm * (Gp/C); - else - r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - } else { - start_meas(rm_stats); - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - stop_meas(rm_stats); - } - } - - stop_meas(te_main_stats); - start_meas(te_wait_stats); - - if(worker_num == 1) { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - } else if(worker_num == 2) { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - wait_on_busy_condition(&proc->tep[1].mutex_te,&proc->tep[1].cond_te,&proc->tep[1].instance_cnt_te,"te thread 1"); - } else { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - wait_on_busy_condition(&proc->tep[1].mutex_te,&proc->tep[1].cond_te,&proc->tep[1].instance_cnt_te,"te thread 1"); - wait_on_busy_condition(&proc->tep[2].mutex_te,&proc->tep[2].cond_te,&proc->tep[2].instance_cnt_te,"te thread 2"); - } - - stop_meas(te_wait_stats); - /*if(opp_enabled == 1 && te_wait_stats->p_time>100*3000){ - print_meas_now(te_wait_stats,"coding_wait",stderr); - printf("coding delay in wait on codition in frame_rx: %d \n",proc->frame_rx); - }*/ - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); - return(0); -} - - int dlsch_encoding_all(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -568,108 +259,72 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, time_stats_t *te_wakeup_stats0, time_stats_t *te_wakeup_stats1, time_stats_t *i_stats) { - int encoding_return = 0; - unsigned int L,C,B; uint8_t harq_pid = dlsch->harq_ids[frame%2][subframe]; if(harq_pid >= dlsch->Mdlharq) { LOG_E(PHY,"dlsch_encoding_all illegal harq_pid %d\n", harq_pid); return(-1); } - B = dlsch->harq_processes[harq_pid]->B; + + LOG_D(PHY,"B %d, harq_pid %d\n", + dlsch->harq_processes[harq_pid]->B, + dlsch->harq_ids[frame%2][subframe]); + + return dlsch_encoding(eNB, + proc, + a, + num_pdcch_symbols, + dlsch, + frame, + subframe, + rm_stats, + te_stats, + i_stats); - LOG_D(PHY,"B %d, harq_pid %d\n",B,dlsch->harq_ids[frame%2][subframe]); - - if(B<=6144) { - L=0; - C=1; - } else { - L=24; - C = B/(6144-L); - - if((6144-L)*C < B) { - C = C+1; - } - } +} - if(get_thread_worker_conf() == WORKER_ENABLE) { - if(C >= 8) { //one main three worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 3); - } else if(C >= 6) { //one main two worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 2); - } else if(C >= 4) { //one main one worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 1); - } else { - encoding_return = - dlsch_encoding(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - i_stats); - } - } else { - encoding_return = - dlsch_encoding(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - i_stats); +static void TPencode(void * arg) { + turboEncode_t * rdata=(turboEncode_t *) arg; + unsigned char harq_pid = rdata->harq_pid; + LTE_DL_eNB_HARQ_t *hadlsch=rdata->dlsch->harq_processes[harq_pid]; + + if ( rdata-> round == 0) { + uint8_t tmp[96+12+3+3*6144]; + memset(tmp,LTE_NULL, TURBO_SIMD_SOFTBITS); + start_meas(rdata->te_stats); + encoder(rdata->input, + rdata->Kr_bytes, + tmp+96,//&dlsch->harq_processes[harq_pid]->d[r][96], + rdata->filler); + stop_meas(rdata->te_stats); + start_meas(rdata->i_stats); + hadlsch->RTC[rdata->r] = + sub_block_interleaving_turbo(4+(rdata->Kr_bytes*8), + tmp+96, + hadlsch->w[rdata->r]); + stop_meas(rdata->i_stats); } - - return encoding_return; + + // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the + // outputs for each code segment, see Section 5.1.5 p.20 + start_meas(rdata->rm_stats); + lte_rate_matching_turbo(hadlsch->RTC[rdata->r], + rdata->G, //G + hadlsch->w[rdata->r], + hadlsch->eDL+rdata->r_offset, + hadlsch->C, // C + rdata->dlsch->Nsoft, // Nsoft, + rdata->dlsch->Mdlharq, + rdata->dlsch->Kmimo, + hadlsch->rvidx, + hadlsch->Qm, + hadlsch->Nl, + rdata->r, + hadlsch->nb_rb); + stop_meas(rdata->rm_stats); } - int dlsch_encoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -678,8 +333,6 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, time_stats_t *rm_stats, time_stats_t *te_stats, time_stats_t *i_stats) { - unsigned int G; - unsigned int crc=1; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe]; if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) { @@ -687,135 +340,88 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, return(-1); } - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int A; - unsigned char mod_order; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; + LTE_DL_eNB_HARQ_t *hadlsch=dlsch->harq_processes[harq_pid]; uint8_t beamforming_mode=0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - A = dlsch->harq_processes[harq_pid]->TBS; //6228 - // printf("Encoder: A: %d\n",A); - mod_order = dlsch->harq_processes[harq_pid]->Qm; - if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7) + if(hadlsch->mimo_mode == TM7) beamforming_mode = 7; - else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8) + else if(hadlsch->mimo_mode == TM8) beamforming_mode = 8; - else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10) + else if(hadlsch->mimo_mode == TM9_10) beamforming_mode = 9; - G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode); + unsigned int G = get_G(frame_parms,hadlsch->nb_rb, + hadlsch->rb_alloc, + hadlsch->Qm, // mod order + hadlsch->Nl, + num_pdcch_symbols, + frame,subframe,beamforming_mode); - // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet -#ifdef DEBUG_DLSCH_CODING - printf("encoding thinks this is a new packet for harq_pid %d (%p), A %u \n",harq_pid,dlsch,A); -#endif - /* - int i; - printf("dlsch (tx): \n"); - for (i=0;i<(A>>3);i++) - printf("%02x.",a[i]); - printf("\n"); - */ + proc->nbEncode=0; + + // if (hadlsch->Ndi == 1) { // this is a new packet + if (hadlsch->round == 0) { // this is a new packet // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a, + unsigned int A=hadlsch->TBS; //6228; + unsigned int crc = crc24a(a, A)>>8; a[A>>3] = ((uint8_t *)&crc)[2]; a[1+(A>>3)] = ((uint8_t *)&crc)[1]; a[2+(A>>3)] = ((uint8_t *)&crc)[0]; // printf("CRC %x (A %d)\n",crc,A); - dlsch->harq_processes[harq_pid]->B = A+24; - // dlsch->harq_processes[harq_pid]->b = a; - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); - - if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->Cplus, - &dlsch->harq_processes[harq_pid]->Cminus, - &dlsch->harq_processes[harq_pid]->Kplus, - &dlsch->harq_processes[harq_pid]->Kminus, - &dlsch->harq_processes[harq_pid]->F)<0) + hadlsch->B = A+24; + // hadlsch->b = a; + memcpy(hadlsch->b,a,(A/8)+4); + + if (lte_segmentation(hadlsch->b, + hadlsch->c, + hadlsch->B, + &hadlsch->C, + &hadlsch->Cplus, + &hadlsch->Cminus, + &hadlsch->Kplus, + &hadlsch->Kminus, + &hadlsch->F)<0) return(-1); - - for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) { - if (r<dlsch->harq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; -#ifdef DEBUG_DLSCH_CODING - printf("Generating Code Segment %u (%u bits)\n",r,Kr); - // generate codewords - printf("bits_per_codeword (Kr)= %u, A %u\n",Kr,A); - printf("N_RB = %d\n",nb_rb); - printf("Ncp %d\n",frame_parms->Ncp); - printf("mod_order %d\n",mod_order); -#endif - start_meas(te_stats); - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - stop_meas(te_stats); -#ifdef DEBUG_DLSCH_CODING - - if (r==0) - LOG_M("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4); - -#endif - start_meas(i_stats); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - stop_meas(i_stats); - } } - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - - for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) { -#ifdef DEBUG_DLSCH_CODING - printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb); -#endif - start_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - printf("rvidx in encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - stop_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - - if (r==dlsch->harq_processes[harq_pid]->C-1) - LOG_M("enc_output.m","enc",dlsch->harq_processes[harq_pid]->e,r_offset,1,4); - -#endif + + for (int r=0, r_offset=0; r<hadlsch->C; r++) { + + union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, proc->respEncode, TPencode); + turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req); + rdata->input=hadlsch->c[r]; + rdata->Kr_bytes= ( r<hadlsch->Cminus ? hadlsch->Kminus : hadlsch->Kplus) >>3; + rdata->filler=(r==0) ? hadlsch->F : 0; + rdata->r=r; + rdata->harq_pid=harq_pid; + rdata->dlsch=dlsch; + rdata->rm_stats=rm_stats; + rdata->te_stats=te_stats; + rdata->i_stats=i_stats; + rdata->round=hadlsch->round; + rdata->r_offset=r_offset; + rdata->G=G; + + if ( proc->threadPool->activated ) { + pushTpool(proc->threadPool,req); + proc->nbEncode++; + } else { + TPencode(rdata); + delNotifiedFIFO_elt(req); + } + + int Qm=hadlsch->Qm; + int C=hadlsch->C; + int Nl=hadlsch->Nl; + int Gp = G/Nl/Qm; + int GpmodC = Gp%C; + if (r < (C-(GpmodC))) + r_offset += Nl*Qm * (Gp/C); + else + r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return(0); } diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 04a49d062a3be069a78bb6e505c3cf3eb830f200..475c8bd521d8ea8b777d3bf04a40e799497858cd 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -158,7 +158,7 @@ int allocate_REs_in_RB_no_pilots_QPSK_siso(PHY_VARS_eNB* phy_vars_eNB, { LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qpsk_table_offset_re = 0; uint32_t qpsk_table_offset_im = 0; @@ -248,7 +248,7 @@ int allocate_REs_in_RB_pilots_QPSK_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qpsk_table_offset_re = 0; uint32_t qpsk_table_offset_im = 0; @@ -343,7 +343,7 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, { LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam16_table_offset_re = 0; uint32_t qam16_table_offset_im = 0; @@ -439,7 +439,7 @@ int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam16_table_offset_re = 0; uint32_t qam16_table_offset_im = 0; @@ -542,7 +542,7 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam64_table_offset_re = 0; uint32_t qam64_table_offset_im = 0; @@ -699,7 +699,7 @@ int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam64_table_offset_re = 0; uint32_t qam64_table_offset_im = 0; @@ -866,12 +866,12 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, if ((dlsch0_harq != NULL) && (dlsch1_harq != NULL)) { //this is for TM3, TM4 - x0 = dlsch0_harq->e; + x0 = dlsch0_harq->eDL; mimo_mode = dlsch0_harq->mimo_mode; first_layer0 = dlsch0_harq->first_layer; Nlayers0 = dlsch0_harq->Nlayers; mod_order0 = dlsch0_harq->Qm; - x1 = dlsch1_harq->e; + x1 = dlsch1_harq->eDL; // Fill these in later for TM8-10 // Nlayers1 = dlsch1_harq->Nlayers; // first_layer1 = dlsch1_harq->first_layer; @@ -879,7 +879,7 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, } else if ((dlsch0_harq != NULL) && (dlsch1_harq == NULL)){ //This is for SIS0 TM1, TM6, etc - x0 = dlsch0_harq->e; + x0 = dlsch0_harq->eDL; mimo_mode = dlsch0_harq->mimo_mode; first_layer0 = dlsch0_harq->first_layer; Nlayers0 = dlsch0_harq->Nlayers; @@ -887,7 +887,7 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, } else if ((dlsch0_harq == NULL) && (dlsch1_harq != NULL)){ // This is for TM4 retransmission - x0 = dlsch1_harq->e; + x0 = dlsch1_harq->eDL; mimo_mode = dlsch1_harq->mimo_mode; first_layer0 = dlsch1_harq->first_layer; Nlayers0 = dlsch1_harq->Nlayers; @@ -2692,7 +2692,7 @@ int dlsch_modulation_SIC(int32_t **sic_buffer, LTE_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid]; uint32_t i,jj,re_allocated=0; uint8_t mod_order0 = dlsch0_harq->Qm; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint8_t qam64_table_offset_re = 0; uint8_t qam64_table_offset_im = 0; uint8_t qam16_table_offset_re = 0; @@ -2883,7 +2883,7 @@ int mch_modulation(int32_t **txdataF, &jj, re_offset, symbol_offset, - dlsch->harq_processes[0]->e, + dlsch->harq_processes[0]->eDL, l, mod_order, amp, diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c index 2e8ddde8488a2e59e37455ea50f5dfb54308b9cc..d48164e07d605a16aa27e3c81415c85879585f67 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c @@ -52,7 +52,7 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, int n; // uint8_t reset; uint32_t x1, x2, s=0; - uint8_t *dlsch_e=dlsch->harq_processes[harq_pid]->e; + uint8_t *dlsch_e=dlsch->harq_processes[harq_pid]->eDL; uint8_t *e=dlsch_e; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_IN); // Rule for accumulation of subframes for BL/CE UEs diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.h b/openair1/PHY/LTE_TRANSPORT/if5_tools.h index 0f24f7becee0334c1e2d900a5b79133bb9130ba8..6c75b20bd9692f72eceb25388aff375bb5ed5aa3 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.h @@ -61,7 +61,8 @@ typedef struct IF5_mobipass_header IF5_mobipass_header_t; void send_IF5(RU_t *, openair0_timestamp, int, uint8_t*, uint16_t); -void recv_IF5(RU_t *, openair0_timestamp*, int, uint16_t); +void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type); + void malloc_IF5_buffer(RU_t *ru); diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index ab2fe2d743b8b2310ff1af8d5592a5df0979afc7..6d8b58818b16155fcabdc7ebc2fef4999ec9a01b 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -714,7 +714,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, int32_t **txdataF = eNB->common_vars.txdataF; uint8_t Ngroup_PHICH,ngroup_PHICH,nseq_PHICH; uint8_t NSF_PHICH = 4; - uint8_t pusch_subframe; + uint8_t pusch_subframe=-1; uint8_t i; int subframe = proc->subframe_tx; phich_config_t *phich; diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index f48ee629a1eed9f1161105fcd27cb288541aca2c..90e2836b1e729dc09d18bdf87a09952a73714ed3 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -105,6 +105,7 @@ void generate_mch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a) AssertFatal(eNB->dlsch_MCH->harq_processes[0]->pdu != NULL, "attempt to encode a NULL harq PDU\n"); AssertFatal(dlsch_encoding(eNB, + proc, // a, eNB->dlsch_MCH->harq_processes[0]->pdu, 1, diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 983e30c80a1b6c50ccf4a9f7b4ac418304db86ae..24faf584d3ae2e2048e3ee4a412c3c33637d8a0d 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -38,9 +38,13 @@ #include "SCHED/sched_eNB.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "prach_extern.h" +#include <openair1/PHY/LTE_TRANSPORT/transport_proto.h> +#include <executables/split_headers.h> void rx_prach0(PHY_VARS_eNB *eNB, RU_t *ru, + int frame_prach, + int subframe, uint16_t *max_preamble, uint16_t *max_preamble_energy, uint16_t *max_preamble_delay, @@ -51,17 +55,14 @@ void rx_prach0(PHY_VARS_eNB *eNB, uint8_t ce_level ) { int i; - LTE_DL_FRAME_PARMS *fp=NULL; lte_frame_type_t frame_type; uint16_t rootSequenceIndex; uint8_t prach_ConfigIndex; uint8_t Ncs_config; uint8_t restricted_set; uint8_t n_ra_prb; - int subframe; int16_t *prachF=NULL; int16_t **rxsigF=NULL; - int nb_rx=0; int16_t *prach2; uint8_t preamble_index; uint16_t NCS,NCS2; @@ -89,6 +90,8 @@ void rx_prach0(PHY_VARS_eNB *eNB, int32_t **prach_ifftp=(int32_t **)NULL; int prach_ifft_cnt=0; + LTE_DL_FRAME_PARMS *fp; + int nb_rx; if(eNB) { fp = &(eNB->frame_parms); nb_rx = fp->nb_antennas_rx; @@ -96,7 +99,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, fp = (ru->frame_parms); nb_rx = ru->nb_rx; } - + AssertFatal(fp!=NULL,"rx_prach called without valid RU or eNB descriptor\n"); frame_type = fp->frame_type; @@ -133,14 +136,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (eNB) { if (br_flag == 1) { prach_ifftp = eNB->prach_vars_br.prach_ifft[ce_level]; - subframe = eNB->proc.subframe_prach_br; prachF = eNB->prach_vars_br.prachF; rxsigF = eNB->prach_vars_br.rxsigF[ce_level]; if (LOG_DEBUGFLAG(PRACH)) { - if (((eNB->proc.frame_prach)&1023) < 20) LOG_I(PHY, + if (((frame_prach)&1023) < 20) LOG_I(PHY, "PRACH (eNB) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d, rootSequenceIndex %d, repetition number %d,numRepetitionsPrePreambleAttempt %d\n", - br_flag,ce_level,eNB->proc.frame_prach,subframe, + br_flag,ce_level,frame_prach,subframe, fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level], prach_ConfigIndex,rootSequenceIndex, eNB->prach_vars_br.repetition_number[ce_level], @@ -148,30 +150,27 @@ void rx_prach0(PHY_VARS_eNB *eNB, } } else { prach_ifftp = eNB->prach_vars.prach_ifft[0]; - subframe = eNB->proc.subframe_prach; prachF = eNB->prach_vars.prachF; rxsigF = eNB->prach_vars.rxsigF[0]; if (LOG_DEBUGFLAG(PRACH)) { - if (((eNB->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe, + if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe, fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex,rootSequenceIndex); } } } else { if (br_flag == 1) { - subframe = ru->proc.subframe_prach_br; rxsigF = ru->prach_rxsigF_br[ce_level]; if (LOG_DEBUGFLAG(PRACH)) { - if (((ru->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", - br_flag,ce_level,ru->proc.frame_prach,subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex); + if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + br_flag,ce_level,frame_prach,subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex); } } else { - subframe = ru->proc.subframe_prach; rxsigF = ru->prach_rxsigF; if (LOG_DEBUGFLAG(PRACH)) { - if (((ru->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + if (((frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex); } } @@ -202,7 +201,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (prach[0]!= NULL) LOG_M("prach_rx","prach_rx",prach[0],fp->samples_per_tti,1,1); LOG_I(PHY,"RU %d, br_flag %d ce_level %d frame %d subframe %d per_tti:%d prach:%p (energy %d) TA:%d %s rxdata:%p index:%d\n", - ru->idx,br_flag,ce_level,ru->proc.frame_prach,subframe,fp->samples_per_tti, + ru->idx,br_flag,ce_level,frame_prach,subframe,fp->samples_per_tti, prach[aa],dbEn0,ru->N_TA_offset,buffer,ru->common.rxdata[aa], (subframe*fp->samples_per_tti)-ru->N_TA_offset); } @@ -407,16 +406,16 @@ void rx_prach0(PHY_VARS_eNB *eNB, if ((eNB==NULL) && ru->function == NGFI_RRU_IF4p5) { /// **** send_IF4 of rxsigF to RAU **** /// if (br_flag == 1) - send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH+1+ce_level); + send_IF4p5(ru, frame_prach, subframe, IF4p5_PRACH+1+ce_level); else - send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH); + send_IF4p5(ru, frame_prach, subframe, IF4p5_PRACH); return; } else if (eNB!=NULL) { if ( LOG_DEBUGFLAG(PRACH)) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if ((en > 60)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,eNB->proc.frame_rx,eNB->proc.subframe_rx,en); + if ((en > 60)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,frame_prach,subframe,en); } } @@ -457,7 +456,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (LOG_DEBUGFLAG(PRACH)) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",ru->proc.frame_prach,subframe,preamble_index,br_flag); + if (en>60) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",frame_prach,subframe,preamble_index,br_flag); } if (restricted_set == 0) { @@ -543,7 +542,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); if (en>60) LOG_I(PHY,"frame %d, subframe %d : preamble index %d: offset %d, preamble shift %d (br_flag %d, en %d)\n", - ru->proc.frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en); + frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en); } log2_ifft_size = 10; @@ -618,7 +617,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (LOG_DEBUGFLAG(PRACH)) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d: Checking for peak in time-domain (br_flag %d, en %d)\n",ru->proc.frame_prach,subframe,br_flag,en); + if (en>60) LOG_I(PHY,"frame %d, subframe %d: Checking for peak in time-domain (br_flag %d, en %d)\n",frame_prach,subframe,br_flag,en); } preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<<log2_ifft_size)/N_ZC)); @@ -638,7 +637,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if ((en>60) && (br_flag==1)) LOG_D(PHY,"frame %d, subframe %d : max_preamble_energy %d, max_preamble_delay %d, max_preamble %d (br_flag %d,ce_level %d, levdB %d, lev %d)\n", - ru->proc.frame_prach,subframe, + frame_prach,subframe, *max_preamble_energy,*max_preamble_delay, *max_preamble,br_flag,ce_level,levdB,lev); } @@ -694,8 +693,16 @@ void rx_prach(PHY_VARS_eNB *eNB, int i; int prach_mask=0; + int subframe; + if (eNB) + subframe= br_flag?eNB->proc.subframe_prach_br:eNB->proc.subframe_prach; + else + subframe= br_flag?ru->proc.subframe_prach_br:ru->proc.subframe_prach; + + int frame_prach=eNB?eNB->proc.frame_prach: ru->proc.frame_prach; + if (br_flag == 0) { - rx_prach0(eNB,ru,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); + rx_prach0(eNB,ru,frame_prach,subframe,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); } else { // This is procedure for eMTC, basically handling the repetitions prach_mask = is_prach_subframe(&eNB->frame_parms,eNB->proc.frame_prach_br,eNB->proc.subframe_prach_br); @@ -709,7 +716,7 @@ void rx_prach(PHY_VARS_eNB *eNB, // increment repetition number eNB->prach_vars_br.repetition_number[i]++; // do basic PRACH reception - rx_prach0(eNB,ru,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); + rx_prach0(eNB,ru,frame_prach,subframe,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); // if last repetition, clear counter if (eNB->prach_vars_br.repetition_number[i] == eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[i]) { diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index e142d2f29febdac4a98c539f46e9115d461c503f..8637e80137576108f7302ff6df27aad6a1c5d1eb 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -180,7 +180,7 @@ uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX uint16_t n3_pucch_array[NUMBER_OF_UE_MAX], uint8_t ncs_cell[20][7] ) { uint32_t aa, symNo, k, slotNo, sym, i, j; - int16_t np, np_n, ip_ind; + int16_t np, np_n, ip_ind=-1; //int16_t npucch_sf; int16_t calctmp[2]; int16_t BsCshData[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2]; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 7b9004ba80cd6f33e49be2b155b5842c1018fd64..5e446db5fdd1a11431d2e3075bcda66fdc5bd68a 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -100,7 +100,7 @@ typedef struct { /// start symbold of pdsch uint8_t pdsch_start; /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - uint8_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); + uint8_t eDL[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Turbo-code outputs (36-212 V8.6 2009-03, p.12 uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; /// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17) @@ -261,12 +261,13 @@ typedef struct { /// coded RI bits int16_t q_RI[MAX_RI_PAYLOAD]; /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - int16_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); + int16_t eUL[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Temporary h sequence to flag PUSCH_x/PUSCH_y symbols which are not scrambled uint8_t h[MAX_NUM_CHANNEL_BITS]; /// Pointer to the payload - uint8_t *b; + uint8_t *decodedBytes; /// Pointers to transport block segments + //TBD uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15) uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; @@ -282,8 +283,12 @@ typedef struct { uint8_t rvidx; /// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; + int16_t pusch_rep_buffer[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) + //TBD int16_t *d[MAX_NUM_ULSCH_SEGMENTS]; + uint32_t processedSegments; + uint32_t processedBadSegment; /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) uint32_t C; /// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10) diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index f034039e7e23479059f9f7be3036a4b0f2877412..3988923bb98cdd77b93996ebb7fac009aee0ac12 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -73,18 +73,19 @@ void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch); LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag); int dlsch_encoding_all(PHY_VARS_eNB *eNB, - unsigned char *a, - uint8_t num_pdcch_symbols, - LTE_eNB_DLSCH_t *dlsch, - int frame, - uint8_t subframe, - time_stats_t *rm_stats, - time_stats_t *te_stats, - time_stats_t *te_wait_stats, - time_stats_t *te_main_stats, - time_stats_t *te_wakeup_stats0, - time_stats_t *te_wakeup_stats1, - time_stats_t *i_stats); + L1_rxtx_proc_t *proc, + unsigned char *a, + uint8_t num_pdcch_symbols, + LTE_eNB_DLSCH_t *dlsch, + int frame, + uint8_t subframe, + time_stats_t *rm_stats, + time_stats_t *te_stats, + time_stats_t *te_wait_stats, + time_stats_t *te_main_stats, + time_stats_t *te_wakeup_stats0, + time_stats_t *te_wakeup_stats1, + time_stats_t *i_stats); /** \fn dlsch_encoding(PHY_VARS_eNB *eNB, uint8_t *input_buffer, @@ -112,6 +113,7 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, @returns status */ int32_t dlsch_encoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, uint8_t *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -467,9 +469,12 @@ void rx_ulsch(PHY_VARS_eNB *eNB, int ulsch_decoding_data_all(PHY_VARS_eNB *eNB, - int UE_id, - int harq_pid, - int llr8_flag); + + L1_rxtx_proc_t *proc, + int UE_id, + int harq_pid, + int llr8_flag); + /*! \brief Decoding of PUSCH/ACK/RI/ACK from 36-212. @@ -511,6 +516,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB, @returns 0 on success */ int ulsch_decoding_data(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag); diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 39556902fcdd97d94bcaf34caa2f22d9468ae551..90492b999991905e8829d35447dda2716bb61913 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -41,22 +41,22 @@ #include "RRC/LTE/rrc_extern.h" #include "PHY_INTERFACE/phy_interface.h" #include "transport_proto.h" -#include "common/utils/LOG/vcd_signal_dumper.h" - +#include <executables/split_headers.h> extern WORKER_CONF_t get_thread_worker_conf(void); extern volatile int oai_exit; + void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) { int i,r; if (ulsch) { for (i=0; i<8; i++) { if (ulsch->harq_processes[i]) { - if (ulsch->harq_processes[i]->b) { - free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); - ulsch->harq_processes[i]->b = NULL; + if (ulsch->harq_processes[i]->decodedBytes) { + free16(ulsch->harq_processes[i]->decodedBytes,MAX_ULSCH_PAYLOAD_BYTES); + ulsch->harq_processes[i]->decodedBytes = NULL; } for (r=0; r<MAX_NUM_ULSCH_SEGMENTS; r++) { @@ -115,10 +115,10 @@ LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uin if (ulsch->harq_processes[i]) { memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t)); - ulsch->harq_processes[i]->b = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + ulsch->harq_processes[i]->decodedBytes = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); - if (ulsch->harq_processes[i]->b) - memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + if (ulsch->harq_processes[i]->decodedBytes) + memset(ulsch->harq_processes[i]->decodedBytes,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); else exit_flag=3; @@ -210,490 +210,163 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) { return(crc); } - - - -int ulsch_decoding_data_2thread0(td_params *tdp) { - PHY_VARS_eNB *eNB = tdp->eNB; - int UE_id = tdp->UE_id; - int harq_pid = tdp->harq_pid; - int llr8_flag = tdp->llr8_flag; - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; - int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - int Q_m = ulsch_harq->Qm; - int G = ulsch_harq->G; - uint32_t E=0; - uint32_t Gp,GpmodC,Nl=1; - uint32_t C = ulsch_harq->C; - decoder_if_t *tc; - - if (llr8_flag == 0) - tc = decoder16; - else - tc = decoder8; - - // go through first half of segments to get r_offset - for (r=0; r<(ulsch_harq->C/2); r++) { - // Get Turbo interleaver parameters - if (r<ulsch_harq->Cminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - // This is stolen from rate-matching algorithm to get the value of E - Gp = G/Nl/Q_m; - GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - E = Nl*Q_m * (Gp/C); - else - E = Nl*Q_m * ((GpmodC==0?0:1) + (Gp/C)); - - r_offset += E; - - if (r==0) { - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } - - // go through second half of segments - for (; r<(ulsch_harq->C); r++) { - // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); - // Get Turbo interleaver parameters - if (r<ulsch_harq->Cminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], +void processULSegment(void * arg) { + turboDecode_t* rdata=(turboDecode_t*) arg; + PHY_VARS_eNB *eNB=rdata->eNB; + LTE_UL_eNB_HARQ_t *ulsch_harq=rdata->ulsch_harq; + int r=rdata->segment_r; + int G=ulsch_harq->G; + int Kr_bytes=rdata->Kr>>3; + int16_t dummy_w[3*(6144+64)]; + + memset(&dummy_w[0],0,3*(6144+64)*sizeof(short)); + ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), + (uint8_t *)&dummy_w[0], (r==0) ? ulsch_harq->F : 0); -#ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n", - r, G, - Kr*3, - Q_m, - nb_rb, - ulsch_harq->Nl); -#endif - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], + start_meas(&eNB->ulsch_deinterleaving_stats); + unsigned int E; + if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, + (uint8_t *) &dummy_w[0], + ulsch_harq->eUL+rdata->r_offset, ulsch_harq->C, NSOFT, 0, //Uplink 1, ulsch_harq->rvidx, - (ulsch_harq->round==0)?1:0, // clear + (ulsch_harq->rvidx==0)?1:0, // clear ulsch_harq->Qm, 1, r, &E)==-1) { LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); - } + return; + } + stop_meas(&eNB->ulsch_rate_unmatching_stats); + int max_Ncb = 3*ulsch_harq->RTC[r]*32 ; - r_offset += E; - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); + if(ulsch_harq->repetition_number == 1) { + memset(ulsch_harq->pusch_rep_buffer[r],0,(sizeof(int32_t)*3*(6144+64))) ; // reset the buffer every new repetitions + } + if(ulsch_harq->total_number_of_repetitions > 1) { + if (ulsch_harq->rvidx==1) { + LOG_E(PHY,"Adding HARQ data for segment: %d\n", r); + // Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1 + for (int nn=0; nn<max_Ncb; nn++) + ulsch_harq->pusch_rep_buffer[r][nn] += ulsch_harq->w[r][nn] ; + } - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (r<ulsch_harq->Cminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } else { - break; + if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) { + LOG_E(PHY,"Will use HARQ data sum up for segment: %d\n", r); + for (int nn=0; nn<max_Ncb; nn++) + ulsch_harq->w[r][nn] = ulsch_harq->pusch_rep_buffer[r][nn] ; } } - - return(ret); + int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32))); + sub_block_deinterleaving_turbo(4+rdata->Kr, + soft_bits+96, + ulsch_harq->w[r]); + stop_meas(&eNB->ulsch_deinterleaving_stats); + rdata->decodeIterations = rdata->function( soft_bits+96, + NULL, + rdata->decoded_bytes, + NULL, + rdata->Kr, + rdata->maxIterations, + rdata->nbSegments == 1 ? CRC24_A: CRC24_B, + rdata->Fbits, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + stop_meas(&eNB->ulsch_turbo_decoding_stats); + } - void *td_thread(void *param) { - PHY_VARS_eNB *eNB = ((td_params *)param)->eNB; - L1_proc_t *proc = &eNB->proc; - pthread_setname_np( pthread_self(),"td processing"); - LOG_I(PHY,"thread td created id=%ld\n", syscall(__NR_gettid)); - //wait_sync("td_thread"); - - while (!oai_exit) { - if (wait_on_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread")<0) break; - - if(oai_exit) break; - - ((td_params *)param)->ret = ulsch_decoding_data_2thread0((td_params *)param); - - if (release_thread(&proc->mutex_td,&proc->instance_cnt_td,"td thread")<0) break; - - if (pthread_cond_signal(&proc->cond_td) != 0) { - printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(NULL); - } - } return(NULL); } -int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - L1_proc_t *proc = &eNB->proc; - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; +int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, + int UE_id,int harq_pid,int llr8_flag) { + unsigned int r_offset=0; int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; int G = ulsch_harq->G; unsigned int E; - int Cby2; - decoder_if_t *tc; - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - if (llr8_flag == 0) - tc = decoder16; - else - tc = decoder8; - - if (ulsch_harq->C>1) { // wakeup worker if more than 1 segment - if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { - printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td); - exit_fun( "error locking mutex_fep" ); - return -1; - } - - if (proc->instance_cnt_td==0) { - printf("[eNB] TD thread busy\n"); - exit_fun("TD thread busy"); - pthread_mutex_unlock( &proc->mutex_td ); - return -1; - } - - ++proc->instance_cnt_td; - proc->tdp.eNB = eNB; - proc->tdp.UE_id = UE_id; - proc->tdp.harq_pid = harq_pid; - proc->tdp.llr8_flag = llr8_flag; - - // wakeup worker to do second half segments - if (pthread_cond_signal(&proc->cond_td) != 0) { - printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return (1+ulsch->max_turbo_iterations); - } - - pthread_mutex_unlock( &proc->mutex_td ); - Cby2 = ulsch_harq->C/2; - } else { - Cby2 = 1; - } - - // go through first half of segments in main thread - for (r=0; r<Cby2; r++) { + int ret=0; + + decoder_if_t * td=llr8_flag == 0 ? + *decoder16 : *decoder8; + ulsch_harq->processedSegments=0; + + for (int r=0; r<ulsch_harq->C; r++) { // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); // Get Turbo interleaver parameters - if (r<ulsch_harq->Cminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], - (r==0) ? ulsch_harq->F : 0); + unsigned int Kr= r<ulsch_harq->Cminus ? + ulsch_harq->Kminus :ulsch_harq->Kplus; + unsigned int Kr_bytes = Kr>>3; + #ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n", - r, G, - Kr*3, - Q_m, - nb_rb, - ulsch_harq->Nl); -#endif - start_meas(&eNB->ulsch_rate_unmatching_stats); - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], - G, - ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, - ulsch_harq->C, - NSOFT, - 0, //Uplink - 1, - ulsch_harq->rvidx, - (ulsch_harq->round==0)?1:0, // clear - ulsch_harq->Qm, - 1, - r, - &E)==-1) { - LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); - } - - stop_meas(&eNB->ulsch_rate_unmatching_stats); - r_offset += E; - start_meas(&eNB->ulsch_deinterleaving_stats); - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); - stop_meas(&eNB->ulsch_deinterleaving_stats); - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - start_meas(&eNB->ulsch_turbo_decoding_stats); - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (r<ulsch_harq->Cminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - - if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } else { - break; - } - - stop_meas(&eNB->ulsch_turbo_decoding_stats); - //printf("/////////////////////////////////////////**************************loop for %d time in ulsch_decoding main\n",r); - } - - // wait for worker to finish - wait_on_busy_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread"); - return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret ); -} - -int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; - int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - int G = ulsch_harq->G; - unsigned int E; - decoder_if_t *tc; - static int32_t pusch_rep_buffer[3*(6144+64)]; - int max_Ncb; - - if (llr8_flag == 0) - tc = *decoder16; - else - tc = *decoder8; - - if(ulsch_harq->repetition_number == 1) { - memset(pusch_rep_buffer,0,(sizeof(int32_t)*3*(6144+64))) ; // reset the buffer every new repetitions - } - - for (r=0; r<ulsch_harq->C; r++) { - // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); - // Get Turbo interleaver parameters - if (r<ulsch_harq->Cminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], - (r==0) ? ulsch_harq->F : 0); -#ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d)...\n", + printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d, r_offset %u)...\n", r, G, Kr*3, ulsch_harq->Qm, - ulsch_harq->Nl); + ulsch_harq->Nl, r_offset); #endif - start_meas(&eNB->ulsch_rate_unmatching_stats); - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], - G, - ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, - ulsch_harq->C, - NSOFT, - 0, //Uplink - 1, - ulsch_harq->rvidx, - (ulsch_harq->rvidx==0)?1:0, // clear - ulsch_harq->Qm, - 1, - r, - &E)==-1) { - LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); - } - - stop_meas(&eNB->ulsch_rate_unmatching_stats); - max_Ncb = 3*ulsch_harq->RTC[r]*32 ; - - if(ulsch_harq->total_number_of_repetitions > 1) { - if (ulsch_harq->rvidx==1) { - // Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1 - for (int nn=0; nn<max_Ncb; nn++) { - pusch_rep_buffer[nn] += ulsch_harq->w[r][nn] ; - } - } - - if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) { - for (int nn=0; nn<max_Ncb; nn++) { - ulsch_harq->w[r][nn] = pusch_rep_buffer[nn] ; - } - } - } - - r_offset += E; - start_meas(&eNB->ulsch_deinterleaving_stats); - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); - stop_meas(&eNB->ulsch_deinterleaving_stats); - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; + int Gp=G/ulsch_harq->Qm; + int GpmodC = Gp%ulsch_harq->C; + + if (r < (ulsch_harq->C-(GpmodC))) + E = ulsch_harq->Qm * (Gp/ulsch_harq->C); else - crc_type = CRC24_B; - - start_meas(&eNB->ulsch_turbo_decoding_stats); - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - stop_meas(&eNB->ulsch_turbo_decoding_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (r<ulsch_harq->Cminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - - if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } else { - break; + E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C)); + + if ( split73 == SPLIT73_DU ) { + sendFs6Ul(eNB, UE_id, harq_pid, r, ulsch_harq->eUL+r_offset, E*sizeof(int16_t), r_offset); + r_offset += E; + continue; } - } + union turboReqUnion id= {.s={ulsch->rnti,proc->frame_rx,proc->subframe_rx,0,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboDecode_t), id.p, proc->respDecode, processULSegment); + turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); + + rdata->eNB=eNB; + rdata->frame=proc->frame_rx; + rdata->subframe=proc->subframe_rx; + rdata->UEid=UE_id; + rdata->harq_pid=harq_pid; + rdata->Kr=Kr; + rdata->maxIterations=eNB->ulsch[UE_id]->max_turbo_iterations; + rdata->ulsch_harq=ulsch_harq; + rdata->eNB=eNB; + rdata->nbSegments=ulsch_harq->C; + rdata->segment_r=r; + rdata->Fbits=(r==0) ? ulsch_harq->F : 0; + rdata->r_offset=r_offset; + rdata->offset=offset; + rdata->function=td; + int Fbytes=(r==0) ? rdata->Fbits>>3 : 0; + int sz=Kr_bytes - Fbytes - ((ulsch_harq->C>1)?3:0); + pushTpool(proc->threadPool,req); + proc->nbDecode++; + LOG_D(PHY,"Added a block to decode, in pipe: %d\n",proc->nbDecode); + r_offset+=E; + offset+=sz; + } return(ret); } -int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - int ret = 0; - /*if(get_thread_worker_conf() == WORKER_ENABLE) - { - ret = ulsch_decoding_data_2thread(eNB,UE_id,harq_pid,llr8_flag); - } - else*/ - { - ret = ulsch_decoding_data(eNB,UE_id,harq_pid,llr8_flag); - } - return ret; +int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, + int UE_id,int harq_pid,int llr8_flag) { + return ulsch_decoding_data(eNB,proc,UE_id,harq_pid,llr8_flag); } static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline)); @@ -767,7 +440,6 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, else harq_pid = subframe2harq_pid(frame_parms,proc->frame_rx,subframe); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1); // x1 is set in lte_gold_generic x2 = ((uint32_t)ulsch->rnti<<14) + ((uint32_t)subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1 ulsch_harq = ulsch->harq_processes[harq_pid]; @@ -779,8 +451,9 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, A = ulsch_harq->TBS; Q_m = ulsch_harq->Qm; G = nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch; + LOG_D(PHY, "PUSCH nb_rb %d Q_m %d ulsch_harq->Nsymb_pusch %d\n",nb_rb, Q_m, ulsch_harq->Nsymb_pusch); //#ifdef DEBUG_ULSCH_DECODING - LOG_D(PHY,"[PUSCH %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): A %d, round %d, RV %d, O_r1 %d, O_RI %d, O_ACK %d, G %d, Q_m %d Nsymb_pusch %d nb_rb %d\n", + LOG_D(PHY,"[PUSCH harq %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): TBS %d, round %d, RV %d, O_r1 %d, O_RI %d, O_ACK %d, G %d, Q_m %d Nsymb_pusch %d nb_rb %d\n", harq_pid, proc->frame_rx,subframe, frame_parms->Nid_cell,ulsch->rnti,x2, @@ -833,6 +506,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, subframe); // Compute Q_ri Qprime = ulsch_harq->O_RI*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_ri_times8; + LOG_D(PHY, "Qprime %d, O_RI %d, Msc %d, Nym %d beta %d\n", + Qprime, + ulsch_harq->O_RI, + ulsch_harq->Msc_initial, + ulsch_harq->Nsymb_initial, + ulsch->beta_offset_ri_times8); if (Qprime > 0 ) { if ((Qprime % (8*sumKr)) > 0) @@ -893,7 +572,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, G = G - Q_RI - Q_CQI; ulsch_harq->G = G; AssertFatal((int)G > 0, - "FATAL: ulsch_decoding.c G < 0 (%d) : Q_RI %d, Q_CQI %d\n",G,Q_RI,Q_CQI); + "FATAL: ulsch_decoding.c G < 0 (%u) : Q_RI %u, Q_CQI %u\n",G,Q_RI,Q_CQI); H = G + Q_CQI; Hprime = H/Q_m; // Demultiplexing/Deinterleaving of PUSCH/ACK/RI/CQI @@ -1209,8 +888,8 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=2; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -1222,10 +901,10 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=4; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -1237,12 +916,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=6; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -1280,7 +959,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, */ int16_t *yp,*ep; - for (iprime=0,yp=&y[j2],ep=&ulsch_harq->e[0]; + for (iprime=0,yp=&y[j2],ep=&ulsch_harq->eUL[0]; iprime<G; iprime+=8,j2+=8,ep+=8,yp+=8) { ep[0] = yp[0]; @@ -1404,7 +1083,6 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, LOG_D(PHY,"frame %d subframe %d O_ACK:%d o_ACK[]=%d:%d:%d:%d\n",frame,subframe,ulsch_harq->O_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]); // Do ULSCH Decoding for data portion - ret = ulsch_decoding_data_all(eNB,UE_id,harq_pid,llr8_flag); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0); + ret = ulsch_decoding_data_all(eNB,proc, UE_id,harq_pid,llr8_flag); return(ret); } diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c index 4ca9a7c7625f19470fb3023269e37081ade943d2..7442a0ae7e0ff225c9486ff8442308d811127ea2 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c @@ -793,7 +793,7 @@ int dlsch_encoding_SIC(PHY_VARS_UE *ue, r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], G, //G dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, + dlsch->harq_processes[harq_pid]->eDL+r_offset, dlsch->harq_processes[harq_pid]->C, // C dlsch->Nsoft, // Nsoft, dlsch->Mdlharq, diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c index 5c75dd250cff86a92eb3e50a38f8ef5d0442e098..e4083863f0da352bfd5c74998414cbd768526601 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c @@ -65,7 +65,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 uint16_t *prach_root_sequence_map; uint16_t preamble_offset,preamble_shift; uint16_t preamble_index0,n_shift_ra,n_shift_ra_bar; - uint16_t d_start,numshift; + uint16_t d_start=-1,numshift; uint8_t prach_fmt = get_prach_fmt(prach_ConfigIndex,frame_type); //uint8_t Nsp=2; //uint8_t f_ra,t1_ra; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c index cc1f762e7046b9836d0c898d6c459afd9f34cb89..de1c3891da078517be8425ebf1556a916df5b6ec 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c @@ -446,6 +446,13 @@ uint32_t ulsch_encoding(uint8_t *a, Qprime = (ulsch->O + L) * ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_cqi_times8; else Qprime = 0; + LOG_D(PHY,"Qprime %d, O_RI %d + %d, Msc %d, Nym %d beta %d\n", + Qprime, + ulsch->O, L, + ulsch->harq_processes[harq_pid]->Msc_initial, + ulsch->harq_processes[harq_pid]->Nsymb_initial, + ulsch->beta_offset_cqi_times8); + if (Qprime > 0) { if ((Qprime % (8*sumKr)) > 0) @@ -455,7 +462,7 @@ uint32_t ulsch_encoding(uint8_t *a, } G = ulsch->harq_processes[harq_pid]->nb_rb * (12 * Q_m) * (ulsch->Nsymb_pusch); - + LOG_D(PHY,"G: rb %d * ( 12 * Qm %d ) * nsymb %d, Qprime %d, O_RI %d\n", ulsch->harq_processes[harq_pid]->nb_rb, Q_m, ulsch->Nsymb_pusch, Qprime, ulsch->O_RI); if (Qprime > (G - ulsch->O_RI)) Qprime = G - ulsch->O_RI; @@ -465,6 +472,7 @@ uint32_t ulsch_encoding(uint8_t *a, G = G - Q_RI - Q_CQI; + LOG_D(PHY,"new G: %d, Q_RI %d Q_CQI %d\n", G , Q_RI , Q_CQI); ulsch->harq_processes[harq_pid]->G = G; /* diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index ccec73d40e9c7f9a93cb7f0122d3d05d62040667..c7b14571b7d14f5d846eca804ee3418134e4454a 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -137,7 +137,7 @@ void nr_fill_cce_list(PHY_VARS_gNB *gNB, uint8_t m) { int N_reg = n_rb * pdcch_pdu_rel15->DurationSymbols; - int C; + int C=-1; for (int d=0;d<pdcch_pdu_rel15->numDlDci;d++) { int L = pdcch_pdu_rel15->AggregationLevel[d]; @@ -210,7 +210,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, for (int i=0;i<pdcch_pdu_rel15->numDlDci;i++) { - uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->Payload[i]; + //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->Payload[i]; int dlsch_id = find_nr_dlsch(pdcch_pdu_rel15->RNTI[i],gNB,SEARCH_EXIST_OR_FREE); @@ -248,7 +248,7 @@ void nr_fill_ul_dci(PHY_VARS_gNB *gNB, for (int i=0;i<pdcch_pdu_rel15->numDlDci;i++) { - uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->Payload[i]; + //uint64_t *dci_pdu = (uint64_t*)pdcch_pdu_rel15->Payload[i]; // if there's no DL DCI then generate CCE list if (gNB->pdcch_pdu) nr_fill_cce_list(gNB,0); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 3f16bc246562ca66202e7366f5cddbd7957dc22b..adef4a759277c8371e089239310394e79ad8640d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -88,7 +88,7 @@ int32_t generate_nr_prach( PHY_VARS_NR_UE *ue, uint8_t eNB_id, uint8_t subframe, uint16_t *prach_root_sequence_map; uint16_t preamble_offset,preamble_shift; uint16_t preamble_index0,n_shift_ra,n_shift_ra_bar; - uint16_t d_start,numshift; + uint16_t d_start=-1,numshift; uint16_t prach_fmt = get_nr_prach_fmt(prach_ConfigIndex,fp->frame_type,fp->freq_range); //uint8_t Nsp=2; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index f1d4a304f979554d0125b83a9870fd738d2a3b15..a15851bf4910a0476f657cbb75de0b2b516179cf 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -116,7 +116,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, uint16_t beta_ptrs; // PTRS parameter related to power control NR_UE_ULSCH_t *ulsch_ue; - NR_UL_UE_HARQ_t *harq_process_ul_ue; + NR_UL_UE_HARQ_t *harq_process_ul_ue=NULL; NR_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; NR_UE_PUSCH *pusch_ue = UE->pusch_vars[thread_id][gNB_id]; uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES]; diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index dbcd9540be3478d1a917914e60a6763156950579..8621898d9d4c09db5a16ff1f3186c2960d241617 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -325,12 +325,18 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, // PUSCH I/Q of MF Output if (pusch_comp!=NULL) { ind=0; + int range=80*1000*1000; for (k=0; k<frame_parms->symbols_per_tti; k++) { for (i=0; i<12*frame_parms->N_RB_UL; i++) { - I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; - Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; - ind++; + if ( pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i] > -range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i] < range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1] > -range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1] < range ) { + I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; + Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; + ind++; + } } } diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h index b9777686eac01601edfc2bed4835adec187cb10e..2deab40f27fef6bb44ee41327ffd6e38bd0901f0 100644 --- a/openair1/PHY/TOOLS/time_meas.h +++ b/openair1/PHY/TOOLS/time_meas.h @@ -33,7 +33,7 @@ #include <linux/types.h> // global var to enable openair performance profiler extern int opp_enabled; -double cpu_freq_GHz; +double cpu_freq_GHz __attribute__ ((aligned(32)));; #if defined(__x86_64__) || defined(__i386__) typedef struct { diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h index 10496ced20dd7c0f4600a048bbf403a069362604..2fd4d0ea663d0c9fc6045ab40598ea1e6b56383a 100644 --- a/openair1/PHY/defs_RU.h +++ b/openair1/PHY/defs_RU.h @@ -38,6 +38,7 @@ #include "openairinterface5g_limits.h" #include "PHY/TOOLS/time_meas.h" #include "defs_common.h" +#include <openair2/PHY_INTERFACE/IF_Module.h> #define MAX_BANDS_PER_RRU 4 diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 7b06f6c8c70665beefc627d4b76678129ce7bd1e..557b8bfc30e0108105f79f7d3328ee6bf2b05bc7 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -201,41 +201,11 @@ typedef struct { int repetition_number[4]; } LTE_eNB_PRACH; -/// Context data structure for RX/TX portion of subframe processing -typedef struct { - /// Component Carrier index - uint8_t CC_id; - /// timestamp transmitted to HW - openair0_timestamp timestamp_tx; - /// subframe to act upon for transmission - int subframe_tx; - /// subframe to act upon for reception - int subframe_rx; - /// frame to act upon for transmission - int frame_tx; - /// frame to act upon for reception - int frame_rx; - /// \brief Instance count for RXn-TXnp4 processing thread. - /// \internal This variable is protected by \ref mutex_rxtx. - int instance_cnt; - /// pthread structure for RXn-TXnp4 processing thread - pthread_t pthread; - /// pthread attributes for RXn-TXnp4 processing thread - pthread_attr_t attr; - /// condition variable for tx processing thread - pthread_cond_t cond; - /// mutex for RXn-TXnp4 processing thread - pthread_mutex_t mutex; - /// scheduling parameters for RXn-TXnp4 thread - struct sched_param sched_param_rxtx; - - /// \internal This variable is protected by \ref mutex_RUs. - int instance_cnt_RUs; - /// condition variable for tx processing thread - pthread_cond_t cond_RUs; - /// mutex for RXn-TXnp4 processing thread - pthread_mutex_t mutex_RUs; -} L1_rxtx_proc_t; +#include "PHY/TOOLS/time_meas.h" +#include "PHY/CODING/coding_defs.h" +#include "PHY/TOOLS/tools_defs.h" +#include "PHY/LTE_TRANSPORT/transport_eNB.h" + typedef struct { struct PHY_VARS_eNB_s *eNB; @@ -694,6 +664,57 @@ typedef struct PHY_VARS_eNB_s { int32_t pusch_stats_mcs[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX][10240]; int32_t pusch_stats_BO[NUMBER_OF_UE_MAX][10240]; + uint8_t *FS6bufferZone; } PHY_VARS_eNB; + +struct turboReqId { + uint16_t rnti; + uint16_t frame; + uint8_t subframe; + uint8_t codeblock; + uint16_t spare; +} __attribute__((packed)); + +union turboReqUnion { + struct turboReqId s; + uint64_t p; +}; + +typedef struct TurboDecode_s { + PHY_VARS_eNB *eNB; + decoder_if_t *function; + uint8_t decoded_bytes[3+1768] __attribute__((aligned(32))); + int UEid; + int harq_pid; + int frame; + int subframe; + int Fbits; + int Kr; + LTE_UL_eNB_HARQ_t *ulsch_harq; + int nbSegments; + int segment_r; + int r_offset; + int offset; + int maxIterations; + int decodeIterations; +} turboDecode_t; + +#define TURBO_SIMD_SOFTBITS 96+12+3+3*6144 +typedef struct turboEncode_s { + uint8_t * input; + int Kr_bytes; + int filler; + unsigned int G; + int r; + int harq_pid; + int round; + int r_offset; + LTE_eNB_DLSCH_t *dlsch; + time_stats_t *rm_stats; + time_stats_t *te_stats; + time_stats_t *i_stats; +} turboEncode_t; + + #endif /* __PHY_DEFS_ENB__H__ */ diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index 16fcc75a794259e6d9df5238a6c0266846041244..96a073fbb8ca86baf98bfa5f12f1c529d76e2c51 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -732,7 +732,7 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE) { AssertFatal(1==0,"NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE not handled yet\n"); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE) { - AssertFatal((UE_id = find_uci(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti, + AssertFatal((UE_id = find_uci(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti, proc->frame_tx,proc->subframe_tx,eNB,SEARCH_EXIST_OR_FREE))>=0, "No available UE UCI for rnti %x\n",ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti); handle_uci_sr_pdu(eNB,UE_id,ul_config_pdu,frame,subframe,srs_present); @@ -745,9 +745,8 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, } } -void schedule_response(Sched_Rsp_t *Sched_INFO) { +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc) { PHY_VARS_eNB *eNB; - L1_rxtx_proc_t *proc; // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; uint8_t CC_id = Sched_INFO->CC_id; @@ -767,7 +766,6 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { AssertFatal(RC.eNB[Mod_id][CC_id]!=NULL,"RC.eNB[%d][%d] is null\n",Mod_id,CC_id); eNB = RC.eNB[Mod_id][CC_id]; fp = &eNB->frame_parms; - proc = &eNB->proc.L1_proc; /* TODO: check that following line is correct - in the meantime it is disabled */ //if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)==SF_UL)) return; ul_subframe = pdcch_alloc2ul_subframe(fp,subframe); @@ -1020,11 +1018,11 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { /*Dummy functions*/ -int memcpy_dl_config_req (nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { +int memcpy_dl_config_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { return 0; } -int memcpy_ul_config_req (nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { +int memcpy_ul_config_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { return 0; } diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h index 05ec813917be7b0122dcba129c43f3fddab841c0..4da1fa63ec54b5493e520b018b4dbc78ecc157c0 100644 --- a/openair1/SCHED/fapi_l1.h +++ b/openair1/SCHED/fapi_l1.h @@ -37,10 +37,10 @@ #include "SCHED/sched_common.h" #include "nfapi_interface.h" -void fill_uci_harq_indication(PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci,int frame,int subframe,uint8_t *harq_ack,uint8_t tdd_mapping_mode,uint16_t tdd_multiplexing_mask); +void fill_uci_harq_indication(int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci,int frame,int subframe,uint8_t *harq_ack,uint8_t tdd_mapping_mode,uint16_t tdd_multiplexing_mask); void fill_ulsch_harq_indication(PHY_VARS_eNB *eNB,LTE_UL_eNB_HARQ_t *ulsch_harq,uint16_t rnti, int frame,int subframe,int bundling); void fill_ulsch_cqi_indication(PHY_VARS_eNB *eNB,uint16_t frame,uint8_t subframe,LTE_UL_eNB_HARQ_t *ulsch_harq,uint16_t rnti); -void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat); +void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat); void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe); void fill_crc_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe,uint8_t crc_flag); void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,nfapi_dl_config_request_pdu_t *dl_config_pdu); @@ -81,4 +81,4 @@ void handle_uci_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu void handle_srs_pdu(PHY_VARS_eNB *eNB,nfapi_ul_config_request_pdu_t *ul_config_pdu,uint16_t frame,uint8_t subframe); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 45448068ae9ffa68b67383b21b1a8fea838d8904..ba03e79e624178cb781e930d6126fab06a317e99 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -47,6 +47,7 @@ #include <time.h> #include "intertask_interface.h" +#include <executables/split_headers.h> #define MBMS_NFAPI_SCHEDULER @@ -303,6 +304,7 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, start_meas(&eNB->dlsch_encoding_stats); dlsch_encoding_all(eNB, + proc, dlsch_harq->pdu, dlsch_harq->pdsch_start, dlsch, @@ -317,6 +319,14 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, &eNB->dlsch_interleaving_stats); stop_meas(&eNB->dlsch_encoding_stats); + if ( proc->threadPool->activated ) { + // Wait all other threads finish to process + while (proc->nbEncode) { + delNotifiedFIFO_elt(pullTpool(proc->respEncode, proc->threadPool)); + proc->nbEncode--; + } + } + if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1) { print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr); } @@ -431,6 +441,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here for (i=0; i<NUMBER_OF_UE_MAX; i++) { if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; + else harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); @@ -591,7 +602,12 @@ void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } } -void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { +void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { + if ( split73 == SPLIT73_DU ) { + sendFs6Ulharq(fs6ULindicationSr, UEid, eNB, NULL, frame, subframe, NULL,0,0, rnti, stat); + return; + } + pthread_mutex_lock(&eNB->UL_INFO_mutex); nfapi_sr_indication_t *sr_ind = &eNB->UL_INFO.sr_ind; nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body; @@ -604,6 +620,7 @@ void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,u pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; int SNRtimes10 = dB_fixed_times10(stat) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; + LOG_D(PHY,"stat %d subbandpower %d, SNRtimes10 %d\n", stat, eNB->measurements.n0_subband_power_dB[0][0], SNRtimes10); pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; if (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0; @@ -714,7 +731,7 @@ uci_procedures(PHY_VARS_eNB *eNB, if (uci->type == SR) { if (SR_payload == 1) { - fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); break; } else { break; @@ -748,7 +765,7 @@ uci_procedures(PHY_VARS_eNB *eNB, /* cancel SR detection if reception on n1_pucch0 is better than on SR PUCCH resource index, otherwise send it up to MAC */ if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0; - else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + else if (SR_payload == 1) fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); if (uci->type==HARQ_SR && metric[0] <= metric_SR) { /* when transmitting ACK/NACK on SR PUCCH resource index, SR payload is always 1 */ @@ -773,7 +790,7 @@ uci_procedures(PHY_VARS_eNB *eNB, frame,subframe, pucch_b0b1[0][0],metric[0]); uci->stat = metric[0]; - fill_uci_harq_indication(eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff); + fill_uci_harq_indication(i, eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff); } else { // frame_type == TDD LOG_D(PHY,"Frame %d Subframe %d Demodulating PUCCH (UCI %d) for ACK/NAK (uci->pucch_fmt %d,uci->type %d.uci->frame %d, uci->subframe %d): n1_pucch0 %d SR_payload %d\n", frame,subframe,i, @@ -795,7 +812,7 @@ uci_procedures(PHY_VARS_eNB *eNB, ); if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0; - else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + else if (SR_payload == 1) fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); if (uci->type==HARQ_SR && metric[0] <= metric_SR) { SR_payload = 1; @@ -877,7 +894,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = metric[0]; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode } else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==2)) { // multiplexing + no SR, implement Table 10.1.3-5 (Rel14) for multiplexing with M=2 if (pucch_b0b1[0][0] == 4 || pucch_b0b1[1][0] == 4) { // there isn't a likely transmission @@ -913,7 +930,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max(metric[0],metric[1]); - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } //else if ((uci->tdd_bundling == 0) && (res==2)) else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==3)) { // multiplexing + no SR, implement Table 10.1.3-6 (Rel14) for multiplexing with M=3 if (harq_ack[0] == 4 || @@ -984,7 +1001,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max_metric; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } } //else if ((uci->tdd_bundling == 0) && (res==3)) else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==4)) { // multiplexing + no SR, implement Table 10.1.3-7 (Rel14) for multiplexing with M=4 @@ -1106,14 +1123,14 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max_metric; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } // else if ((uci->tdd_bundling == 0) && (res==4)) else { // bundling harq_ack[0] = pucch_b0b1[0][0]; harq_ack[1] = pucch_b0b1[0][1]; uci->stat = metric[0]; LOG_D(PHY,"bundling: (%d,%d), metric %d\n",harq_ack[0],harq_ack[1],uci->stat); - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode } #ifdef DEBUG_PHY_PROC @@ -1144,8 +1161,93 @@ uci_procedures(PHY_VARS_eNB *eNB, } // end loop for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { } +void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { + turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); + + LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid]; + LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + PHY_VARS_eNB *eNB=rdata->eNB; + + bool decodeSucess=rdata->decodeIterations <= rdata->maxIterations; + ulsch_harq->processedSegments++; + LOG_D(PHY, "processing result of segment: %d, ue %d, processed %d/%d\n", + rdata->segment_r, rdata->UEid, ulsch_harq->processedSegments, rdata->nbSegments); + proc->nbDecode--; + LOG_D(PHY,"remain to decoded in subframe: %d\n", proc->nbDecode); + if (decodeSucess) { + int Fbytes=(rdata->segment_r==0) ? rdata->Fbits>>3 : 0; + int sz=(rdata->Kr>>3) - Fbytes - ((ulsch_harq->C>1)?3:0); + memcpy(ulsch_harq->decodedBytes+rdata->offset, + rdata->decoded_bytes+Fbytes, + sz); + } else { + if ( rdata->nbSegments != ulsch_harq->processedSegments ) { + int nb=abortTpool(proc->threadPool, req->key); + nb+=abortNotifiedFIFO(proc->respDecode, req->key); + proc->nbDecode-=nb; + LOG_I(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); + AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", + ulsch_harq->processedSegments, nb, rdata->nbSegments); + ulsch_harq->processedSegments=rdata->nbSegments; + } + } + + // if this UE segments are all done + if ( rdata->nbSegments == ulsch_harq->processedSegments) { + //compute the expected ULSCH RX power (for the stats) + int i=rdata->UEid; + ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,rdata->harq_pid, 0); // 0 means bw_factor is not considered + if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */ + if (ulsch_harq->cqi_crc_status == 1) { + fill_ulsch_cqi_indication(eNB,rdata->frame,rdata->subframe,ulsch_harq,ulsch->rnti); + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << rdata->subframe)); + } else { + if(RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag & (1 << rdata->subframe) ) { + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << rdata->subframe)); + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_timer=30; + LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",rdata->frame,rdata->subframe); + } + } + } + + if (!decodeSucess) { + fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,1); // indicate NAK to MAC + fill_rx_indication(eNB,i,rdata->frame,rdata->subframe); // indicate SDU to MAC + LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", + eNB->Mod_id,rdata->harq_pid, + rdata->frame,rdata->subframe, i, + ulsch_harq->round, + ulsch->Mlimit, + ulsch_harq->o_ACK[0], + ulsch_harq->o_ACK[1]); + + if (ulsch_harq->round >= 3) { + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + ulsch_harq->round = 0; + } + /* Mark the HARQ process to release it later if max transmission reached + * (see below). + * MAC does not send the max transmission count, we have to deal with it + * locally in PHY. + */ + ulsch_harq->handled = 1; + } // ulsch in error + else if(ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions){ + fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,0); // indicate ACK to MAC + fill_rx_indication(eNB,i,rdata->frame,rdata->subframe); // indicate SDU to MAC + ulsch_harq->status = SCH_IDLE; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + } // ulsch not in error + + if (ulsch_harq->O_ACK>0) + fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,rdata->frame,rdata->subframe,ulsch->bundling); + } +} + void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { - uint32_t ret=0,i; + uint32_t i; uint32_t harq_pid; uint8_t nPRS; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -1154,7 +1256,6 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); - int rvidx_tab[4] = {0,2,3,1}; for (i = 0; i < NUMBER_OF_UE_MAX; i++) { ulsch = eNB->ulsch[i]; @@ -1208,127 +1309,13 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { rx_ulsch(eNB,proc, i); stop_meas(&eNB->ulsch_demodulation_stats); start_meas(&eNB->ulsch_decoding_stats); - ret = ulsch_decoding(eNB,proc, + ulsch_decoding(eNB,proc, i, 0, // control_only_flag ulsch_harq->V_UL_DAI, ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); - LOG_D(PHY, - "[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n", - eNB->Mod_id,harq_pid, - frame,subframe, - ulsch->rnti, - dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]), - dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]), - 30,//eNB->measurements.n0_power_dB[0], - 30,//eNB->measurements.n0_power_dB[1], - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1], - ret, - ulsch_harq->cqi_crc_status, - ulsch_harq->O_ACK, - eNB->ulsch_decoding_stats.p_time, eNB->ulsch_decoding_stats.max); - if (ulsch_harq->repetition_number < ulsch_harq->total_number_of_repetitions){ - ulsch_harq->rvidx = rvidx_tab[(ulsch_harq->repetition_number%4)] ; // Set the correct rvidx for the next emtc repetitions - ulsch_harq->repetition_number +=1 ; // Increment repetition_number for the next ULSCH allocation - } - //compute the expected ULSCH RX power (for the stats) - ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered - - if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */ - if (ulsch_harq->cqi_crc_status == 1) { -#ifdef DEBUG_PHY_PROC - //if (((frame%10) == 0) || (frame < 50)) - print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL); -#endif - fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti); - RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - } else { - if(RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ) { - RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_timer=30; - LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",frame,subframe); - } - } - } - - if (ret == (1+MAX_TURBO_ITERATIONS)) { - T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti), - T_INT(harq_pid)); - fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC - fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC - LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", - eNB->Mod_id,harq_pid, - frame,subframe, i, - ulsch_harq->round, - ulsch->Mlimit, - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1]); - - if (ulsch_harq->round >= 3) { - ulsch_harq->status = SCH_IDLE; - ulsch_harq->handled = 0; - ulsch->harq_mask &= ~(1 << harq_pid); - ulsch_harq->round = 0; - } - - MSC_LOG_RX_DISCARDED_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u ULSCH received rnti %x harq id %u round %d", - frame,subframe, - ulsch->rnti,harq_pid, - ulsch_harq->round-1 - ); - /* Mark the HARQ process to release it later if max transmission reached - * (see below). - * MAC does not send the max transmission count, we have to deal with it - * locally in PHY. - */ - ulsch_harq->handled = 1; - } // ulsch in error - else if(ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions){ - fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC - fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC - ulsch_harq->status = SCH_IDLE; - ulsch->harq_mask &= ~(1 << harq_pid); - T (T_ENB_PHY_ULSCH_UE_ACK, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (ulsch->rnti), T_INT (harq_pid)); - MSC_LOG_RX_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u ULSCH received rnti %x harq id %u", - frame,subframe, - ulsch->rnti,harq_pid - ); -#ifdef DEBUG_PHY_PROC -#ifdef DEBUG_ULSCH - LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe, - harq_pid,ulsch_harq->TBS>>3); - - for (j=0; j<ulsch_harq->TBS>>3; j++) - LOG_T(PHY,"%x.",ulsch->harq_processes[harq_pid]->b[j]); - - LOG_T(PHY,"\n"); -#endif -#endif - } // ulsch not in error - - if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,frame,subframe,ulsch->bundling); - - LOG_D(PHY,"[eNB %d] Frame %d subframe %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n", - eNB->Mod_id,frame,subframe, - harq_pid, - i, - ret, - ulsch_harq->cqi_crc_status, - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1], - eNB->UE_stats[i].ulsch_errors[harq_pid], - eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); - } // if ((ulsch) && - // (ulsch->rnti>0) && - // (ulsch_harq->status == ACTIVE)) + } else if ((ulsch) && (ulsch->rnti>0) && (ulsch_harq->status == ACTIVE) && @@ -1342,6 +1329,12 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); } } // for (i=0; i<NUMBER_OF_UE_MAX; i++) + + while (proc->nbDecode > 0) { + notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool); + postDecode(proc, req); + delNotifiedFIFO_elt(req); + } } extern int oai_exit; @@ -1349,24 +1342,29 @@ extern int oai_exit; extern void *td_thread (void *); void init_td_thread(PHY_VARS_eNB *eNB) { + /* L1_proc_t *proc = &eNB->proc; proc->tdp.eNB = eNB; proc->instance_cnt_td = -1; threadCreate(&proc->pthread_td, td_thread, (void *)&proc->tdp, "TD", -1, OAI_PRIORITY_RT); + */ } void kill_td_thread(PHY_VARS_eNB *eNB) { + /* L1_proc_t *proc = &eNB->proc; proc->instance_cnt_td = 0; pthread_cond_signal(&proc->cond_td); pthread_join(proc->pthread_td, NULL); pthread_mutex_destroy( &proc->mutex_td ); pthread_cond_destroy( &proc->cond_td ); + */ } extern void *te_thread (void *); void init_te_thread(PHY_VARS_eNB *eNB) { + /* L1_proc_t *proc = &eNB->proc; for(int i=0; i<3 ; i++) { @@ -1377,9 +1375,11 @@ void init_te_thread(PHY_VARS_eNB *eNB) { sprintf(txt,"TE_%d", i); threadCreate(&proc->tep[i].pthread_te, te_thread, (void *)&proc->tep[i], txt, -1, OAI_PRIORITY_RT); } + */ } void kill_te_thread(PHY_VARS_eNB *eNB) { + /* L1_proc_t *proc = &eNB->proc; for(int i=0; i<3 ; i++) { @@ -1389,6 +1389,7 @@ void kill_te_thread(PHY_VARS_eNB *eNB) { pthread_mutex_destroy( &proc->tep[i].mutex_te); pthread_cond_destroy( &proc->tep[i].cond_te); } + */ } void fill_rx_indication(PHY_VARS_eNB *eNB, @@ -1416,7 +1417,7 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation - pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->b; + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->decodedBytes; // estimate timing advance for MAC sync_pos = lte_est_timing_advance_pusch(eNB,UE_id); timing_advance_update = sync_pos; // - eNB->frame_parms.nb_prefix_samples/4; //to check @@ -1749,7 +1750,12 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har pthread_mutex_unlock(&eNB->UL_INFO_mutex); } -void fill_uci_harq_indication (PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { +void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { + if ( split73 == SPLIT73_DU ) { + sendFs6Ulharq(fs6ULindicationHarq, UEid, eNB, uci, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask, 0, 0); + return; + } + int UE_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST); //AssertFatal(UE_id>=0,"UE_id doesn't exist rnti:%x\n", uci->rnti); diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c index 6d392b04378bb41b7bab838f3854c92d4077a0c0..8846b77af9f9b756bbc308012bf8494792012ac6 100644 --- a/openair1/SCHED/ru_procedures.c +++ b/openair1/SCHED/ru_procedures.c @@ -321,7 +321,7 @@ void feptx_ofdm(RU_t *ru, fp->nb_prefix_samples, CYCLIC_PREFIX); } else { - if(is_pmch_subframe(ru->proc.frame_tx,subframe,fp)/*subframe==1*/){ + if(is_pmch_subframe(frame,subframe,fp)/*subframe==1*/){ normal_prefix_mod(&ru->common.txdataF_BF[aa][0], dummy_tx_b, 2, @@ -426,7 +426,7 @@ void feptx_ofdm(RU_t *ru, stop_meas(&ru->ofdm_mod_stats); LOG_D(PHY,"feptx_ofdm (TXPATH): frame %d, subframe %d: txp (time %p) %d dB, txp (freq) %d dB\n", - ru->proc.frame_tx,subframe,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->samples_per_tti)), + frame,subframe,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->samples_per_tti)), dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF))); } } diff --git a/openair1/SCHED/sched_common.h b/openair1/SCHED/sched_common.h index e9af869b05518d68b71d05f4efef29ec90a9adeb..f3e43d516ece342271860bad060b5669da6bb01b 100644 --- a/openair1/SCHED/sched_common.h +++ b/openair1/SCHED/sched_common.h @@ -311,7 +311,7 @@ void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id); int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id, uint8_t eNB_index); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); diff --git a/openair1/SCHED/sched_eNB.h b/openair1/SCHED/sched_eNB.h index e74b9a312fda7bc7ed76430b83a73b4b92d9fa15..f04bec2e5c45f691d75fb0e39aeaae07c34d409f 100644 --- a/openair1/SCHED/sched_eNB.h +++ b/openair1/SCHED/sched_eNB.h @@ -128,8 +128,8 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc); @param br_flag indicator for eMTC PRACH */ -void prach_procedures(PHY_VARS_eNB *eNB, - int br_flag); +void prach_procedures(PHY_VARS_eNB *eNB, + int br_flag); /*! \brief Function to compute timing of Msg3 transmission on UL-SCH (first UE transmission in RA procedure). This implements the timing in paragraph a) from Section 6.1.1 in 36.213 (p. 17 in version 8.6). Used by eNB upon transmission of random-access response (RA_RNTI) to program corresponding ULSCH reception procedure. Used by UE upon reception of random-access response (RA_RNTI) to program corresponding ULSCH transmission procedure. This does not support the UL_delay field in RAR (always assumed to be 0). @@ -193,7 +193,7 @@ int8_t find_ue_ulsch(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); LTE_eNB_UE_stats *get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); @@ -218,8 +218,6 @@ int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subf void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset); void release_rnti_of_phy(module_id_t mod_id); - -void ru_fep_full_2thread(RU_t *ru, int subframe); /*@}*/ diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index fa22e43661f5fd9a0fd0f419ca12a0cea039af51..a36cebd6aeed3b8c7c26007384bf805396a8ca16 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -202,7 +202,7 @@ int set_tdd_config_nr( nfapi_nr_config_request_scf_t *cfg, void add_tdd_dedicated_configuration_nr(NR_DL_FRAME_PARMS *frame_parms, int slotIndex, int nrofDownlinkSymbols, int nrofUplinkSymbols) { TDD_UL_DL_SlotConfig_t *p_TDD_UL_DL_ConfigDedicated = frame_parms->p_TDD_UL_DL_ConfigDedicated; - TDD_UL_DL_SlotConfig_t *p_previous_TDD_UL_DL_ConfigDedicated; + TDD_UL_DL_SlotConfig_t *p_previous_TDD_UL_DL_ConfigDedicated=NULL; int next = 0; while (p_TDD_UL_DL_ConfigDedicated != NULL) { diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 509f4b60213bb27365d70386e3eee91545275463..1f46408e48cdf83fa97aedc748e71a433a8151a4 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2460,7 +2460,7 @@ ue->prach_resources[eNB_id]->ra_PreambleIndex = preamble_tx; ue->tx_total_RE[nr_tti_tx] = 96; #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) - ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm[nr_tti_tx], + ue->prach_vars[eNB_id]->amp = nr_get_tx_amp(ue->tx_power_dBm[nr_tti_tx], ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL, 6); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 6706b0f91238d22f979825a85af8593ca55d1cab..f65e1f9633f14bdc898ca4937d6a6f8af2af1cd5 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -59,6 +59,7 @@ #include "unitary_defs.h" #include "dummy_functions.c" #include "executables/thread-common.h" +#include "executables/split_headers.h" void feptx_ofdm(RU_t *ru, int frame, int subframe); void feptx_prec(RU_t *ru, int frame, int subframe); @@ -78,6 +79,13 @@ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ int emulate_rf = 0; +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} void handler(int sig) { void *array[10]; @@ -515,7 +523,7 @@ int main(int argc, char **argv) { char fname[32],vname[32]; FILE *bler_fd; char bler_fname[256]; - FILE *time_meas_fd; + FILE *time_meas_fd=NULL; char time_meas_fname[256]; // FILE *tikz_fd; // char tikz_fname[256]; @@ -1266,6 +1274,13 @@ int main(int argc, char **argv) { } L1_rxtx_proc_t *proc_eNB = &eNB->proc.L1_proc; + proc_eNB->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); + proc_eNB->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + proc_eNB->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initTpool("n", proc_eNB->threadPool, true); + initNotifiedFIFO(proc_eNB->respEncode); + initNotifiedFIFO(proc_eNB->respDecode); + proc_eNB->frame_tx=0; if (input_fd==NULL) { @@ -1446,7 +1461,7 @@ int main(int argc, char **argv) { sched_resp.subframe=subframe; sched_resp.frame=proc_eNB->frame_tx; eNB->abstraction_flag=0; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_eNB); phy_procedures_eNB_TX(eNB,proc_eNB,1); if (uncoded_ber_bit == NULL) { @@ -1480,7 +1495,7 @@ int main(int argc, char **argv) { TX_req.tx_request_body.number_of_pdus=0; proc_eNB->subframe_tx = subframe+1; sched_resp.subframe=subframe+1; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_eNB); phy_procedures_eNB_TX(eNB,proc_eNB,0); ru->proc.tti_tx=(subframe+1)%10; feptx_prec(ru,proc_eNB->frame_tx,subframe+1); @@ -1583,11 +1598,11 @@ int main(int argc, char **argv) { subframe<<1); for (i=0; i<coded_bits_per_codeword; i++) - if ((eNB->dlsch[0][0]->harq_processes[0]->e[i]==1 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] > 0)|| - (eNB->dlsch[0][0]->harq_processes[0]->e[i]==0 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] < 0)) { + if ((eNB->dlsch[0][0]->harq_processes[0]->eDL[i]==1 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] > 0)|| + (eNB->dlsch[0][0]->harq_processes[0]->eDL[i]==0 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] < 0)) { uncoded_ber_bit[bit_errors++] = 1; printf("error in pos %d : %d => %d\n",i, - eNB->dlsch[0][0]->harq_processes[0]->e[i], + eNB->dlsch[0][0]->harq_processes[0]->eDL[i], UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i]); } else { /* @@ -1634,7 +1649,7 @@ int main(int argc, char **argv) { //pdsch_vars printf("coded_bits_per_codeword %u\n",coded_bits_per_codeword); dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round, UE->dlsch[UE->current_thread_id[subframe]][0][0]->current_harq_pid); - LOG_M("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); + LOG_M("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->eDL,coded_bits_per_codeword,1,4); //pdcch_vars LOG_M("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[0][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); LOG_M("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[0][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index db97240ed55686138b7a67a4903fe1ec3e04f9f9..c950d6f4da2079fe3a23af075fe8e6f5ceb1e547 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -54,6 +54,7 @@ #include "common/config/config_load_configmodule.h" #include "executables/thread-common.h" #include "targets/RT/USER/lte-softmodem.h" +#include "executables/split_headers.h" double cpuf; #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) @@ -81,6 +82,14 @@ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} + extern void fep_full(RU_t *ru, int subframe); extern void ru_fep_full_2thread(RU_t *ru, int subframe); //extern void eNB_fep_full(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); @@ -793,6 +802,13 @@ int main(int argc, char **argv) { proc_rxtx_ue->frame_rx = (subframe<4)?(proc_rxtx->frame_tx-1):(proc_rxtx->frame_tx); proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx; proc_rxtx_ue->subframe_rx = (proc_rxtx->subframe_tx+6)%10; + proc_rxtx->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); + proc_rxtx->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + proc_rxtx->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initTpool("n",proc_rxtx->threadPool, true); + initNotifiedFIFO(proc_rxtx->respEncode); + initNotifiedFIFO(proc_rxtx->respDecode); + printf("Init UL hopping UE\n"); init_ul_hopping(&UE->frame_parms); printf("Init UL hopping eNB\n"); @@ -995,7 +1011,7 @@ int main(int argc, char **argv) { srs_flag); sched_resp.subframe=(subframe+6)%10; sched_resp.frame=(1024+eNB->proc.frame_rx+((subframe<4)?-1:0))&1023; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_rxtx); ///////////////////// if (abstx) { @@ -1270,7 +1286,7 @@ int main(int argc, char **argv) { LOG_UDUMPMSG(SIM,dataArray(table_rx),table_rx->size,LOG_DUMP_DOUBLE,"The receiver raw data: \n"); } - printf("\n**********rb: %d ***mcs : %d *********SNR = %f dB (%f): TX %u dB (gain %f dB), N0W %f dB, I0 %d dB, delta_IF %d [ (%d,%d) dB / (%d,%d) dB ]**************************\n", + printf("\n**********rb: %d ***mcs : %d *********SNR = %f dB (%f): TX %u dB (gain %f dB), N0W %f dB, I0 %u dB, delta_IF %d [ (%d,%d) dB / (%u,%u) dB ]**************************\n", nb_rb,mcs,SNR,SNR2, tx_lev_dB, 20*log10(tx_gain), @@ -1352,7 +1368,7 @@ int main(int argc, char **argv) { printStatIndent2(&eNB->ulsch_deinterleaving_stats,"sub-block interleaving" ); printStatIndent2(&eNB->ulsch_demultiplexing_stats,"sub-block demultiplexing" ); printStatIndent2(&eNB->ulsch_rate_unmatching_stats,"sub-block rate-matching" ); - printf("|__ turbo_decoder(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n", + printf(" |__ turbo_decoder(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n", eNB->ulsch[0]->harq_processes[harq_pid]->Cminus ? eNB->ulsch[0]->harq_processes[harq_pid]->Kminus : eNB->ulsch[0]->harq_processes[harq_pid]->Kplus, diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 30c10940c99fb8496e12b197c8a641baa7a211c2..a85cbac5439465b3ca9d88e2a21241a67bb72ab9 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -290,7 +290,7 @@ Protocol__FlexUlCqiReport * copy_ul_cqi_report(Protocol__FlexUlCqiReport * origi full_ul_report->has_sfn_sn = original->has_sfn_sn; full_ul_report->n_cqi_meas = original->n_cqi_meas; - Protocol__FlexUlCqi **ul_report; + Protocol__FlexUlCqi **ul_report=NULL; ul_report = malloc(sizeof(Protocol__FlexUlCqi *) * full_ul_report->n_cqi_meas); if(ul_report == NULL) goto error; @@ -348,7 +348,7 @@ Protocol__FlexDlCqiReport * copy_dl_cqi_report(Protocol__FlexDlCqiReport * origi dl_report->has_sfn_sn = original->has_sfn_sn; dl_report->n_csi_report = original->n_csi_report; - Protocol__FlexDlCsi **csi_reports; + Protocol__FlexDlCsi **csi_reports=NULL; csi_reports = malloc(sizeof(Protocol__FlexDlCsi *) * dl_report->n_csi_report); if (csi_reports == NULL) goto error; @@ -383,7 +383,7 @@ Protocol__FlexPagingBufferReport * copy_paging_buffer_report(Protocol__FlexPagin protocol__flex_paging_buffer_report__init(copy); copy->n_paging_info = original->n_paging_info; - Protocol__FlexPagingInfo **p_info; + Protocol__FlexPagingInfo **p_info=NULL; p_info = malloc(sizeof(Protocol__FlexPagingInfo *) * copy->n_paging_info); if (p_info == NULL) goto error; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index a42922c300387b7cca6c8a0528726501b9b838c3..00fd40109db819a754e3bbf9ad79810df59b0641 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -2240,7 +2240,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( uint8_t first_ue_total[MAX_NUM_CCs][20]; uint8_t first_ue_id[MAX_NUM_CCs][20]; uint8_t ul_inactivity_num[MAX_NUM_CCs]; - uint8_t ul_inactivity_id[MAX_NUM_CCs][20]; + uint8_t ul_inactivity_id[MAX_NUM_CCs][20]={0}; // LTE_DL_FRAME_PARMS *frame_parms; uint8_t ulsch_ue_max_num[MAX_NUM_CCs]; uint16_t saved_ulsch_dci[MAX_NUM_CCs]; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 656dd885dfde293845ee2b24ef75ad0e3102e22e..3062e5c9647826af5fe547d5fa7a06c7f6707004 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -180,7 +180,7 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->scheduled_ul_bytes = 0; } } else { // sduP == NULL => error - LOG_W(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d, UE_id %d, RNTI %x\n", + LOG_W(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d, UE_id %d, RNTI %x (len %d)\n", enb_mod_idP, harq_pid, CC_idP, @@ -189,7 +189,8 @@ rx_sdu(const module_id_t enb_mod_idP, UE_scheduling_control->round_UL[CC_idP][harq_pid], ul_cqi, UE_id, - current_rnti); + current_rnti, + sdu_lenP); if (ul_cqi > 200) { // too high energy pattern UE_scheduling_control->pusch_snr[CC_idP] = ul_cqi; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 36d285e320e416c7f14d3f0694e01322d6ddc6c7..3c625ec2ff11a7932d8c78427d88d2049070a72b 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -166,6 +166,11 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, nr_dci_pdu_rel15_t *nr_pdci_info_extracted); +uint8_t +nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, + sub_frame_t subframe, uint8_t eNB_index, + uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) ; + int set_tdd_config_nr_ue(fapi_nr_config_request_t *cfg, int mu, int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSlots, int nrofUplinkSymbols); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 93768558823ed86df27e162fca962daebcf729e7..b7fddf9b733fba3d9bc74d66af550b825a027cdc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -507,7 +507,7 @@ void nr_configure_pdcch(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu, AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n"); AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0, "searchPsacesToAddModList is empty\n"); - NR_SearchSpace_t *ss; + NR_SearchSpace_t *ss=NULL; int found=0; int target_ss = NR_SearchSpace__searchSpaceType_PR_common; if (ss_type == 1) { diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h index ca952119221548c2f1d56efde7ac91996ada7fa1..27ca18ed7ee9d2b712254eb43ffbb64850ac78c2 100644 --- a/openair2/LAYER2/RLC/rlc.h +++ b/openair2/LAYER2/RLC/rlc.h @@ -137,7 +137,7 @@ void (*rlc_rrc_data_ind)( const protocol_ctxt_t *const ctxtP, const rb_id_t rb_idP, const sdu_size_t sdu_sizeP, - const uint8_t *const sduP); + const uint8_t *const sduP) __attribute__ ((aligned(32))); void (*rlc_rrc_data_conf)( const protocol_ctxt_t *const ctxtP, @@ -250,7 +250,7 @@ logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; (((hash_key_t)(sESSION_ID)) << 37) | \ (((hash_key_t)(0x0000000000000001)) << 63)) -hash_table_t *rlc_coll_p; +hash_table_t *rlc_coll_p __attribute__ ((aligned(32))); /*! \fn tbs_size_t mac_rlc_serialize_tb (char* bufferP, list_t transport_blocksP) * \brief Serialize a list of transport blocks coming from RLC in order to be processed by MAC. diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c index 32dfa5cc42cc8153134c27322b321f15dd1a1a0d..6f7454c321a7a3fd9e22b480f42e0082b8792348 100644 --- a/openair2/MCE_APP/mce_app.c +++ b/openair2/MCE_APP/mce_app.c @@ -343,7 +343,9 @@ void *MCE_app_task(void *args_p) { /* Try to register each MCE */ // This assumes that node_type of all RRC instances is the same - if (EPC_MODE_ENABLED) { + if ( EPC_MODE_ENABLED && RC.rrc == NULL ) + LOG_E(RRC, "inconsistent global variables\n"); + if (EPC_MODE_ENABLED && RC.rrc ) { register_mce_pending = MCE_app_register(RC.rrc[0]->node_type, mce_id_start, mce_id_end); } diff --git a/openair2/PHY_INTERFACE/IF_Module.c b/openair2/PHY_INTERFACE/IF_Module.c index b5cda35193fea99f9f6f5f580c2f1b38850bde1d..d98c603d78444f2951f2a47bf6413506a959ad83 100644 --- a/openair2/PHY_INTERFACE/IF_Module.c +++ b/openair2/PHY_INTERFACE/IF_Module.c @@ -685,7 +685,7 @@ static void dump_dl(Sched_Rsp_t *d) { /* debug utility functions end */ /****************************************************************************/ -void UL_indication(UL_IND_t *UL_info) { +void UL_indication(UL_IND_t *UL_info, L1_rxtx_proc_t *proc) { AssertFatal(UL_info!=NULL,"UL_INFO is null\n"); #ifdef DUMP_FAPI dump_ul(UL_info); @@ -767,7 +767,7 @@ void UL_indication(UL_IND_t *UL_info) { "schedule_response is null (mod %d, cc %d)\n", module_id, CC_id); - ifi->schedule_response(sched_info); + ifi->schedule_response(sched_info, proc ); } LOG_D(PHY,"Schedule_response: SFN_SF:%d%d dl_pdus:%d\n",sched_info->frame,sched_info->subframe,sched_info->DL_req->dl_config_request_body.number_pdu); diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h index f2602220970220b120b57cd1504cca540556b912..42a4459732326a89b12c5c0ca224c71c8303c325 100644 --- a/openair2/PHY_INTERFACE/IF_Module.h +++ b/openair2/PHY_INTERFACE/IF_Module.h @@ -34,10 +34,12 @@ #include <stdint.h> +#include <sched.h> //#include "openair1/PHY/LTE_TRANSPORT/transport_eNB.h" #include "nfapi_interface.h" #include "platform_constants.h" #include "platform_types.h" +#include <common/utils/threadPool/thread-pool.h> #define MAX_NUM_DL_PDU 100 #define MAX_NUM_UL_PDU 100 @@ -130,16 +132,69 @@ typedef struct { } Sched_Rsp_t; typedef struct { - uint8_t Mod_id; - int CC_id; - nfapi_config_request_t *cfg; -} PHY_Config_t; - -typedef struct IF_Module_s { - //define the function pointer - void (*UL_indication)(UL_IND_t *UL_INFO); - void (*schedule_response)(Sched_Rsp_t *Sched_INFO); - void (*PHY_config_req)(PHY_Config_t *config_INFO); + uint8_t Mod_id; + int CC_id; + nfapi_config_request_t *cfg; +}PHY_Config_t; +#include <targets/ARCH/COMMON/common_lib.h> +/// Context data structure for RX/TX portion of subframe processing +typedef struct { + /// Component Carrier index + uint8_t CC_id; + /// timestamp transmitted to HW + openair0_timestamp timestamp_tx; + openair0_timestamp timestamp_rx; + /// subframe to act upon for transmission + int subframe_tx; + /// subframe to act upon for reception + int subframe_rx; + /// frame to act upon for transmission + int frame_tx; + /// frame to act upon for reception + int frame_rx; + int frame_prach; + int subframe_prach; + int frame_prach_br; + int subframe_prach_br; + /// \brief Instance count for RXn-TXnp4 processing thread. + /// \internal This variable is protected by \ref mutex_rxtx. + int instance_cnt; + /// pthread structure for RXn-TXnp4 processing thread + pthread_t pthread; + /// pthread attributes for RXn-TXnp4 processing thread + pthread_attr_t attr; + /// condition variable for tx processing thread + pthread_cond_t cond; + /// mutex for RXn-TXnp4 processing thread + pthread_mutex_t mutex; + /// scheduling parameters for RXn-TXnp4 thread + struct sched_param sched_param_rxtx; + + /// \internal This variable is protected by \ref mutex_RUs. + int instance_cnt_RUs; + /// condition variable for tx processing thread + pthread_cond_t cond_RUs; + /// mutex for RXn-TXnp4 processing thread + pthread_mutex_t mutex_RUs; + tpool_t *threadPool; + int nbEncode; + int nbDecode; + notifiedFIFO_t *respEncode; + notifiedFIFO_t *respDecode; + pthread_mutex_t mutex_emulateRF; + int instance_cnt_emulateRF; + pthread_t pthread_emulateRF; + pthread_attr_t attr_emulateRF; + pthread_cond_t cond_emulateRF; + int first_rx; +} L1_rxtx_proc_t; + +typedef struct IF_Module_s{ +//define the function pointer + void (*UL_indication)(UL_IND_t *UL_INFO, L1_rxtx_proc_t *proc); + void (*schedule_response)(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); + void (*PHY_config_req)(PHY_Config_t* config_INFO); + void (*PHY_config_update_sib2_req)(PHY_Config_t* config_INFO); void (*PHY_config_update_sib13_req)(PHY_Config_t* config_INFO); uint32_t CC_mask; @@ -165,7 +220,7 @@ void IF_Module_kill(int Mod_id); /*Interface for uplink, transmitting the Preamble(list), ULSCH SDU, NAK, Tick (trigger scheduler) */ -void UL_indication(UL_IND_t *UL_INFO); +void UL_indication(UL_IND_t *UL_INFO, L1_rxtx_proc_t *proc); /*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/ void Schedule_Response(Sched_Rsp_t *Sched_INFO); diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index 21c4efa06c63fe4ab9e622c41283e2879fbcf135..41fb3ddc3a7eebfcdd376c32a3009e75aa602eb4 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -882,7 +882,8 @@ void hi_dci0_req_UE_MAC(int sfn, // The following set of memcpy functions should be getting called as callback // functions from pnf_p7_subframe_ind. -int memcpy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, +int memcpy_dl_config_req(L1_rxtx_proc_t *proc, + nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { dl_config_req = (nfapi_dl_config_request_t *)malloc(sizeof(nfapi_dl_config_request_t)); @@ -910,10 +911,11 @@ int memcpy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, return 0; } -int memcpy_ul_config_req(nfapi_pnf_p7_config_t *pnf_p7, - nfapi_ul_config_request_t *req) { +int memcpy_ul_config_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req) +{ ul_config_req = malloc(sizeof(nfapi_ul_config_request_t)); + ul_config_req->sfn_sf = req->sfn_sf; ul_config_req->vendor_extension = req->vendor_extension; @@ -957,9 +959,12 @@ int memcpy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { return 0; } -int memcpy_hi_dci0_req(nfapi_pnf_p7_config_t *pnf_p7, - nfapi_hi_dci0_request_t *req) { +int memcpy_hi_dci0_req (L1_rxtx_proc_t *proc, + nfapi_pnf_p7_config_t* pnf_p7, + nfapi_hi_dci0_request_t* req) { hi_dci0_req = (nfapi_hi_dci0_request_t *)malloc(sizeof(nfapi_hi_dci0_request_t)); + //if(req!=0){ + hi_dci0_req->sfn_sf = req->sfn_sf; hi_dci0_req->vendor_extension = req->vendor_extension; @@ -1074,7 +1079,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB, int frame, int subframe, L1_rxtx_proc_t *proc, - nfapi_dl_config_request_pdu_t *dl_config_pdu, + nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t codeword_index, uint8_t *sdu) { } diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.h b/openair2/PHY_INTERFACE/phy_stub_UE.h index 15496f8ba15572b205ef26fd059f77f5a082543d..09356fc9f81da4e01641598de5ea9e589fdee7d0 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.h +++ b/openair2/PHY_INTERFACE/phy_stub_UE.h @@ -118,16 +118,16 @@ void hi_dci0_req_UE_MAC(int sfn, // The following set of memcpy functions should be getting called as callback functions from // pnf_p7_subframe_ind. -int memcpy_dl_config_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_dl_config_request_t* req); +int memcpy_dl_config_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t* pnf_p7, nfapi_dl_config_request_t* req); -int memcpy_ul_config_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req); +int memcpy_ul_config_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req); int memcpy_tx_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_tx_request_t* req); -int memcpy_hi_dci0_req (nfapi_pnf_p7_config_t* pnf_p7, nfapi_hi_dci0_request_t* req); +int memcpy_hi_dci0_req (L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t* pnf_p7, nfapi_hi_dci0_request_t* req); void UE_config_stub_pnf(void); diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index dc9183a87d5a05a9820b4722d0b20bc43372b32d..9cca00ca2ec6905139ed7808531c9a4f56183e6f 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -8884,27 +8884,30 @@ void *rrc_enb_process_itti_msg(void *notUsed) { return NULL; } +// as there are race conditions, no rrc thread //----------------------------------------------------------------------------- void * -rrc_enb_task( +rrc_enb_process_msg( void *args_p ) //----------------------------------------------------------------------------- { - rrc_enb_init(); - itti_mark_task_ready(TASK_RRC_ENB); - LOG_I(RRC,"Entering main loop of RRC message task\n"); - while (1) { + //while (1) { + //(void) rrc_enb_process_itti_msg(NULL); + //} + + //while (1) { (void) rrc_enb_process_itti_msg(NULL); { //extern volatile int go_nr; void rrc_go_nr(void); //if (go_nr) rrc_go_nr(); } + //} +return NULL; } -} /*------------------------------------------------------------------------------*/ void diff --git a/openair2/RRC/NR/nr_rrc_extern.h b/openair2/RRC/NR/nr_rrc_extern.h index 8373a53584d96d81283071badef899dcfdf6ebc5..04e0392236bf5ada098861923a84bf3a2da13b4a 100644 --- a/openair2/RRC/NR/nr_rrc_extern.h +++ b/openair2/RRC/NR/nr_rrc_extern.h @@ -28,8 +28,8 @@ * \email: navid.nikaein@eurecom.fr, kroempa@gmail.com */ -#ifndef __OPENAIR_RRC_EXTERN_H__ -#define __OPENAIR_RRC_EXTERN_H__ +#ifndef __OPENAIR_NR_RRC_EXTERN_H__ +#define __OPENAIR_NR_RRC_EXTERN_H__ #include "nr_rrc_defs.h" #include "COMMON/mac_rrc_primitives.h" #include "LAYER2/MAC/mac.h" @@ -69,10 +69,12 @@ extern uint32_t timeToTrigger_ms[16]; extern float RSRP_meas_mapping[98]; extern float RSRQ_meas_mapping[35]; -extern UE_PF_PO_t UE_PF_PO[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; +extern UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; + extern pthread_mutex_t ue_pf_po_mutex; -extern uint16_t reestablish_rnti_map[NUMBER_OF_UE_MAX][2]; +extern uint16_t reestablish_rnti_map[MAX_MOBILES_PER_ENB][2]; +char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration); #endif diff --git a/openair2/RRC/NR/rrc_gNB_UE_context.h b/openair2/RRC/NR/rrc_gNB_UE_context.h index 4681cabb8f216b974536c7f01c4223208802d57d..762d9642897c8ceb3bd28ad25f436e2c7ae50edb 100644 --- a/openair2/RRC/NR/rrc_gNB_UE_context.h +++ b/openair2/RRC/NR/rrc_gNB_UE_context.h @@ -28,6 +28,7 @@ * \email: lionel.gauthier@eurecom.fr */ #ifndef __RRC_ENB_UE_CONTEXT_H__ +#define __RRC_ENB_UE_CONTEXT_H__ #include "collection/tree.h" #include "COMMON/platform_types.h" #include "nr_rrc_defs.h" @@ -58,7 +59,7 @@ int rrc_gNB_compare_ue_rnti_id( struct rrc_gNB_ue_context_s* c2_pP ); -RB_PROTOTYPE(rrc_ue_tree_s, rrc_gNB_ue_context_s, entries, rrc_gNB_compare_ue_rnti_id); +RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries, rrc_gNB_compare_ue_rnti_id); struct rrc_gNB_ue_context_s* rrc_gNB_allocate_new_UE_context( diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index cf48aef45941854e78c3d60bbf7fc2dc2e141d53..763c208dfe64b72d31e684e8b14b9e9d1bab96e5 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -41,9 +41,9 @@ void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,LTE_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList) { struct rrc_gNB_ue_context_s *ue_context_p = NULL; - OCTET_STRING_t *ueCapabilityRAT_Container_nr; - OCTET_STRING_t *ueCapabilityRAT_Container_MRDC; - int list_size; + OCTET_STRING_t *ueCapabilityRAT_Container_nr=NULL; + OCTET_STRING_t *ueCapabilityRAT_Container_MRDC=NULL; + int list_size=0; AssertFatal(UE_CapabilityRAT_ContainerList!=NULL,"UE_CapabilityRAT_ContainerList is null\n"); AssertFatal((list_size=UE_CapabilityRAT_ContainerList->list.count) >= 2, "UE_CapabilityRAT_ContainerList->list.size %d < 2\n",UE_CapabilityRAT_ContainerList->list.count); for (int i=0;i<list_size;i++) { diff --git a/openair2/UTIL/MEM/mem_block.c b/openair2/UTIL/MEM/mem_block.c deleted file mode 100644 index 0150ef00cdaf208120828c54840d80545b6908ca..0000000000000000000000000000000000000000 --- a/openair2/UTIL/MEM/mem_block.c +++ /dev/null @@ -1,668 +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 - */ - -/*************************************************************************** - mem_block.c - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - ***************************************************************************/ -#define MEM_BLOCK_C -//#include "rtos_header.h" -#include "mem_block.h" -#include "mem_pool.h" -#include "list.h" -#include "LAYER2/MAC/mac_extern.h" -#include "assertions.h" -/* all function calls are protected by a mutex - * to ensure that many threads calling them at - * the same time don't mess up. - * We might be more clever in the future, it's a - * bit overkill. - * Commenting this define removes the protection, - * so be careful with it. - */ -#define MEMBLOCK_BIG_LOCK - -#ifdef MEMBLOCK_BIG_LOCK -static pthread_mutex_t mtex = PTHREAD_MUTEX_INITIALIZER; -#endif - -//----------------------------------------------------------------------------- -//#define DEBUG_MEM_MNGT_FREE -//#define DEBUG_MEM_MNGT_ALLOC_SIZE -//#define DEBUG_MEM_MNGT_ALLOC -//----------------------------------------------------------------------------- -#if defined(DEBUG_MEM_MNGT_ALLOC) -uint32_t counters[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -#endif -//----------------------------------------------------------------------------- -/* - * initialize all ures - */ -extern mem_pool *memBlockVar; -void * -pool_buffer_init (void) -{ - //----------------------------------------------------------------------------- - - uint32_t index, mb_index, pool_index; - mem_pool *memory = (mem_pool *) &mem_block_var; - memBlockVar=malloc(sizeof(mem_pool)); - int pool_sizes[14] = { MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB1_NB_BLOCKS, - MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB3_NB_BLOCKS, - MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB5_NB_BLOCKS, - MEM_MNGT_MB6_NB_BLOCKS, MEM_MNGT_MB7_NB_BLOCKS, - MEM_MNGT_MB8_NB_BLOCKS, MEM_MNGT_MB9_NB_BLOCKS, - MEM_MNGT_MB10_NB_BLOCKS, MEM_MNGT_MB11_NB_BLOCKS, - MEM_MNGT_MB12_NB_BLOCKS, MEM_MNGT_MBCOPY_NB_BLOCKS - }; - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_lock(&mtex)) abort(); -#endif - - memset (memory, 0, sizeof (mem_pool)); - mb_index = 0; - - // LG_TEST - for (pool_index = 0; pool_index <= MEM_MNGT_POOL_ID_COPY; pool_index++) { - list_init (&memory->mem_lists[pool_index], "POOL"); - - for (index = 0; index < pool_sizes[pool_index]; index++) { - //memory->mem_blocks[mb_index + index].previous = NULL; -> done in memset 0 - //memory->mem_blocks[mb_index + index].next = NULL; -> done in memset 0 - switch (pool_index) { - case 0: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool0[index][0]); - break; - - case 1: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool1[index][0]); - break; - - case 2: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool2[index][0]); - break; - - case 3: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool3[index][0]); - break; - - case 4: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool4[index][0]); - break; - - case 5: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool5[index][0]); - break; - - case 6: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool6[index][0]); - break; - - case 7: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool7[index][0]); - break; - - case 8: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool8[index][0]); - break; - - case 9: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool9[index][0]); - break; - - case 10: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool10[index][0]); - break; - - case 11: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool11[index][0]); - break; - - case 12: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool12[index][0]); - break; - - default: - ; - memory->mem_blocks[mb_index + index].data = NULL; // pool copy - - } - - memory->mem_blocks[mb_index + index].pool_id = pool_index; - list_add_tail_eurecom (&memory->mem_blocks[mb_index + index], &memory->mem_lists[pool_index]); - } - - mb_index += pool_sizes[pool_index]; - } - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_unlock(&mtex)) abort(); -#endif - - return 0; -} - -//----------------------------------------------------------------------------- -void * -pool_buffer_clean (void *arg) -{ - //----------------------------------------------------------------------------- - return 0; -} -//----------------------------------------------------------------------------- -void -free_mem_block (mem_block_t * leP, const char* caller) -{ - //----------------------------------------------------------------------------- - - if (!(leP)) { - LOG_W (RLC,"[MEM_MNGT][FREE] WARNING FREE NULL MEM_BLOCK\n"); - return; - } - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_lock(&mtex)) abort(); -#endif - -#ifdef DEBUG_MEM_MNGT_FREE - LOG_D (RLC,"[MEM_MNGT][FREE] free_mem_block() %p pool: %d\n", leP, leP->pool_id); -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC - check_free_mem_block (leP); -#endif - - if (leP->pool_id <= MEM_MNGT_POOL_ID_COPY) { - list_add_tail_eurecom (leP, &mem_block_var.mem_lists[leP->pool_id]); -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[leP->pool_id] -= 1; - LGO_D (RLC,"[%s][MEM_MNGT][INFO] after pool[%2d] freed: counters = {%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d}\n", - caller, leP->pool_id, - counters[0],counters[1],counters[2],counters[3],counters[4], - counters[5],counters[6],counters[7],counters[8],counters[9], - counters[10],counters[11]); -#endif - leP = NULL; // this prevent from freeing the block twice - } else { - LOG_E (RLC,"[MEM_MNGT][FREE] ERROR free_mem_block() unknown pool_id : %d\n", leP->pool_id); - } - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_unlock(&mtex)) abort(); -#endif -} - -//----------------------------------------------------------------------------- -mem_block_t * -get_free_mem_block (uint32_t sizeP, const char* caller) -{ - //----------------------------------------------------------------------------- - mem_block_t *le = NULL; - int pool_selected; - int size; - - if (sizeP > MEM_MNGT_MB12_BLOCK_SIZE) { - LOG_E (RLC,"[MEM_MNGT][ERROR][FATAL] size requested %d out of bounds\n", sizeP); - display_mem_load (); - AssertFatal(1==0,"get_free_mem_block size requested out of bounds"); - return NULL; - } - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_lock(&mtex)) abort(); -#endif - - size = sizeP >> 6; - pool_selected = 0; - - while ((size)) { - pool_selected += 1; - size = size >> 1; - } - - // pool is selected according to the size requested, now get a block - // if no block is available pick one in an other pool - do { - if ((le = list_remove_head (&mem_block_var.mem_lists[pool_selected]))) { -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[pool_selected] += 1; - LOG_D (RLC,"[%s][MEM_MNGT][INFO] after pool[%2d] allocated: counters = {%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d}\n", - caller, - pool_selected, - counters[0],counters[1],counters[2],counters[3],counters[4], - counters[5],counters[6],counters[7],counters[8],counters[9], - counters[10],counters[11]); -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC_SIZE - LOG_D (RLC,"[MEM_MNGT][INFO] ALLOC MEM_BLOCK SIZE %d bytes pool %d (%p)\n", sizeP, pool_selected,le); -#endif - - AssertFatal(le->pool_id == pool_selected, "Unexpected pool ID!"); - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_unlock(&mtex)) abort(); -#endif - - return le; - } - -#ifdef DEBUG_MEM_MNGT_ALLOC - LOG_E (RLC,"[MEM_MNGT][ERROR][MINOR] memory pool %d is empty trying next pool alloc count = %d\n", pool_selected, counters[pool_selected]); - // display_mem_load (); - // check_mem_area ((void *)&mem_block_var); -#endif - } while (pool_selected++ < 12); - - LOG_E(PHY, "[MEM_MNGT][ERROR][FATAL] failed allocating MEM_BLOCK size %d byes (pool_selected=%d size=%d)\n", sizeP, pool_selected, size); -// display_mem_load(); -// AssertFatal(1==0,"get_free_mem_block failed"); - LOG_E(MAC,"[MEM_MNGT][ERROR][FATAL] get_free_mem_block failed!!!\n"); -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_unlock(&mtex)) abort(); -#endif - - return NULL; -}; - -//----------------------------------------------------------------------------- -mem_block_t * -get_free_copy_mem_block (void) -{ - //----------------------------------------------------------------------------- - mem_block_t *le; - -#ifdef MEMBLOCK_BIG_LOCK - AssertFatal(0, "This function is not handled properly but not used anywhere. FIXME?\n"); -#endif - - if ((le = list_remove_head (&mem_block_var.mem_lists[MEM_MNGT_POOL_ID_COPY]))) { -#ifdef DEBUG_MEM_MNGT_ALLOC_SIZE - LOG_D (RLC,"[MEM_MNGT][INFO] ALLOC COPY MEM BLOCK (%p)\n",le); -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[MEM_MNGT_POOL_ID_COPY] += 1; - LOG_D (RLC,"[MEM_MNGT][INFO] pool counters = {%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d}\n", - counters[0],counters[1],counters[2],counters[3],counters[4], - counters[5],counters[6],counters[7],counters[8],counters[9], - counters[10],counters[11]); -#endif - return le; - } else { - LOG_E (RLC,"[MEM_MNGT][ERROR] POOL COPY IS EMPTY\n"); - //#ifdef DEBUG_MEM_MNGT_ALLOC - check_mem_area (); - // break_point (); - //#endif - - AssertFatal(1==0,"mem pool is empty"); - return NULL; - } -} - -//----------------------------------------------------------------------------- -mem_block_t * -copy_mem_block (mem_block_t * leP, mem_block_t * destP) -{ - //----------------------------------------------------------------------------- - -#ifdef MEMBLOCK_BIG_LOCK - AssertFatal(0, "This function is not handled properly but not used anywhere. FIXME?\n"); -#endif - - if ((destP != NULL) && (leP != NULL) && (destP->pool_id == MEM_MNGT_POOL_ID_COPY)) { - destP->data = leP->data; - } else { - LOG_E (RLC,"[MEM_MNGT][COPY] copy_mem_block() pool dest src or dest is NULL\n"); - } - - return destP; -} - -//----------------------------------------------------------------------------- -void -display_mem_load (void) -{ - //----------------------------------------------------------------------------- -#ifdef MEMBLOCK_BIG_LOCK - /* this function does not need to be protected, do nothing */ -#endif - - mem_pool *memory = (mem_pool *) &mem_block_var; - - LOG_D (RLC,"POOL 0 (%d elements of %d Bytes): ", MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB0_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID0]); - LOG_D (RLC,"POOL 1 (%d elements of %d Bytes): ", MEM_MNGT_MB1_NB_BLOCKS, MEM_MNGT_MB1_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID1]); - LOG_D (RLC,"POOL 2 (%d elements of %d Bytes): ", MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB2_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID2]); - LOG_D (RLC,"POOL 3 (%d elements of %d Bytes): ", MEM_MNGT_MB3_NB_BLOCKS, MEM_MNGT_MB3_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID3]); - LOG_D (RLC,"POOL 4 (%d elements of %d Bytes): ", MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB4_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID4]); - LOG_D (RLC,"POOL 5 (%d elements of %d Bytes): ", MEM_MNGT_MB5_NB_BLOCKS, MEM_MNGT_MB5_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID5]); - LOG_D (RLC,"POOL 6 (%d elements of %d Bytes): ", MEM_MNGT_MB6_NB_BLOCKS, MEM_MNGT_MB6_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID6]); - LOG_D (RLC,"POOL 7 (%d elements of %d Bytes): ", MEM_MNGT_MB7_NB_BLOCKS, MEM_MNGT_MB7_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID7]); - LOG_D (RLC,"POOL 8 (%d elements of %d Bytes): ", MEM_MNGT_MB8_NB_BLOCKS, MEM_MNGT_MB8_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID8]); - LOG_D (RLC,"POOL 9 (%d elements of %d Bytes): ", MEM_MNGT_MB9_NB_BLOCKS, MEM_MNGT_MB9_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID9]); - LOG_D (RLC,"POOL 10 (%d elements of %d Bytes): ", MEM_MNGT_MB10_NB_BLOCKS, MEM_MNGT_MB10_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID10]); - LOG_D (RLC,"POOL 11 (%d elements of %d Bytes): ", MEM_MNGT_MB11_NB_BLOCKS, MEM_MNGT_MB11_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID11]); - LOG_D (RLC,"POOL 12 (%d elements of %d Bytes): ", MEM_MNGT_MB12_NB_BLOCKS, MEM_MNGT_MB12_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID12]); - LOG_D (RLC,"POOL C (%d elements): ", MEM_MNGT_MBCOPY_NB_BLOCKS); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID_COPY]); -} - -//----------------------------------------------------------------------------- -void -check_mem_area (void) -{ - //----------------------------------------------------------------------------- - int index, mb_index; - mem_pool *memory = (mem_pool *) &mem_block_var; - -#ifdef MEMBLOCK_BIG_LOCK - AssertFatal(0, "This function is not handled properly but not used anywhere. FIXME?\n"); -#endif - - for (index = 0; index < MEM_MNGT_MB0_NB_BLOCKS; index++) { - if ((memory->mem_blocks[index].data != (unsigned char*)&(memory->mem_pool0[index][0])) && (memory->mem_blocks[index].pool_id != MEM_MNGT_POOL_ID0)) { - LOG_D (RLC,"[MEM] ERROR POOL0 block index %d\n", index); - } - } - - mb_index = MEM_MNGT_MB0_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB1_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool1[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID1)) { - LOG_D (RLC,"[MEM] ERROR POOL1 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB1_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB2_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool2[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID2)) { - LOG_D (RLC,"[MEM] ERROR POOL2 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB2_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB3_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool3[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID3)) { - LOG_D (RLC,"[MEM] ERROR POOL3 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB3_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB4_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool4[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID4)) { - LOG_D (RLC,"[MEM] ERROR POOL4 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB4_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB5_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool5[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID5)) { - LOG_D (RLC,"[MEM] ERROR POOL5 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB5_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB6_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool6[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID6)) { - LOG_D (RLC,"[MEM] ERROR POOL6 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB6_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB7_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool7[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID7)) { - LOG_D (RLC,"[MEM] ERROR POOL7 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB7_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB8_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool8[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID8)) { - LOG_D (RLC,"[MEM] ERROR POOL8 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB8_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB9_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool9[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID9)) { - LOG_D (RLC,"[MEM] ERROR POOL9 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB9_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_MB10_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool10[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID10)) { - LOG_D (RLC,"[MEM] ERROR POOL10 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB10_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_MB11_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool11[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID11)) { - LOG_D (RLC,"[MEM] ERROR POOL11 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB11_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_MB12_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool12[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID12)) { - LOG_D (RLC,"[MEM] ERROR POOL12 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB12_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_NB_ELEMENTS; index++) { - if ((memory->mem_blocks[index].data != NULL) && (memory->mem_blocks[index].pool_id != MEM_MNGT_POOL_ID_COPY)) { - LOG_D (RLC,"[MEM] ERROR POOL COPY block index %d\n", index); - } - } -} - -//----------------------------------------------------------------------------- -void -check_free_mem_block (mem_block_t * leP) -{ - //----------------------------------------------------------------------------- - ptrdiff_t block_index; - -#ifdef MEMBLOCK_BIG_LOCK - /* this function does not SEEM TO need to be protected, do nothing (for the moment) */ -#endif - - if ((leP >= mem_block_var.mem_blocks) && (leP <= &mem_block_var.mem_blocks[MEM_MNGT_NB_ELEMENTS-1])) { - // the pointer is inside the memory region - block_index = leP - mem_block_var.mem_blocks; - // block_index is now: 0 <= block_index < MEM_MNGT_NB_ELEMENTS - - if (block_index < MEM_MNGT_MB0_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool0[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID0)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB0_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB1_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool1[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID1)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB1_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB2_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool2[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID2)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB2_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB3_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool3[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID3)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB3_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB4_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool4[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID4)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB4_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB5_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool5[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID5)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB5_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB6_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool6[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID6)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB6_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB7_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool7[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID7)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB7_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB8_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool8[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID8)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB8_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB9_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool9[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID9)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB9_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB10_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool10[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID10)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB10_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB11_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool11[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID11)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB11_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB12_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool12[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID12)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - } else { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - // the block is ok -} diff --git a/openair2/UTIL/MEM/mem_block.h b/openair2/UTIL/MEM/mem_block.h index f40566f6ed2d8051e5cfb8bae9220f1f531e2bec..0d9943064070caab5afb1be339cd08d7bffeeb35 100644 --- a/openair2/UTIL/MEM/mem_block.h +++ b/openair2/UTIL/MEM/mem_block.h @@ -57,91 +57,8 @@ mem_block_t *get_free_copy_mem_block (void); mem_block_t *get_free_copy_mem_block_up (void); mem_block_t *copy_mem_block (mem_block_t * leP, mem_block_t * destP); void display_mem_load (void); - -void check_mem_area (void); -void check_free_mem_block (mem_block_t * leP); -# define MEM_SCALE MAX_MOBILES_PER_ENB -// definition of the size of the allocated memory area -# define MEM_MNGT_MB0_BLOCK_SIZE 64 -// 64 -# define MEM_MNGT_MB0_NB_BLOCKS 4096 * MEM_SCALE -# define MEM_MNGT_POOL_ID0 0 - -# define MEM_MNGT_MB1_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*2 -// 128 -# define MEM_MNGT_MB1_NB_BLOCKS 4096 * MEM_SCALE -# define MEM_MNGT_POOL_ID1 1 - -# define MEM_MNGT_MB2_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*4 -// 256 -# define MEM_MNGT_MB2_NB_BLOCKS 2048 * MEM_SCALE -# define MEM_MNGT_POOL_ID2 2 - -# define MEM_MNGT_MB3_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*8 -// 512 -# define MEM_MNGT_MB3_NB_BLOCKS 2048 * MEM_SCALE -# define MEM_MNGT_POOL_ID3 3 - -# define MEM_MNGT_MB4_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*16 -// 1024 -# define MEM_MNGT_MB4_NB_BLOCKS 1024 * MEM_SCALE -# define MEM_MNGT_POOL_ID4 4 - -# define MEM_MNGT_MB5_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*32 -// 2048 -# define MEM_MNGT_MB5_NB_BLOCKS 1024 * MEM_SCALE // LG WAS 1024 -# define MEM_MNGT_POOL_ID5 5 - -# define MEM_MNGT_MB6_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*64 -// 4096 -# define MEM_MNGT_MB6_NB_BLOCKS 1024 * MEM_SCALE // LG WAS 256 -# define MEM_MNGT_POOL_ID6 6 - -# define MEM_MNGT_MB7_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*128 -// 8192 -# define MEM_MNGT_MB7_NB_BLOCKS 64* MEM_SCALE // LG WAS 32 -# define MEM_MNGT_POOL_ID7 7 - -# define MEM_MNGT_MB8_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*256 - -#ifdef JUMBO_FRAMES -# define MEM_MNGT_MB8_NB_BLOCKS 256 * MEM_SCALE -#else -# define MEM_MNGT_MB8_NB_BLOCKS 16 * MEM_SCALE -// 16384 -#endif -# define MEM_MNGT_POOL_ID8 8 - -# define MEM_MNGT_MB9_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*512 -// 32768 -# define MEM_MNGT_MB9_NB_BLOCKS 8 * MEM_SCALE -# define MEM_MNGT_POOL_ID9 9 - -# define MEM_MNGT_MB10_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*1024 -// 65536 -# define MEM_MNGT_MB10_NB_BLOCKS 0 * MEM_SCALE -# define MEM_MNGT_POOL_ID10 10 - -# define MEM_MNGT_MB11_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*2048 -// 131072 -# define MEM_MNGT_MB11_NB_BLOCKS 0 * MEM_SCALE -# define MEM_MNGT_POOL_ID11 11 - -# define MEM_MNGT_MB12_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*4096 -// 262144 -# define MEM_MNGT_MB12_NB_BLOCKS 32 * MEM_SCALE -//# define MEM_MNGT_MB12_NB_BLOCKS 4096 * MEM_SCALE - -# define MEM_MNGT_POOL_ID12 12 - - -# define MEM_MNGT_MBCOPY_NB_BLOCKS 1024 -# define MEM_MNGT_NB_ELEMENTS MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + MEM_MNGT_MB6_NB_BLOCKS + MEM_MNGT_MB7_NB_BLOCKS + MEM_MNGT_MB8_NB_BLOCKS + MEM_MNGT_MB9_NB_BLOCKS + MEM_MNGT_MB10_NB_BLOCKS + MEM_MNGT_MB11_NB_BLOCKS + MEM_MNGT_MB12_NB_BLOCKS + MEM_MNGT_MBCOPY_NB_BLOCKS -# define MEM_MNGT_POOL_ID_COPY 13 - #define LIST_NAME_MAX_CHAR 32 - typedef struct { struct mem_block_t *head; struct mem_block_t *tail; @@ -156,31 +73,6 @@ typedef struct { char name[LIST_NAME_MAX_CHAR]; } list_t; - - -typedef struct { - //----------------------------------------------------------- - // basic memory management - //----------------------------------------------------------- - char mem_pool0[MEM_MNGT_MB0_NB_BLOCKS][MEM_MNGT_MB0_BLOCK_SIZE]; - char mem_pool1[MEM_MNGT_MB1_NB_BLOCKS][MEM_MNGT_MB1_BLOCK_SIZE]; - char mem_pool2[MEM_MNGT_MB2_NB_BLOCKS][MEM_MNGT_MB2_BLOCK_SIZE]; - char mem_pool3[MEM_MNGT_MB3_NB_BLOCKS][MEM_MNGT_MB3_BLOCK_SIZE]; - char mem_pool4[MEM_MNGT_MB4_NB_BLOCKS][MEM_MNGT_MB4_BLOCK_SIZE]; - char mem_pool5[MEM_MNGT_MB5_NB_BLOCKS][MEM_MNGT_MB5_BLOCK_SIZE]; - char mem_pool6[MEM_MNGT_MB6_NB_BLOCKS][MEM_MNGT_MB6_BLOCK_SIZE]; - char mem_pool7[MEM_MNGT_MB7_NB_BLOCKS][MEM_MNGT_MB7_BLOCK_SIZE]; - char mem_pool8[MEM_MNGT_MB8_NB_BLOCKS][MEM_MNGT_MB8_BLOCK_SIZE]; - char mem_pool9[MEM_MNGT_MB9_NB_BLOCKS][MEM_MNGT_MB9_BLOCK_SIZE]; - char mem_pool10[MEM_MNGT_MB10_NB_BLOCKS][MEM_MNGT_MB10_BLOCK_SIZE]; - char mem_pool11[MEM_MNGT_MB11_NB_BLOCKS][MEM_MNGT_MB11_BLOCK_SIZE]; - char mem_pool12[MEM_MNGT_MB12_NB_BLOCKS][MEM_MNGT_MB12_BLOCK_SIZE]; - mem_block_t mem_blocks[MEM_MNGT_NB_ELEMENTS]; - list_t mem_lists[14]; - -} mem_pool; - - #ifdef __cplusplus } #endif diff --git a/openair2/UTIL/MEM/mem_mngt.c b/openair2/UTIL/MEM/mem_mngt.c deleted file mode 100644 index 57c90ea4f909268f0c6aadcbacb7305e51f5bf4f..0000000000000000000000000000000000000000 --- a/openair2/UTIL/MEM/mem_mngt.c +++ /dev/null @@ -1,489 +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 - */ - -/*************************************************************************** - mem_mngt.c - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - ***************************************************************************/ -#define MEM_MNGT_C -#include "rtos_header.h" -#include "platform.h" -#include "protocol_vars_extern.h" -#include "print.h" - -#include "mem_block.h" -#include "mem_pool.h" -#include "lists_proto_extern.h" -#include "umts_sched.h" -//----------------------------------------------------------------------------- -#define DEBUG_MEM_MNGT_FREE -#define DEBUG_MEM_MNGT_ALLOC_SIZE -#define DEBUG_MEM_MNGT_ALLOC -#ifdef DEBUG_MEM_MNGT_ADDR -# define PRINT_MEM_MNGT_ADDR msg -#else -# define PRINT_MEM_MNGT_ADDR -// -#endif -//----------------------------------------------------------------------------- -uint32_t counters[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -//----------------------------------------------------------------------------- -/* - * initialize all ures - */ -void * -pool_buffer_init (void *arg) -{ - //----------------------------------------------------------------------------- - - uint32_t index, mb_index, pool_index; - mem_pool *memory = (mem_pool *) arg; - int pool_sizes[11] = { MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB1_NB_BLOCKS, - MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB3_NB_BLOCKS, - MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB5_NB_BLOCKS, - MEM_MNGT_MB6_NB_BLOCKS, MEM_MNGT_MB7_NB_BLOCKS, - MEM_MNGT_MB8_NB_BLOCKS, MEM_MNGT_MB9_NB_BLOCKS, - MEM_MNGT_MBCOPY_NB_BLOCKS - }; - - memset (memory, 0, sizeof (mem_pool)); - mb_index = 0; - - // LG_TEST - for (pool_index = 0; pool_index <= MEM_MNGT_POOL_ID_COPY; pool_index++) { - init_list (&memory->mem_lists[pool_index], "POOL"); - - for (index = 0; index < pool_sizes[pool_index]; index++) { - //memory->mem_blocks[mb_index + index].previous = NULL; -> done in memset 0 - //memory->mem_blocks[mb_index + index].next = NULL; -> done in memset 0 - switch (pool_index) { - case 0: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool0[index][0]); - break; - - case 1: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool1[index][0]); - break; - - case 2: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool2[index][0]); - break; - - case 3: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool3[index][0]); - break; - - case 4: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool4[index][0]); - break; - - case 5: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool5[index][0]); - break; - - case 6: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool6[index][0]); - break; - - case 7: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool7[index][0]); - break; - - case 8: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool8[index][0]); - break; - - case 9: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool9[index][0]); - break; - - default: - ; - memory->mem_blocks[mb_index + index].data = NULL; // pool copy - - } - - memory->mem_blocks[mb_index + index].pool_id = pool_index; - add_tail (&memory->mem_blocks[mb_index + index], &memory->mem_lists[pool_index]); - } - - mb_index += pool_sizes[pool_index]; - } - - return 0; -} - -//----------------------------------------------------------------------------- -void * -pool_buffer_clean (void *arg) -{ - //----------------------------------------------------------------------------- -#ifndef NO_THREAD_SAFE - mem_pool *memory = (mem_pool *) arg; - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID0].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID1].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID2].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID3].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID4].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID5].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID6].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID7].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID8].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID9].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID_COPY].mutex); -#endif - return 0; -} -//----------------------------------------------------------------------------- -void -free_mem_block (mem_block_t * leP, __func__) -{ - //----------------------------------------------------------------------------- - - if (!(leP)) { - msg ("[MEM_MNGT][FREE] WARNING FREE NULL MEM_BLOCK\n"); - return; - } - -#ifdef DEBUG_MEM_MNGT_FREE - msg ("[MEM_MNGT][FREE] free_mem_block() %p pool: %d\n", leP, leP->pool_id, __func__); -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC - check_free_mem_block (leP, __func__); -#endif - - if (leP->pool_id <= MEM_MNGT_POOL_ID_COPY) { - add_tail (leP, &mem->mem_lists[leP->pool_id]); -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[leP->pool_id] -= 1; -#endif - leP = NULL; // this prevent from freeing the block twice - } else { - msg ("[MEM_MNGT][FREE] ERROR free_mem_block() unknown pool_id : %d\n", leP->pool_id, __func__); - } -} - - -//----------------------------------------------------------------------------- -mem_block_t * -get_free_mem_block (uint16_t sizeP, __func__) -{ - //----------------------------------------------------------------------------- - mem_block_t *le = NULL; - int pool_selected; - int size; - - if (sizeP > MEM_MNGT_MB9_BLOCK_SIZE) { - msg ("[MEM_MNGT][ERROR][FATAL] size requested %d out of bounds %d\n",sizeP,MEM_MNGT_MB9_BLOCK_SIZE); - wcdma_handle_error (WCDMA_ERROR_OUT_OF_MEM_BLOCK); - return NULL; - } - - size = sizeP >> 6; - pool_selected = 0; - - while ((size)) { - pool_selected += 1; - size = size >> 1; - } - - // pool is selected according to the size requested, now get a block - // if no block is available pick one in an other pool - do { - if ((le = remove_head (&mem->mem_lists[pool_selected]))) { -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[pool_selected] += 1; -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC_SIZE - msg ("[MEM_MNGT][INFO] ALLOC MEM_BLOCK SIZE %d bytes pool %d\n", sizeP, pool_selected); -#endif - return le; - } - -#ifdef DEBUG_MEM_MNGT_ALLOC - msg ("[MEM_MNGT][ERROR][MINOR] memory pool %d is empty trying next pool alloc count = %d\n", pool_selected, counters[pool_selected]); - display_mem_load (); - check_mem_area (mem); -#endif - } while (pool_selected++ < 9); - - msg ("[MEM_MNGT][ERROR][FATAL] size %d requested out of bounds or memory pools empty\n", sizeP); - wcdma_handle_error (WCDMA_ERROR_OUT_OF_MEM_BLOCK); - return NULL; -}; - -//----------------------------------------------------------------------------- -mem_block_t * -get_free_copy_mem_block (void) -{ - //----------------------------------------------------------------------------- - mem_block_t *le; - - if ((le = remove_head (&mem->mem_lists[MEM_MNGT_POOL_ID_COPY]))) { - return le; - } else { - msg ("[MEM_MNGT][ERROR] POOL COPY IS EMPTY\n"); - display_mem_load (); -#ifdef DEBUG_MEM_MNGT_ALLOC - check_mem_area (mem); - break_point (); -#endif - wcdma_handle_error (WCDMA_ERROR_OUT_OF_MEM_BLOCK); - - return NULL; - } -} - -//----------------------------------------------------------------------------- -mem_block_t * -copy_mem_block (mem_block_t * leP, mem_block_t * destP) -{ - //----------------------------------------------------------------------------- - - if ((destP != NULL) && (leP != NULL) && (destP->pool_id == MEM_MNGT_POOL_ID_COPY)) { - destP->data = leP->data; - } else { - msg ("[MEM_MNGT][COPY] copy_mem_block() pool dest src or dest is NULL\n"); - } - - return destP; -} - -//----------------------------------------------------------------------------- -void -display_mem_load (void) -{ - //----------------------------------------------------------------------------- - - msg ("POOL 0 (%d elements of %d Bytes): \n", MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB0_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID0]); - msg ("POOL 1 (%d elements of %d Bytes): \n", MEM_MNGT_MB1_NB_BLOCKS, MEM_MNGT_MB1_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID1]); - msg ("POOL 2 (%d elements of %d Bytes): \n", MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB2_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID2]); - msg ("POOL 3 (%d elements of %d Bytes): \n", MEM_MNGT_MB3_NB_BLOCKS, MEM_MNGT_MB3_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID3]); - msg ("POOL 4 (%d elements of %d Bytes): \n", MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB4_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID4]); - msg ("POOL 5 (%d elements of %d Bytes): \n", MEM_MNGT_MB5_NB_BLOCKS, MEM_MNGT_MB5_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID5]); - msg ("POOL 6 (%d elements of %d Bytes): \n", MEM_MNGT_MB6_NB_BLOCKS, MEM_MNGT_MB6_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID6]); - msg ("POOL 7 (%d elements of %d Bytes): \n", MEM_MNGT_MB7_NB_BLOCKS, MEM_MNGT_MB7_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID7]); - msg ("POOL 8 (%d elements of %d Bytes): \n", MEM_MNGT_MB8_NB_BLOCKS, MEM_MNGT_MB8_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID8]); - msg ("POOL 9 (%d elements of %d Bytes): \n", MEM_MNGT_MB9_NB_BLOCKS, MEM_MNGT_MB9_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID9]); - msg ("POOL C (%d elements): \n", MEM_MNGT_MBCOPY_NB_BLOCKS); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID_COPY]); -} - -//----------------------------------------------------------------------------- -void -check_mem_area (void *arg) -{ - //----------------------------------------------------------------------------- - int index, mb_index; - mem_pool *memory = (mem_pool *) arg; - - for (index = 0; index < MEM_MNGT_MB0_NB_BLOCKS; index++) { - if ((memory->mem_blocks[index].data != &(memory->mem_pool0[index][0])) && (memory->mem_blocks[index].pool_id != MEM_MNGT_POOL_ID0)) { - msg ("[MEM] ERROR POOL0 block index %d\n", index); - break_point (); - } - } - - mb_index = MEM_MNGT_MB0_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB1_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool1[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID1)) { - msg ("[MEM] ERROR POOL1 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB1_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB2_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool2[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID2)) { - msg ("[MEM] ERROR POOL2 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB2_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB3_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool3[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID3)) { - msg ("[MEM] ERROR POOL3 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB3_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB4_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool4[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID4)) { - msg ("[MEM] ERROR POOL4 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB4_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB5_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool5[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID5)) { - msg ("[MEM] ERROR POOL5 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB5_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB6_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool6[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID6)) { - msg ("[MEM] ERROR POOL6 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB6_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB7_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool7[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID7)) { - msg ("[MEM] ERROR POOL7 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB7_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB8_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool8[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID8)) { - msg ("[MEM] ERROR POOL8 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB8_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB9_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool9[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID9)) { - msg ("[MEM] ERROR POOL9 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB9_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_NB_ELEMENTS; index++) { - if ((memory->mem_blocks[index].data != NULL) && (memory->mem_blocks[index].pool_id != MEM_MNGT_POOL_ID_COPY)) { - msg ("[MEM] ERROR POOL COPY block index %d\n", index); - break_point (); - } - } -} - -//----------------------------------------------------------------------------- -void -check_free_mem_block (mem_block_t * leP, __func__) -{ - //----------------------------------------------------------------------------- - int block_index; - - if ((leP >= &mem->mem_blocks[0]) && (leP <= &mem->mem_blocks[MEM_MNGT_NB_ELEMENTS])) { - block_index = ((uint32_t) leP - (uint32_t) (&mem->mem_blocks[0])) / sizeof (mem_block_t); - - if (block_index < MEM_MNGT_MB0_NB_BLOCKS) { - if (((uint32_t) (leP->data) != (uint32_t) (&(mem->mem_pool0[block_index][0]))) && (leP->pool_id != MEM_MNGT_POOL_ID0)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < (MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS)) { - if ((leP->data != &(mem->mem_pool1[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID1)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool2[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID2)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool3[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID3)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool4[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID4)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + - MEM_MNGT_MB5_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool5[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID5)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < - MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + - MEM_MNGT_MB6_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool6[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID6)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < - MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + - MEM_MNGT_MB6_NB_BLOCKS + - MEM_MNGT_MB7_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool7[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID7)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < - MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + - MEM_MNGT_MB6_NB_BLOCKS + - MEM_MNGT_MB7_NB_BLOCKS + MEM_MNGT_MB8_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool8[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID8)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < - MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + - MEM_MNGT_MB6_NB_BLOCKS + - MEM_MNGT_MB7_NB_BLOCKS + MEM_MNGT_MB8_NB_BLOCKS + MEM_MNGT_MB9_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool9[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID9)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } - - } else { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } -} - -//----------------------------------------------------------------------------- -void -break_point (void) -{ - //----------------------------------------------------------------------------- - int break_var; - - msg ("[BREAK_POINT]\n"); - break_var = 1; -} diff --git a/openair2/UTIL/MEM/mem_mngt_proto_extern.h b/openair2/UTIL/MEM/mem_mngt_proto_extern.h deleted file mode 100644 index 4690bba42e5b91f4721d727b38d41da928e0c55a..0000000000000000000000000000000000000000 --- a/openair2/UTIL/MEM/mem_mngt_proto_extern.h +++ /dev/null @@ -1,21 +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 - */ - diff --git a/openair2/UTIL/MEM/mem_pool.h b/openair2/UTIL/MEM/mem_pool.h deleted file mode 100644 index cc0face78c673afa37a2b78367fe4d2193956732..0000000000000000000000000000000000000000 --- a/openair2/UTIL/MEM/mem_pool.h +++ /dev/null @@ -1,38 +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 - */ - -/*************************************************************************** - mem_pool.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - ***************************************************************************/ -#ifndef __MEM_POOL_H__ -# define __MEM_POOL_H__ - -# include "list.h" -# include "mem_block.h" - - -#endif diff --git a/openair2/UTIL/OPT/probe.c b/openair2/UTIL/OPT/probe.c index f8cd0ef64c52328a96344c89119ad84fb7fffa19..8c6a74e0429837ffb8cecdddb546fc0f5711e916 100644 --- a/openair2/UTIL/OPT/probe.c +++ b/openair2/UTIL/OPT/probe.c @@ -99,8 +99,8 @@ int opt_enabled=0; //static unsigned char g_PDUBuffer[1600]; //static unsigned int g_PDUOffset; -static char *in_ip; -static char *in_path; +static char in_ip[128]={0}; +static char in_path[128]={0}; FILE *file_fd = NULL; pcap_hdr_t file_header = { 0xa1b2c3d4, /* magic number */ @@ -447,9 +447,11 @@ int init_opt(void) char *in_type=NULL; paramdef_t opt_params[] = OPT_PARAMS_DESC ; checkedparam_t opt_checkParams[] = OPTPARAMS_CHECK_DESC; - uint16_t in_port; - config_set_checkfunctions(opt_params, opt_checkParams, sizeof(opt_params)/sizeof(paramdef_t)); - config_get(opt_params, sizeof(opt_params)/sizeof(paramdef_t), OPT_CONFIGPREFIX); + uint16_t in_port=0; + config_set_checkfunctions(opt_params, opt_checkParams, + sizeof(opt_params)/sizeof(paramdef_t)); + config_get( opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX); + subframesSinceCaptureStart = 0; int tmptype = config_get_processedint( &(opt_params[OPTTYPE_IDX])); diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index 95e0910fcde6f2d213ea99ca6ae15c232ced7b63..afaae1756d49b443733bdb02d95f0f1b9ee85d0f 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -1772,7 +1772,7 @@ int x2ap_gNB_handle_ENDC_sGNB_addition_request (instance_t instance, X2AP_ProtocolIE_ID_id_MeNBtoSgNBContainer, true); X2AP_MeNBtoSgNBContainer_t *container = &ie->value.choice.MeNBtoSgNBContainer; - + //X2AP_MeNBtoSgNBContainer_t *container = &ie->value.choice.MeNBtoSgNBContainer; if (container->size > 8192 ) // TODO: this is the size of rrc_buffer in struct x2ap_handover_req_s { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); } diff --git a/openair3/NAS/COMMON/UTIL/socket.c b/openair3/NAS/COMMON/UTIL/socket.c index 25876c3e6ff2e42ec17f7713780cd486f3d679eb..53a6ec8823d063bb5ec1d7d87154015af2981bd6 100644 --- a/openair3/NAS/COMMON/UTIL/socket.c +++ b/openair3/NAS/COMMON/UTIL/socket.c @@ -107,7 +107,7 @@ void* socket_udp_open(int type, const char* host, const char* port) { struct addrinfo socket_info; /* endpoint information */ struct addrinfo *socket_addr, *sp; /* endpoint address */ - int sfd; /* socket file descriptor */ + int sfd=-1; /* socket file descriptor */ /* * Parameters sanity check diff --git a/openair3/NAS/TOOLS/conf_network.c b/openair3/NAS/TOOLS/conf_network.c index 96e2183327ad1c8d35215f898566582efe2ee994..7e71c9b4ee79cafbd68404350195e3c4dec18975 100644 --- a/openair3/NAS/TOOLS/conf_network.c +++ b/openair3/NAS/TOOLS/conf_network.c @@ -80,7 +80,7 @@ bool parse_plmn_param(config_setting_t *plmn_setting, plmn_conf_param_t *conf) { bool parse_plmns(config_setting_t *all_plmn_setting, networks_t *networks) { config_setting_t *plmn_setting = NULL; - char plmn[10]; + char plmn[100]; int size = 0; size = config_setting_length(all_plmn_setting); diff --git a/openair3/NAS/TOOLS/conf_parser.c b/openair3/NAS/TOOLS/conf_parser.c index d46142c4614970827c3a050323297480670f848e..3ea1e29554f6f55cd5a7a002cac4263ccb98a319 100644 --- a/openair3/NAS/TOOLS/conf_parser.c +++ b/openair3/NAS/TOOLS/conf_parser.c @@ -13,7 +13,7 @@ bool parse_config_file(const char *output_dir, const char *conf_filename, int ou config_setting_t *root_setting = NULL; config_setting_t *ue_setting = NULL; config_setting_t *all_plmn_setting = NULL; - char user[10]; + char user[100]; config_t cfg; networks_t networks;; diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md index 014f5f7505c6318ac082496b68e92e3d987d9bd3..421cc662bb2a6fe1a462317f578bd15a82dbc430 100644 --- a/targets/ARCH/rfsimulator/README.md +++ b/targets/ARCH/rfsimulator/README.md @@ -3,6 +3,12 @@ This is an RF simulator that allows to test OAI without an RF board. It replaces As much as possible, it works like an RF board, but not in real-time: It can run faster than real-time if there is enough CPU, or slower (it is CPU-bound instead of real-time RF sampling-bound). +It can be run either in: + +- "noS1" mode: the generated IP traffic is sent and received between gNB and UE IP tunnel interfaces ("oaitun") by applications like ping and iperf +- "phy-test" mode: random UL and DL traffic is generated at every scheduling opportunity + + # build ## From [build_oai](../../../doc/BUILD.md) script diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 54dfd3b888ab347bdaf7cacc6ac591e121675510..a1b517a1ed23bd72073091f704790157e9ae4563 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -33,7 +33,7 @@ #include <openair1/SIMULATION/TOOLS/sim.h> #define PORT 4043 //default TCP port for this simulator -#define CirSize 3072000 // 100ms is enough +#define CirSize 307200 // 100ms is enough #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) @@ -346,7 +346,8 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp if ( t->lastWroteTS != 0 && abs((double)t->lastWroteTS-timestamp) > (double)CirSize) LOG_E(HW,"Discontinuous TX gap too large Tx:%lu, %lu\n", t->lastWroteTS, timestamp); - AssertFatal(t->lastWroteTS <= timestamp+1, " Not supported to send Tx out of order (same in USRP) %lu, %lu\n", + if (t->lastWroteTS > timestamp+nsamps) + LOG_E(HW,"Not supported to send Tx out of order (same in USRP) %lu, %lu\n", t->lastWroteTS, timestamp); t->lastWroteTS=timestamp+nsamps; @@ -420,7 +421,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi if ( sz < 0 ) { if ( errno != EAGAIN ) { LOG_E(HW,"socket failed %s\n", strerror(errno)); - abort(); + //abort(); } } else if ( sz == 0 ) continue; @@ -439,11 +440,15 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi b->headerMode=false; if ( t->nextTimestamp == 0 ) { // First block in UE, resync with the eNB current TS - t->nextTimestamp = b->th.timestamp > nsamps_for_initial ? b->th.timestamp - nsamps_for_initial : 0; - b->lastReceivedTS = b->th.timestamp > nsamps_for_initial ? b->th.timestamp : nsamps_for_initial; - LOG_W(HW,"UE got first timestamp: starting at %lu\n", t->nextTimestamp); - b->trashingPacket=true; - } else if ( b->lastReceivedTS < b->th.timestamp) { + t->nextTimestamp=b->th.timestamp> nsamps_for_initial ? + b->th.timestamp - nsamps_for_initial : + 0; + b->lastReceivedTS=b->th.timestamp> nsamps_for_initial ? + b->th.timestamp : + nsamps_for_initial; + LOG_W(HW,"UE got first timestamp: starting at %lu\n", t->nextTimestamp); + b->trashingPacket=true; + } else if ( b->lastReceivedTS < b->th.timestamp) { int nbAnt= b->th.nbAnt; for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ ) { @@ -463,8 +468,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi } else if ( b->lastReceivedTS == b->th.timestamp ) { // normal case } else { - abort(); - AssertFatal(false, "received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); + LOG_E(HW, "received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); + b->trashingPacket=true; } pthread_mutex_lock(&Sockmutex); diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c index cbbd30b62ca5ecc07287fec616e84c82b8f79eb2..10691d2db8c39363bba45368a0a93eed6904aa8c 100644 --- a/targets/COMMON/create_tasks.c +++ b/targets/COMMON/create_tasks.c @@ -41,6 +41,7 @@ # include "f1ap_du_task.h" # include "enb_app.h" # include "openair2/LAYER2/MAC/mac_proto.h" +#include <executables/split_headers.h> extern RAN_CONTEXT_t RC; @@ -55,16 +56,16 @@ int create_tasks(uint32_t enb_nb) { rc = itti_create_task (TASK_ENB_APP, eNB_app_task, NULL); AssertFatal(rc >= 0, "Create task for eNB APP failed\n"); - LOG_I(RRC,"Creating RRC eNB Task\n"); - rc = itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL); - AssertFatal(rc >= 0, "Create task for RRC eNB failed\n"); + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); - if (EPC_MODE_ENABLED) { + if (EPC_MODE_ENABLED && ! ( split73==SPLIT73_DU ) ) { rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for SCTP failed\n"); } - if (EPC_MODE_ENABLED && !NODE_IS_DU(type)) { + if (EPC_MODE_ENABLED && !NODE_IS_DU(type) && ! ( split73==SPLIT73_DU ) ) { rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for S1AP failed\n"); if (!(get_softmodem_params()->emulate_rf)){ diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 5ea4ec9695ef49d68af729b25579affdda009331..cb04480d3321c1080299ecd7aaaaa4069ced9151 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -261,7 +261,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB, eNB->UL_INFO.subframe = proc->subframe_rx; eNB->UL_INFO.module_id = eNB->Mod_id; eNB->UL_INFO.CC_id = eNB->CC_id; - eNB->if_inst->UL_indication(&eNB->UL_INFO); + eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); AssertFatal((ret= pthread_mutex_unlock(&eNB->UL_INFO_mutex))==0,"error unlocking UL_INFO_mutex, return %d\n",ret); /* this conflict resolution may be totally wrong, to be tested */ /* CONFLICT RESOLUTION: BEGIN */ diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 42221064b88f275e8ac4ca7f615a3beaf806688a..f5db3d3c5a1881bc39ec5a5e08ebce5c097d9e3b 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -80,7 +80,7 @@ unsigned short config_frames[4] = {2,9,11,13}; //#include "PHY/TOOLS/time_meas.h" #ifndef OPENAIR2 -#include "UTIL/OTG/otg_vars.h" + #include "UTIL/OTG/otg_vars.h" #endif @@ -93,6 +93,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "lte-softmodem.h" #include "NB_IoT_interface.h" +#include <executables/split_headers.h> pthread_cond_t nfapi_sync_cond; @@ -152,6 +153,13 @@ int otg_enabled; uint64_t num_missed_slots=0; // counter for the number of missed slots +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} extern void reset_opp_meas(void); extern void print_opp_meas(void); @@ -170,7 +178,7 @@ eth_params_t *eth_params; double cpuf; int oaisim_flag=0; -//threads_t threads= {-1,-1,-1,-1,-1,-1,-1,-1}; + /* forward declarations */ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); @@ -438,12 +446,9 @@ int restart_L1L2(module_id_t enb_id) { init_UE_info(&RC.mac[enb_id]->UE_info); LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); - if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { - LOG_E(RRC, "Create task for RRC eNB failed\n"); - return -1; - } else { - LOG_I(RRC, "Re-created task for RRC eNB successfully\n"); - } + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); /* pass a reconfiguration request which will configure everything down to * RC.eNB[i][j]->frame_parms, too */ @@ -539,7 +544,7 @@ int main ( int argc, char **argv ) cpuf=get_cpu_freq_GHz(); printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED); itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); - + // allows to forward in wireshark L2 protocol for decoding // initialize mscgen log after ITTI if (get_softmodem_params()->start_msc) { load_module_shlib("msc",NULL,0,&msc_interface); @@ -547,8 +552,6 @@ int main ( int argc, char **argv ) MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); init_opt(); - // to make a graceful exit when ctrl-c is pressed - set_softmodem_sighandler(); check_clock(); #ifndef PACKAGE_VERSION # define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" @@ -579,11 +582,11 @@ int main ( int argc, char **argv ) for (i = 0; i < RC.nb_inst; i++) { flexran_agent_start(i); } - + /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks * for monolithic/F1 modes */ - init_pdcp(); - + init_pdcp(); + if (create_tasks(1) < 0) { printf("cannot create ITTI tasks\n"); exit(-1); @@ -607,7 +610,7 @@ int main ( int argc, char **argv ) ctxt.subframe = 0; pdcp_run(&ctxt); } - + /* start threads if only L1 or not a CU */ if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) { // init UE_PF_PO and mutex lock @@ -618,31 +621,44 @@ int main ( int argc, char **argv ) pthread_mutex_init(&sync_mutex, NULL); rt_sleep_ns(10*100000000ULL); - + if (NFAPI_MODE!=NFAPI_MONOLITHIC) { LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n"); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); } - + if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF #if defined(PRE_SCD_THREAD) init_ru_vnf(); // ru pointer is necessary for pre_scd. #endif wait_nfapi_init("main?"); } - + LOG_I(ENB_APP,"START MAIN THREADS\n"); // start the main threads number_of_cards = 1; printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst); - + if (RC.nb_L1_inst > 0) { printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync); init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync); - // for (inst=0;inst<RC.nb_L1_inst;inst++) - // for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0); } + for (int x=0; x < RC.nb_L1_inst; x++) + for (int CC_id=0; CC_id<RC.nb_L1_CC[x]; CC_id++) { + L1_rxtx_proc_t *L1proc= &RC.eNB[x][CC_id]->proc.L1_proc; + L1proc->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); + L1proc->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) + initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true); + else + initTpool("n", L1proc->threadPool, true); + initNotifiedFIFO(L1proc->respEncode); + initNotifiedFIFO(L1proc->respDecode); + } + + } printf("wait_eNBs()\n"); @@ -660,23 +676,23 @@ int main ( int argc, char **argv ) RC.ru[ru_id]->rf_map.card=0; RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); } - + config_sync_var=0; - + if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF wait_nfapi_init("main?"); } - + printf("wait RUs\n"); - // CI -- Flushing the std outputs for the previous marker to show on the eNB / RRU log file + // end of CI modifications fflush(stdout); fflush(stderr); - // end of CI modifications + // wait_RUs() is wrong and over complex! wait_RUs(); LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU); // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) printf("ALL RUs ready - init eNBs\n"); - + if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) { LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n"); init_eNB_afterRU(); @@ -723,7 +739,7 @@ int main ( int argc, char **argv ) for (int inst = 0; inst < NB_eNB_INST; inst++) { for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) { free_transport(RC.eNB[inst][cc_id]); - phy_free_lte_eNB(RC.eNB[inst][cc_id]); + phy_free_lte_eNB(RC.eNB[inst][cc_id]); } } @@ -741,17 +757,17 @@ int main ( int argc, char **argv ) for(ru_id=0; ru_id<RC.nb_RU; ru_id++) { if (RC.ru[ru_id]->rfdevice.trx_end_func) { - RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); - RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; } if (RC.ru[ru_id]->ifdevice.trx_end_func) { - RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); - RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; } } } - + terminate_opt(); logClean(); printf("Bye.\n"); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 67120c5a2d1fc6f26147e306fdb7fd48025e40ca..0962bb6a2d423b53c15a5df0423525d675dda4f8 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -1562,12 +1562,12 @@ void write_dummy(PHY_VARS_UE *UE, openair0_timestamp timestamp) { for ( int i=0; i < UE->frame_parms.nb_antennas_tx; i++) samplesVoid[i]=(void *)&v; - AssertFatal(1 == UE->rfdevice.trx_write_func(&UE->rfdevice, - timestamp+2*UE->frame_parms.samples_per_tti, - samplesVoid, - 1, - UE->frame_parms.nb_antennas_tx, - 1),""); + AssertFatal( 1 == UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+2*UE->frame_parms.samples_per_tti, + samplesVoid, + 1, + UE->frame_parms.nb_antennas_tx, + 1),""); } void *UE_thread(void *arg) @@ -1618,36 +1618,36 @@ void *UE_thread(void *arg) int instance_cnt_synch = UE->proc.instance_cnt_synch; int is_synchronized = UE->is_synchronized; AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); - + if (is_synchronized == 0) { if (instance_cnt_synch < 0) { // we can invoke the synch // grab 10 ms of signal and wakeup synch thread if (UE->mode != loop_through_memory) { - if (IS_SOFTMODEM_RFSIM) { - for(int sf=0; sf<10; sf++) { - for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) - rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.samples_per_tti*sf]; - + if (IS_SOFTMODEM_RFSIM ) { + for(int sf=0; sf<10; sf++) { + for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) + rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.samples_per_tti*sf]; + AssertFatal(UE->frame_parms.samples_per_tti == UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti, - UE->frame_parms.nb_antennas_rx), ""); - write_dummy(UE, timestamp); - } - } else { - for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) - rxp[i] = (void *)&UE->common_vars.rxdata[i][0]; - - AssertFatal( UE->frame_parms.samples_per_tti*10 == + ×tamp, + rxp, + UE->frame_parms.samples_per_tti, + UE->frame_parms.nb_antennas_rx), ""); + write_dummy(UE, timestamp); + } + } else { + for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) + rxp[i] = (void *)&UE->common_vars.rxdata[i][0]; + + AssertFatal( UE->frame_parms.samples_per_tti*10 == UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp, rxp, UE->frame_parms.samples_per_tti*10, UE->frame_parms.nb_antennas_rx), ""); - } - } + } + } AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); instance_cnt_synch = ++UE->proc.instance_cnt_synch; @@ -1677,10 +1677,10 @@ void *UE_thread(void *arg) rxp, UE->frame_parms.samples_per_tti, UE->frame_parms.nb_antennas_rx); - if (IS_SOFTMODEM_RFSIM ) - write_dummy(UE, timestamp); - } - } + if (IS_SOFTMODEM_RFSIM ) + write_dummy(UE, timestamp); + } + } #endif } } // UE->is_synchronized==0 @@ -1691,17 +1691,17 @@ void *UE_thread(void *arg) if (UE->mode != loop_through_memory) { if (UE->no_timing_correction==0) { LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); - while ( UE->rx_offset ) { - size_t s=min(UE->rx_offset,UE->frame_parms.samples_per_tti); + while ( UE->rx_offset ) { + size_t s=min(UE->rx_offset,UE->frame_parms.samples_per_tti); AssertFatal(s == UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void **)UE->common_vars.rxdata, - s, - UE->frame_parms.nb_antennas_rx),""); - if (IS_SOFTMODEM_RFSIM ) - write_dummy(UE, timestamp); - UE->rx_offset-=s; - } + ×tamp, + (void **)UE->common_vars.rxdata, + s, + UE->frame_parms.nb_antennas_rx),""); + if (IS_SOFTMODEM_RFSIM ) + write_dummy(UE, timestamp); + UE->rx_offset-=s; + } } UE->rx_offset=0; @@ -1742,7 +1742,7 @@ void *UE_thread(void *arg) pthread_mutex_unlock(&proc->mutex_rxtx); } - usleep(300); + usleep(300); } LOG_D(PHY,"Process Subframe %d thread Idx %d \n", sub_frame, UE->current_thread_id[sub_frame]); diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index b03c16af43e4021a14fd7d401690ade787504a4d..395e73bb6622d6938cb5d30fa6e90c5a3624c934 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -281,13 +281,13 @@ void exit_function(const char *file, const char *function, const int line, const extern int16_t dlsch_demod_shift; static void get_options(void) { - int CC_id; - int tddflag = 0; - char *loopfile = NULL; - int dumpframe = 0; - int timingadv = 0; + int CC_id=0; + int tddflag=0; + char *loopfile=NULL; + int dumpframe=0; + int timingadv=0; uint8_t nfapi_mode = NFAPI_MONOLITHIC; - int simL1flag = 0; + int simL1flag =0; set_default_frame_parms(frame_parms); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); @@ -541,6 +541,12 @@ void init_pdcp(void) { pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); } +// Stupid function addition because UE itti messages queues definition is common with eNB +void *rrc_enb_process_msg(void *notUsed) { +AssertFatal(false,""); + return NULL; +} + int main( int argc, char **argv ) { int CC_id; uint8_t abstraction_flag=0;