diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 11ad982f302ad70c1c1f314e71179f033f8c8514..cbe0cfd151103f3e1d97c561646222c22e820708 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -2396,11 +2396,10 @@ add_executable(nr-uesoftmodem ${rrc_h} ${s1ap_h} # ${OPENAIR_BIN_DIR}/messages_xml.h - ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c - ${OPENAIR_TARGETS}/RT/USER/nr-ue.c - ${OPENAIR_TARGETS}/RT/USER/nr-uesoftmodem.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c + ${OPENAIR_DIR}/executables//nr-uesoftmodem.c + ${OPENAIR_DIR}/executables/nr-ue.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c -# ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c diff --git a/common/utils/threadPool/Makefile b/common/utils/threadPool/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..6f0e884886839933ee173e63c02042dde1d6cb23 --- /dev/null +++ b/common/utils/threadPool/Makefile @@ -0,0 +1,8 @@ +all: measurement_display thread-pool-test + +measurement_display: measurement_display.c thread-pool.h + gcc measurement_display.c -I /data/openairinterface5g.nr/common/utils/ -I. /data/openairinterface5g.nr/common/utils/backtrace.c -lpthread -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o measurement_display + +thread-pool-test: thread-pool.c thread-pool.h + gcc -g thread-pool.c -I /data/openairinterface5g.nr/common/utils/ -I. /data/openairinterface5g.nr/common/utils/backtrace.c -lpthread -D TEST_THREAD_POOL -I../LOG -I../../utils/T -o thread-pool-test + diff --git a/common/utils/threadPool/measurement_display.c b/common/utils/threadPool/measurement_display.c new file mode 100644 index 0000000000000000000000000000000000000000..ac7beca1fe00bac4b8d29d5906ded4cc5d7d1ea6 --- /dev/null +++ b/common/utils/threadPool/measurement_display.c @@ -0,0 +1,61 @@ +/* + Author: Laurent THOMAS, Open Cells + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#define __USE_GNU +#define _GNU_SOURCE +#include <stdio.h> +#include <pthread.h> +#include <sched.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <string.h> +#include <unistd.h> +#include <sys/syscall.h> +#include <sys/time.h> +#include <stdint.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "thread-pool.h" + +#define SEP "\t" + +uint64_t cpuCyclesMicroSec; + +int main(int argc, char *argv[]) { + if(argc != 2) { + printf("Need one paramter: the trace Linux pipe (fifo)"); + exit(1); + } + + mkfifo(argv[1],0666); + int fd=open(argv[1], O_RDONLY); + + if ( fd == -1 ) { + perror("open read mode trace file:"); + exit(1); + } + + uint64_t deb=rdtsc(); + usleep(100000); + cpuCyclesMicroSec=(rdtsc()-deb)/100000; + printf("Cycles per µs: %lu\n",cpuCyclesMicroSec); + printf("Key" SEP "delay to process" SEP "processing time" SEP "delay to be read answer\n"); + notifiedFIFO_elt_t doneRequest; + + while ( 1 ) { + if ( read(fd,&doneRequest, sizeof(doneRequest)) == sizeof(doneRequest)) { + printf("%lu" SEP "%lu" SEP "%lu" SEP "%lu" "\n", + doneRequest.key, + (doneRequest.startProcessingTime-doneRequest.creationTime)/cpuCyclesMicroSec, + (doneRequest.endProcessingTime-doneRequest.startProcessingTime)/cpuCyclesMicroSec, + (doneRequest.returnTime-doneRequest.endProcessingTime)/cpuCyclesMicroSec + ); + } else { + printf("no measurements\n"); + sleep(1); + } + } +} diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c new file mode 100644 index 0000000000000000000000000000000000000000..4cc56fc9b8126f8a5f88d03ce8be780563b7d116 --- /dev/null +++ b/common/utils/threadPool/thread-pool.c @@ -0,0 +1,230 @@ +/* + Author: Laurent THOMAS, Open Cells + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#define _GNU_SOURCE +#include <sched.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/sysinfo.h> +#include <threadPool/thread-pool.h> + +void displayList(notifiedFIFO_t *nf) { + int n=0; + notifiedFIFO_elt_t *ptr=nf->outF; + + while(ptr) { + printf("element: %d, key: %lu\n",++n,ptr->key); + ptr=ptr->next; + } + + printf("End of list: %d elements\n",n); +} + +static inline notifiedFIFO_elt_t *pullNotifiedFifoRemember( notifiedFIFO_t *nf, struct one_thread *thr) { + mutexlock(nf->lockF); + + while(!nf->outF) + condwait(nf->notifF, nf->lockF); + + notifiedFIFO_elt_t *ret=nf->outF; + nf->outF=nf->outF->next; + + if (nf->outF==NULL) + nf->inF=NULL; + + // For abort feature + thr->runningOnKey=ret->key; + thr->abortFlag=false; + mutexunlock(nf->lockF); + return ret; +} + +void *one_thread(void *arg) { + struct one_thread *myThread=(struct one_thread *) arg; + struct thread_pool *tp=myThread->pool; + + // configure the thread core assignment + // TBD: reserve the core for us exclusively + if ( myThread->coreID >= 0 && myThread->coreID < get_nprocs_conf()) { + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(myThread->coreID, &cpuset); + pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + } + + //Configure the thread scheduler policy for Linux + struct sched_param sparam= {0}; + sparam.sched_priority = sched_get_priority_max(SCHED_RR); + pthread_setschedparam(pthread_self(), SCHED_RR, &sparam); + // set the thread name for debugging + sprintf(myThread->name,"Tpool_%d",myThread->coreID); + pthread_setname_np(pthread_self(), myThread->name ); + + // Infinite loop to process requests + do { + notifiedFIFO_elt_t *elt=pullNotifiedFifoRemember(&tp->incomingFifo, myThread); + + if (tp->measurePerf) elt->startProcessingTime=rdtsc(); + + elt->processingFunc(NotifiedFifoData(elt)); + + if (tp->measurePerf) elt->endProcessingTime=rdtsc(); + + if (elt->reponseFifo) { + // Check if the job is still alive, else it has been aborted + mutexlock(tp->incomingFifo.lockF); + + if (myThread->abortFlag) + delNotifiedFIFO_elt(elt); + else + pushNotifiedFIFO(elt->reponseFifo, elt); + + mutexunlock(tp->incomingFifo.lockF); + } + } while (true); +} + +void initTpool(char *params,tpool_t *pool, bool performanceMeas) { + memset(pool,0,sizeof(*pool)); + char *measr=getenv("threadPoolMeasurements"); + pool->measurePerf=performanceMeas; + // force measurement if the output is defined + pool->measurePerf=measr!=NULL; + + if (measr) { + mkfifo(measr,0666); + AssertFatal(-1 != (pool->dummyTraceFd= + open(measr, O_RDONLY| O_NONBLOCK)),""); + AssertFatal(-1 != (pool->traceFd= + open(measr, O_WRONLY|O_APPEND|O_NOATIME|O_NONBLOCK)),""); + } else + pool->traceFd=-1; + + //Configure the thread scheduler policy for Linux + struct sched_param sparam= {0}; + sparam.sched_priority = sched_get_priority_max(SCHED_RR)-1; + pthread_setschedparam(pthread_self(), SCHED_RR, &sparam); + pool->activated=true; + initNotifiedFIFO(&pool->incomingFifo); + char *saveptr, * curptr; + pool->nbThreads=0; + pool->restrictRNTI=false; + curptr=strtok_r(params,",",&saveptr); + + while ( curptr!=NULL ) { + int c=toupper(curptr[0]); + + switch (c) { + case 'U': + pool->restrictRNTI=true; + break; + + case 'N': + pool->activated=false; + break; + + default: + pool->allthreads=(struct one_thread *)malloc(sizeof(struct one_thread)); + pool->allthreads->next=pool->allthreads; + printf("create a thread for core %d\n", atoi(curptr)); + pool->allthreads->coreID=atoi(curptr); + pool->allthreads->id=pool->nbThreads; + pool->allthreads->pool=pool; + pthread_create(&pool->allthreads->threadID, NULL, one_thread, (void *)pool->allthreads); + pool->nbThreads++; + } + + curptr=strtok_r(NULL,",",&saveptr); + } + + if (pool->activated && pool->nbThreads==0) { + printf("No servers created in the thread pool, exit\n"); + exit(1); + } +} + +#ifdef TEST_THREAD_POOL + +struct testData { + int id; + char txt[30]; +}; + +void processing(void *arg) { + struct testData *in=(struct testData *)arg; + printf("doing: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); + sprintf(in->txt,"Done by %ld, job %d", pthread_self(), in->id); + usleep(rand()%100); + printf("done: %d, %s, in thr %ld\n",in->id, in->txt,pthread_self() ); +} + +int main() { + notifiedFIFO_t myFifo; + initNotifiedFIFO(&myFifo); + pushNotifiedFIFO(&myFifo,newNotifiedFIFO_elt(sizeof(struct testData), 1234,NULL,NULL)); + + for(int i=10; i>1; i--) { + pushNotifiedFIFO(&myFifo,newNotifiedFIFO_elt(sizeof(struct testData), 1000+i,NULL,NULL)); + } + + displayList(&myFifo); + notifiedFIFO_elt_t *tmp=pullNotifiedFIFO(&myFifo); + printf("pulled: %lu\n", tmp->key); + displayList(&myFifo); + tmp=pullNotifiedFIFO(&myFifo); + printf("pulled: %lu\n", tmp->key); + displayList(&myFifo); + abortNotifiedFIFO(&myFifo,1005); + printf("aborted 1005\n"); + displayList(&myFifo); + pushNotifiedFIFO(&myFifo,newNotifiedFIFO_elt(sizeof(struct testData), 12345678, NULL, NULL)); + displayList(&myFifo); + abortNotifiedFIFO(&myFifo,12345678); + printf("aborted 12345678\n"); + displayList(&myFifo); + + do { + tmp=pollNotifiedFIFO(&myFifo); + + if (tmp) { + printf("pulled: %lu\n", tmp->key); + displayList(&myFifo); + } else + printf("Empty list \n"); + } while(tmp); + + tpool_t pool; + char params[]="1,2,3,u"; + initTpool(params,&pool, true); + notifiedFIFO_t worker_back; + initNotifiedFIFO(&worker_back); + + for (int i=0; i <1000 ; i++) { + notifiedFIFO_elt_t *work=newNotifiedFIFO_elt(sizeof(struct testData), i, &worker_back, processing); + struct testData *x=(struct testData *)NotifiedFifoData(work); + x->id=i; + pushTpool(&pool, work); + } + + do { + tmp=pullTpool(&worker_back,&pool); + + if (tmp) { + struct testData *dd=NotifiedFifoData(tmp); + printf("Result: %s\n",dd->txt); + delNotifiedFIFO_elt(tmp); + } else + printf("Empty list \n"); + + abortTpool(&pool,510); + } while(tmp); + + return 0; +} +#endif diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h new file mode 100644 index 0000000000000000000000000000000000000000..6f34508c5a9023b23d3b15e4be9b036c09b2b06a --- /dev/null +++ b/common/utils/threadPool/thread-pool.h @@ -0,0 +1,244 @@ +/* + Author: Laurent THOMAS, Open Cells + copyleft: OpenAirInterface Software Alliance and it's licence +*/ + +#ifndef THREAD_POOL_H +#define THREAD_POOL_H +#include <stdbool.h> +#include <stdint.h> +#include <pthread.h> +#include <sys/syscall.h> +#include <assertions.h> +#include <LOG/log.h> + +#ifdef DEBUG + #define THREADINIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP +#else + #define THREADINIT PTHREAD_MUTEX_INITIALIZER +#endif +#define mutexinit(mutex) AssertFatal(pthread_mutex_init(&mutex,NULL)==0,""); +#define condinit(signal) AssertFatal(pthread_cond_init(&signal,NULL)==0,""); +#define mutexlock(mutex) AssertFatal(pthread_mutex_lock(&mutex)==0,""); +#define mutextrylock(mutex) pthread_mutex_trylock(&mutex) +#define mutexunlock(mutex) AssertFatal(pthread_mutex_unlock(&mutex)==0,""); +#define condwait(condition, mutex) AssertFatal(pthread_cond_wait(&condition, &mutex)==0,""); +#define condbroadcast(signal) AssertFatal(pthread_cond_broadcast(&signal)==0,""); +#define condsignal(signal) AssertFatal(pthread_cond_broadcast(&signal)==0,""); + +typedef struct notifiedFIFO_elt_s { + struct notifiedFIFO_elt_s *next; + uint64_t key; //To filter out elements + struct notifiedFIFO_s *reponseFifo; + void (*processingFunc)(void *); + bool malloced; + uint64_t creationTime; + uint64_t startProcessingTime; + uint64_t endProcessingTime; + uint64_t returnTime; + void *msgData; +} notifiedFIFO_elt_t; + +typedef struct notifiedFIFO_s { + notifiedFIFO_elt_t *outF; + notifiedFIFO_elt_t *inF; + pthread_mutex_t lockF; + pthread_cond_t notifF; +} notifiedFIFO_t; + +// You can use this allocator or use any piece of memory +static inline notifiedFIFO_elt_t *newNotifiedFIFO_elt(int size, + uint64_t key, + notifiedFIFO_t *reponseFifo, + void (*processingFunc)(void *)) { + notifiedFIFO_elt_t *ret; + AssertFatal( NULL != (ret=(notifiedFIFO_elt_t *) malloc(sizeof(notifiedFIFO_elt_t)+size+32)), ""); + ret->next=NULL; + ret->key=key; + ret->reponseFifo=reponseFifo; + ret->processingFunc=processingFunc; + // We set user data piece aligend 32 bytes to be able to process it with SIMD + ret->msgData=(void *)ret+(sizeof(notifiedFIFO_elt_t)/32+1)*32; + ret->malloced=true; + return ret; +} + +static inline void *NotifiedFifoData(notifiedFIFO_elt_t *elt) { + return elt->msgData; +} + +static inline void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt) { + if (elt->malloced) { + elt->malloced=false; + free(elt); + } else + printf("delNotifiedFIFO on something not allocated by newNotifiedFIFO\n"); + + //LOG_W(UTIL,"delNotifiedFIFO on something not allocated by newNotifiedFIFO\n"); +} + +static inline void initNotifiedFIFO(notifiedFIFO_t *nf) { + mutexinit(nf->lockF); + condinit (nf->notifF); + nf->inF=NULL; + nf->outF=NULL; + // No delete function: the creator has only to free the memory +} + +static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) { + mutexlock(nf->lockF); + msg->next=NULL; + + if (nf->outF == NULL) + nf->outF = msg; + + if (nf->inF) + nf->inF->next = msg; + + nf->inF = msg; + condbroadcast(nf->notifF); + mutexunlock(nf->lockF); +} + +static inline notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf) { + mutexlock(nf->lockF); + + while(!nf->outF) + condwait(nf->notifF, nf->lockF); + + notifiedFIFO_elt_t *ret=nf->outF; + nf->outF=nf->outF->next; + + if (nf->outF==NULL) + nf->inF=NULL; + + mutexunlock(nf->lockF); + return ret; +} + +static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf) { + int tmp=mutextrylock(nf->lockF); + + if (tmp != 0 ) + return NULL; + + notifiedFIFO_elt_t *ret=nf->outF; + + if (ret!=NULL) + nf->outF=nf->outF->next; + + if (nf->outF==NULL) + nf->inF=NULL; + + mutexunlock(nf->lockF); + return ret; +} + +// This function aborts all messages matching the key +// If the queue is used in thread pools, it doesn't cancels already running processing +// because the message has already been picked +static inline void abortNotifiedFIFO(notifiedFIFO_t *nf, uint64_t key) { + mutexlock(nf->lockF); + notifiedFIFO_elt_t **start=&nf->outF; + + while(*start!=NULL) { + if ( (*start)->key == key ) { + notifiedFIFO_elt_t *request=*start; + *start=(*start)->next; + delNotifiedFIFO_elt(request); + } + + if (*start != NULL) + start=&(*start)->next; + } + + mutexunlock(nf->lockF); +} + +struct one_thread { + pthread_t threadID; + int id; + int coreID; + char name[256]; + uint64_t runningOnKey; + bool abortFlag; + struct thread_pool *pool; + struct one_thread *next; +}; + +typedef struct thread_pool { + int activated; + bool measurePerf; + int traceFd; + int dummyTraceFd; + uint64_t cpuCyclesMicroSec; + uint64_t startProcessingUE; + int nbThreads; + bool restrictRNTI; + notifiedFIFO_t incomingFifo; + struct one_thread *allthreads; +} tpool_t; + +static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { + if (t->measurePerf) msg->creationTime=rdtsc(); + + pushNotifiedFIFO(&t->incomingFifo, msg); +} + +static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { + notifiedFIFO_elt_t *msg= pullNotifiedFIFO(responseFifo); + + if (t->measurePerf) + msg->returnTime=rdtsc(); + + if (t->traceFd) + if(write(t->traceFd, msg, sizeof(*msg))); + + return msg; +} + +static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { + notifiedFIFO_elt_t *msg= pollNotifiedFIFO(responseFifo); + + if (msg == NULL) + return NULL; + + if (t->measurePerf) + msg->returnTime=rdtsc(); + + if (t->traceFd) + if(write(t->traceFd, msg, sizeof(*msg))); + + return msg; +} + +static inline void abortTpool(tpool_t *t, uint64_t key) { + notifiedFIFO_t *nf=&t->incomingFifo; + mutexlock(nf->lockF); + notifiedFIFO_elt_t **start=&nf->outF; + + while(*start!=NULL) { + if ( (*start)->key == key ) { + notifiedFIFO_elt_t *request=*start; + *start=(*start)->next; + delNotifiedFIFO_elt(request); + } + + if (*start != NULL) + start=&(*start)->next; + } + + struct one_thread *ptr=t->allthreads; + + while(ptr!=NULL) { + if (ptr->runningOnKey==key) + ptr->abortFlag=true; + + ptr=ptr->next; + } + + mutexunlock(nf->lockF); +} +void initTpool(char *params,tpool_t *pool, bool performanceMeas); + +#endif diff --git a/common/utils/threadPool/thread-pool.md b/common/utils/threadPool/thread-pool.md new file mode 100644 index 0000000000000000000000000000000000000000..2b6336fb6093e7789d82aeb5ccef6cd5815b5f27 --- /dev/null +++ b/common/utils/threadPool/thread-pool.md @@ -0,0 +1,71 @@ +# Thread pool + +The thread pool is a working server, made of a set of worker threads that can be mapped on CPU cores. + +Each worker loop on pick from the same input queue jobs to do. +When a job is done, the worker sends a return if a return is defined. + +A selective abort allows to cancel parallel jobs (usage: a client pushed jobs, but from a response of one job, the other linked jobs becomes useless). + +All the thread pool functions are thread safe, nevertheless the working functions are implemented by the thread pool client, so the client has to tackle the parallel execution of his functions called "processingFunc" hereafter. + +## license +Author: Laurent Thomas, Open cells project +The owner share this piece code to Openairsoftware alliance as per OSA license terms + +# jobs + +A job is a message (notifiedFIFO_elt_t): +next: internal FIFO chain, do not set it +key: a long int that the client can use to identify a message or a group of messages +responseFifo: if the client defines a response FIFO, the message will be posted back after processing +processingFunc: any funtion (type void processingFunc(void *)) that the worker will launch +msgData: the data passed to processingFunc. It can be added automatically, or you can set it to a buffer you are managing +malloced: a boolean that enable internal free in these cases: no return Fifo or Abort feature + +The job messages can be created with newNotifiedFIFO_elt() and delNotifiedFIFO_elt() or managed by the client. + +# Queues of jobs + +Queues are type of: notifiedFIFO_t that must be initialized by init_notifiedFIFO() +No delete function is required, the creator has only to free the data of type notifiedFIFO_t + +push_notifiedFIFO() add a job in the queue +pull_notifiedFIFO() is blocking, poll_notifiedFIFO() is non blocking + +abort_notifiedFIFO() allows the customer to delete all waiting jobs that match with the key (see key in jobs definition) + +# Thread pools + +## initialization +The clients can create one or more thread pools with init_tpool() +the params string structure: describes a list of cores, separated by "," that run a worker thread + +If the core exists on the CPU, the thread pool initialization sets the affinity between this thread and the related code (use negative values is allowed, so the thread will never be mapped on a specific core). + +The threads are all Linux real time scheduler, their name is set automatically is "Tpool_<core id>" + +## adding jobs +The client create their jobs messages as a notifiedFIFO_elt_t, then they push it with pushTpool() (that internally calls push_notifiedFIFO()) + +If they need a return, they have to create response queues with init_notifiedFIFO() and set this FIFO pointer in the notifiedFIFO_elt_t before pushing the job. + +## abort + +A abort service abortTpool() allows to abort all jobs that match a key (see jobs "key"). When the abort returns, it garanties no job (matching the key) response will be posted on response queues. + +Nevertheless, jobs already performed before the return of abortTpool() are pushed in the response Fifo queue. + +## Performance measurements + +A performance measurement is integrated: the pool will automacillay fill timestamps: + +* creationTime: time the request is push to the pool; +* startProcessingTime: time a worker start to run on the job +* endProcessingTime: time the worker finished the job +* returnTime: time the client reads the result + +if you set the environement variable: thread-pool-measurements to a valid file name +These measurements will be wrote to this Linux pipe. + +A tool to read the linux fifo and display it in ascii is provided: see the local directory Makefile for this tool and to compile the thread pool unitary tests. diff --git a/executables/nr-ue.c b/executables/nr-ue.c new file mode 100644 index 0000000000000000000000000000000000000000..402c3796877479df9dc771a18601e34e922e4f8f --- /dev/null +++ b/executables/nr-ue.c @@ -0,0 +1,732 @@ +/* + * 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.0 (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 + */ + +#include "executables/nr-uesoftmodem.h" + +#include "LAYER2/NR_MAC_UE/mac.h" +//#include "RRC/LTE/rrc_extern.h" +#include "PHY_INTERFACE/phy_interface_extern.h" + +#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all +//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "fapi_nr_ue_l1.h" +#include "PHY/phy_extern_nr_ue.h" +#include "PHY/INIT/phy_init.h" +#include "PHY/MODULATION/modulation_UE.h" +#include "LAYER2/NR_MAC_UE/mac_proto.h" +#include "RRC/NR_UE/rrc_proto.h" + +//#ifndef NO_RAT_NR +#include "SCHED_NR/phy_frame_config_nr.h" +//#endif +#include "SCHED_NR_UE/defs.h" + +#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" + +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#include "T.h" + +#ifdef XFORMS + #include "PHY/TOOLS/nr_phy_scope.h" + + extern char do_forms; +#endif + + +extern double cpuf; +//static nfapi_nr_config_request_t config_t; +//static nfapi_nr_config_request_t* config =&config_t; + +/* + * NR SLOT PROCESSING SEQUENCE + * + * Processing occurs with following steps for connected mode: + * + * - Rx samples for a slot are received, + * - PDCCH processing (including DCI extraction for downlink and uplink), + * - PDSCH processing (including transport blocks decoding), + * - PUCCH/PUSCH (transmission of acknowledgements, CSI, ... or data). + * + * Time between reception of the slot and related transmission depends on UE processing performance. + * It is defined by the value NR_UE_CAPABILITY_SLOT_RX_TO_TX. + * + * In NR, network gives the duration between Rx slot and Tx slot in the DCI: + * - for reception of a PDSCH and its associated acknowledgment slot (with a PUCCH or a PUSCH), + * - for reception of an uplink grant and its associated PUSCH slot. + * + * So duration between reception and it associated transmission depends on its transmission slot given in the DCI. + * NR_UE_CAPABILITY_SLOT_RX_TO_TX means the minimum duration but higher duration can be given by the network because UE can support it. + * + * Slot k + * -------+------------+-------- + * Frame | Tx samples | + * Subframe | buffer | + * Slot n -------+------------+-------- + * ------ +------------+-------- | + * | Rx samples | | + * | buffer | | + * -------+------------+-------- | + * | | + * V | + * +------------+ | + * | PDCCH | | + * | processing | | + * +------------+ | + * | | | + * | v | + * | +------------+ | + * | | PDSCH | | + * | | processing | decoding result | + * | +------------+ -> ACK/NACK of PDSCH | + * | | | + * | v | + * | +-------------+------------+ | + * | | PUCCH/PUSCH | Tx samples | | + * | | processing | transfer | | + * | +-------------+------------+ | + * | | + * |/___________________________________________________________\| + * \ duration between reception and associated transmission / + * + * Remark: processing is done slot by slot, it can be distribute on different threads which are executed in parallel. + * This is an architecture optimization in order to cope with real time constraints. + * By example, for LTE, subframe processing is spread over 4 different threads. + * + */ + +#ifndef NO_RAT_NR + #define DURATION_RX_TO_TX (NR_UE_CAPABILITY_SLOT_RX_TO_TX) /* for NR this will certainly depends to such UE capability which is not yet defined */ +#else + #define DURATION_RX_TO_TX (4) /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */ +#endif + +#define FRAME_PERIOD 100000000ULL +#define DAQ_PERIOD 66667ULL +#define FIFO_PRIORITY 40 + +typedef enum { + pss=0, + pbch=1, + si=2 +} sync_mode_t; + + +PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms, + uint8_t UE_id, + uint8_t abstraction_flag) + +{ + PHY_VARS_NR_UE *ue; + + if (frame_parms!=(NR_DL_FRAME_PARMS *)NULL) { // if we want to give initial frame parms, allocate the PHY_VARS_UE structure and put them in + ue = (PHY_VARS_NR_UE *)malloc(sizeof(PHY_VARS_NR_UE)); + memset(ue,0,sizeof(PHY_VARS_NR_UE)); + memcpy(&(ue->frame_parms), frame_parms, sizeof(NR_DL_FRAME_PARMS)); + } else ue = PHY_vars_UE_g[UE_id][0]; + + ue->Mod_id = UE_id; + ue->mac_enabled = 1; + // initialize all signal buffers + init_nr_ue_signal(ue,1,abstraction_flag); + // intialize transport + init_nr_ue_transport(ue,abstraction_flag); + return(ue); +} + +/*! + * It performs band scanning and synchonization. + * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure. + */ + +typedef struct syncData_s { + PHY_VARS_NR_UE *UE; +} syncData_t; + +static void UE_synch(void *arg) { + syncData_t *syncD=(syncData_t *) arg; + int i, hw_slot_offset; + PHY_VARS_NR_UE *UE = syncD->UE; + int current_band = 0; + int current_offset = 0; + sync_mode_t sync_mode = pbch; + int CC_id = UE->CC_id; + int freq_offset=0; + UE->is_synchronized = 0; + + if (UE->UE_scan == 0) { + int ind; + + get_band(downlink_frequency[CC_id][0], &UE->frame_parms.eutra_band, &uplink_frequency_offset[CC_id][0], &UE->frame_parms.frame_type); + + LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", + downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0], + oai_exit, openair0_cfg[0].rx_num_channels); + + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + + if (uplink_frequency_offset[CC_id][i] != 0) // + openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD; + else //FDD + openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD; + } + + sync_mode = pbch; + } else { + current_band=0; + LOG_E(PHY,"Fixme!\n"); + /* + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = + bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min; + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + } + */ + } + + LOG_W(PHY, "Starting sync detection\n"); + + switch (sync_mode) { + /* + case pss: + LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); + //lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset); + current_offset += 20000000; // increase by 20 MHz + + if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) { + current_band++; + current_offset=0; + } + + if (current_band==bands_to_scan.nbands) { + current_band=0; + oai_exit=1; + } + + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset; + uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset; + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB; + + if (UE->UE_scan_carrier) { + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + } + } + + break; + */ + + case pbch: + LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); + + if (nr_initial_sync( UE, UE->mode ) == 0) { + freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync + hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_slot; + LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", + hw_slot_offset, + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset, + UE->UE_scan_carrier ); + + // rerun with new cell parameters and frequency-offset + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + + if (freq_offset >= 0) + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset); + else + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset); + + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; + downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; + } + + // reconfigure for potentially different bandwidth + switch(UE->frame_parms.N_RB_DL) { + case 6: + openair0_cfg[UE->rf_map.card].sample_rate =1.92e6; + openair0_cfg[UE->rf_map.card].rx_bw =.96e6; + openair0_cfg[UE->rf_map.card].tx_bw =.96e6; + // openair0_cfg[0].rx_gain[0] -= 12; + break; + + case 25: + openair0_cfg[UE->rf_map.card].sample_rate =7.68e6; + openair0_cfg[UE->rf_map.card].rx_bw =2.5e6; + openair0_cfg[UE->rf_map.card].tx_bw =2.5e6; + // openair0_cfg[0].rx_gain[0] -= 6; + break; + + case 50: + openair0_cfg[UE->rf_map.card].sample_rate =15.36e6; + openair0_cfg[UE->rf_map.card].rx_bw =5.0e6; + openair0_cfg[UE->rf_map.card].tx_bw =5.0e6; + // openair0_cfg[0].rx_gain[0] -= 3; + break; + + case 100: + openair0_cfg[UE->rf_map.card].sample_rate=30.72e6; + openair0_cfg[UE->rf_map.card].rx_bw=10.0e6; + openair0_cfg[UE->rf_map.card].tx_bw=10.0e6; + // openair0_cfg[0].rx_gain[0] -= 0; + break; + } + + if (UE->mode != loop_through_memory) { + UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); + //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]); + //UE->rfdevice.trx_stop_func(&UE->rfdevice); + // sleep(1); + //nr_init_frame_parms_ue(&UE->frame_parms); + /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { + LOG_E(HW,"Could not start the device\n"); + oai_exit=1; + }*/ + } + + if (UE->UE_scan_carrier == 1) { + UE->UE_scan_carrier = 0; + } else { + UE->is_synchronized = 1; + } + } else { + // initial sync failed + // calculate new offset and try again + if (UE->UE_scan_carrier == 1) { + if (freq_offset >= 0) + freq_offset += 100; + + freq_offset *= -1; + LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", + freq_offset, + UE->rx_total_gain_dB, + downlink_frequency[0][0]+freq_offset, + downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset ); + + for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) { + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset; + openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset; + openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; + + if (UE->UE_scan_carrier==1) + openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1; + } + + if (UE->mode != loop_through_memory) + UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0); + }// initial_sync=0 + + break; + + case si: + default: + break; + } + } +} + +void processSubframeRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { + // Process Rx data for one sub-frame + if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_DOWNLINK_SLOT) { + //clean previous FAPI MESSAGE + UE->rx_ind.number_pdus = 0; + UE->dci_ind.number_of_dcis = 0; + //clean previous FAPI MESSAGE + // call L2 for DL_CONFIG (DCI) + UE->dcireq.module_id = UE->Mod_id; + UE->dcireq.gNB_index = 0; + UE->dcireq.cc_id = 0; + UE->dcireq.frame = proc->frame_rx; + UE->dcireq.slot = proc->nr_tti_rx; + nr_ue_dcireq(&UE->dcireq); //to be replaced with function pointer later + NR_UE_MAC_INST_t *UE_mac = get_mac_inst(0); + UE_mac->scheduled_response.dl_config = &UE->dcireq.dl_config_req; + UE_mac->scheduled_response.slot = proc->nr_tti_rx; + nr_ue_scheduled_response(&UE_mac->scheduled_response); + //write_output("uerxdata_frame.m", "uerxdata_frame", UE->common_vars.rxdata[0], UE->frame_parms.samples_per_frame, 1, 1); + printf("Processing slot %d\n",proc->nr_tti_rx); +#ifdef UE_SLOT_PARALLELISATION + phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL ); +#else + phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode); + // printf(">>> nr_ue_pdcch_procedures ended\n"); +#endif + } + + if (UE->mac_enabled==1) { + // trigger L2 to run ue_scheduler thru IF module + // [TODO] mapping right after NR initial sync + if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) { + UE->ul_indication.module_id = 0; + UE->ul_indication.gNB_index = 0; + UE->ul_indication.cc_id = 0; + UE->ul_indication.frame = proc->frame_rx; + UE->ul_indication.slot = proc->nr_tti_rx; + UE->if_inst->ul_indication(&UE->ul_indication); + } + } +} + +/*! + * \brief This is the UE thread for RX subframe n and TX subframe n+4. + * This thread performs the phy_procedures_UE_RX() on every received slot. + * then, if TX is enabled it performs TX for n+4. + * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure. + * \returns a pointer to an int. The storage is not on the heap and must not be freed. + */ + +typedef struct processingData_s { + UE_nr_rxtx_proc_t proc; + PHY_VARS_NR_UE *UE; +} processingData_t; + +void UE_processing(void *arg) { + processingData_t *rxtxD=(processingData_t *) arg; + UE_nr_rxtx_proc_t *proc = &rxtxD->proc; + PHY_VARS_NR_UE *UE = rxtxD->UE; + processSubframeRX(UE, proc); + //printf(">>> mac ended\n"); + // Prepare the future Tx data +#if 0 +#ifndef NO_RAT_NR + + if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_UPLINK_SLOT) +#else + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || + (UE->frame_parms.frame_type == FDD) ) +#endif + if (UE->mode != loop_through_memory) + phy_procedures_nrUE_TX(UE,proc,0,0,UE->mode,no_relay); + + //phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay); +#endif +#if 0 + + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) && + (UE->frame_parms.frame_type == TDD)) + if (UE->mode != loop_through_memory) + //phy_procedures_UE_S_TX(UE,0,0,no_relay); + updateTimes(current, &t3, 10000, timing_proc_name); + +#endif +} + +void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + void *rxp[NB_ANTENNAS_RX]; + void *dummy_tx[UE->frame_parms.nb_antennas_tx]; + + for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++) + dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); + + for(int x=0; x<10; x++) { + for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) + rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) + 4*x*UE->frame_parms.samples_per_subframe; + + AssertFatal( UE->frame_parms.samples_per_subframe == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + rxp, + UE->frame_parms.samples_per_subframe, + UE->frame_parms.nb_antennas_rx), ""); + } + + for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++) + free(dummy_tx[i]); +} + +void trashFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + void *dummy_tx[UE->frame_parms.nb_antennas_tx]; + + for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++) + dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); + + void *dummy_rx[UE->frame_parms.nb_antennas_rx]; + + for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) + dummy_rx[i]=malloc16(UE->frame_parms.samples_per_subframe*4); + + for (int sf=0; sf<NR_NUMBER_OF_SUBFRAMES_PER_FRAME; sf++) { + // printf("Reading dummy sf %d\n",sf); + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + dummy_rx, + UE->frame_parms.samples_per_subframe, + UE->frame_parms.nb_antennas_rx); + } + + for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++) + free(dummy_tx[i]); + + for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) + free(dummy_rx[i]); +} + +void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { + if (UE->no_timing_correction==0) { + 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]; + + for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++) + dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); + + for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { + int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ; + AssertFatal(unitTransfer == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + (void **)UE->common_vars.rxdata, + unitTransfer, + UE->frame_parms.nb_antennas_rx),""); + } + + for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++) + free(dummy_tx[i]); + } +} + +int computeSamplesShift(PHY_VARS_NR_UE *UE) { + if ( getenv("RFSIMULATOR") != 0) { + LOG_E(PHY,"SET rx_offset %d \n",UE->rx_offset); + //UE->rx_offset_diff=0; + return 0; + } + + // compute TO compensation that should be applied for this frame + if ( UE->rx_offset < 5*UE->frame_parms.samples_per_slot && + UE->rx_offset > 0 ) + return -1 ; + + if ( UE->rx_offset > 5*UE->frame_parms.samples_per_slot && + UE->rx_offset < 10*UE->frame_parms.samples_per_slot ) + return 1; + + return 0; +} + +void *UE_thread(void *arg) { + PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; + // int tx_enabled = 0; + openair0_timestamp timestamp; + void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX]; + int start_rx_stream = 0; + const uint16_t table_sf_slot[20] = {0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9}; + AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), ""); + UE->rfdevice.host_type = RAU_HOST; + AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n"); + notifiedFIFO_t nf; + initNotifiedFIFO(&nf); + bool syncRunning=false; + notifiedFIFO_elt_t *syncMsg=newNotifiedFIFO_elt(sizeof(syncData_t),0,&nf,UE_synch); + syncData_t *syncD=(syncData_t *)NotifiedFifoData(syncMsg); + syncD->UE=UE; + int nbSlotProcessing=0; + int thread_idx=0; + notifiedFIFO_elt_t *processingMsg[RX_NB_TH]; + + for (int i=0; i<RX_NB_TH; i++) { + processingMsg[i]= newNotifiedFIFO_elt(sizeof(processingData_t), 0,&nf,UE_processing); + processingData_t *tmp=(processingData_t *)NotifiedFifoData(processingMsg[i]); + tmp->UE=UE; + } + + const int nb_slot_frame = 10*UE->frame_parms.slots_per_subframe; + int absolute_slot=-1; + + while (!oai_exit) { + if (!syncD->UE->is_synchronized) { + if (syncRunning) { + notifiedFIFO_elt_t *res=tryPullTpool(&nf, Tpool); + + if (res) { + syncRunning=false; + } else + trashFrame(UE, ×tamp); + } else { + readFrame(UE, ×tamp); + pushTpool(Tpool, syncMsg); + syncRunning=true; + } + + continue; + } + + if (start_rx_stream==0) { + start_rx_stream=1; + syncInFrame(UE, ×tamp); + UE->rx_offset=0; + UE->time_sync_cell=0; + //printf("first stream frame rx %d\n",UE->proc.proc_rxtx[0].frame_rx); + // read in first symbol + AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void **)UE->common_vars.rxdata, + UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, + UE->frame_parms.nb_antennas_rx),""); + continue; + } + + absolute_slot++; + thread_idx = absolute_slot % RX_NB_TH; + int slot_nr=absolute_slot % nb_slot_frame; + UE_nr_rxtx_proc_t *proc=&(((processingData_t *)NotifiedFifoData(processingMsg[thread_idx]))->proc); + // update thread index for received subframe + proc->nr_tti_rx= slot_nr; + UE->current_thread_id[slot_nr] = thread_idx; + proc->subframe_rx=table_sf_slot[slot_nr]; + proc->nr_tti_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame; + proc->subframe_tx=proc->nr_tti_rx; + proc->frame_rx = ( absolute_slot/nb_slot_frame ) % MAX_FRAME_NUMBER; + proc->frame_tx = ( (absolute_slot + DURATION_RX_TO_TX) /nb_slot_frame ) % MAX_FRAME_NUMBER; + LOG_D(PHY,"Process slot %d thread Idx %d \n", slot_nr, thread_idx); + + for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++) + rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+ + UE->frame_parms.nb_prefix_samples0+ + slot_nr*UE->frame_parms.samples_per_slot]; + + for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++) + txp[i] = (void *)&UE->common_vars.txdata[i][proc->nr_tti_tx*UE->frame_parms.samples_per_slot]; + + int readBlockSize, writeBlockSize; + + if (slot_nr<(nb_slot_frame - 1)) { + readBlockSize=UE->frame_parms.samples_per_slot; + writeBlockSize=UE->frame_parms.samples_per_slot; + } else { + UE->rx_offset_diff = computeSamplesShift(UE); + readBlockSize=UE->frame_parms.samples_per_slot - + UE->frame_parms.ofdm_symbol_size - + UE->frame_parms.nb_prefix_samples0 - + UE->rx_offset_diff; + writeBlockSize=UE->frame_parms.samples_per_slot - + UE->rx_offset_diff; + } + + AssertFatal(readBlockSize == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + readBlockSize, + UE->frame_parms.nb_antennas_rx),""); + AssertFatal( writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+ + (2*UE->frame_parms.samples_per_slot) - + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - + openair0_cfg[0].tx_sample_advance, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + 1),""); + + if( slot_nr==(nb_slot_frame-1)) { + // read in first symbol of next frame and adjust for timing drift + int first_symbols=writeBlockSize-readBlockSize; + + if ( first_symbols > 0 ) + AssertFatal(first_symbols == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void **)UE->common_vars.rxdata, + first_symbols, + UE->frame_parms.nb_antennas_rx),""); + else + LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols); + } + + proc->timestamp_tx = timestamp+ + (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot)- + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0; + + if (getenv("RFSIMULATOR")) { + // FixMe: Wait previous thread is done, because race conditions seems too bad + // in case of actual RF board, the overlap between threads mitigate the issue + while (!tryPullTpool(&nf, Tpool)) { + nbSlotProcessing--; + usleep(200); + } + } + + while (nbSlotProcessing >= RX_NB_TH && !tryPullTpool(&nf, Tpool)) { + nbSlotProcessing--; + usleep(200); + } + + pushTpool(Tpool, processingMsg[thread_idx]); + } // while !oai_exit + + return NULL; +} + +void init_UE(int nb_inst) { + int inst; + NR_UE_MAC_INST_t *mac_inst; + pthread_t threads[nb_inst]; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedpolicy(&attr, SCHED_RR); + struct sched_param sched; + sched.sched_priority = sched_get_priority_max(SCHED_RR)-1; + pthread_attr_setschedparam(&attr, &sched); + + for (inst=0; inst < nb_inst; inst++) { + // UE->rfdevice.type = NONE_DEV; + //PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0]; + LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]); + PHY_vars_UE_g[inst][0] = init_nr_ue_vars(NULL,inst,0); + PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0]; + AssertFatal((UE->if_inst = nr_ue_if_module_init(inst)) != NULL, "can not initial IF module\n"); + nr_l3_init_ue(); + nr_l2_init_ue(); + mac_inst = get_mac_inst(0); + mac_inst->if_module = UE->if_inst; + UE->if_inst->scheduled_response = nr_ue_scheduled_response; + UE->if_inst->phy_config_request = nr_ue_phy_config_request; + LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]); + //init_UE_threads(inst); + //UE = PHY_vars_UE_g[inst][0]; + AssertFatal(0 == pthread_create(&threads[inst], + &attr, + UE_thread, + (void *)UE), ""); + } + + printf("UE threads created by %ld\n", gettid()); +} + diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c new file mode 100644 index 0000000000000000000000000000000000000000..e6a97c8f287f1488e4bfcc75de544013cadeeb49 --- /dev/null +++ b/executables/nr-uesoftmodem.c @@ -0,0 +1,831 @@ +/* + * 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 + */ + + +#define _GNU_SOURCE /* See feature_test_macros(7) */ +#include <sched.h> + +#include "T.h" +#include "assertions.h" +#include "PHY/types.h" +#include "PHY/defs_nr_UE.h" +#include "common/ran_context.h" +#include "common/config/config_userapi.h" +#include "common/utils/load_module_shlib.h" +//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "../../ARCH/COMMON/common_lib.h" +#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h" + +//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all + +#include "PHY/phy_vars_nr_ue.h" +#include "PHY/LTE_TRANSPORT/transport_vars.h" +#include "SCHED/sched_common_vars.h" +#include "PHY/MODULATION/modulation_vars.h" +//#include "../../SIMU/USER/init_lte.h" + +#include "LAYER2/MAC/mac_vars.h" +#include "LAYER2/MAC/mac_proto.h" +#include "RRC/LTE/rrc_vars.h" +#include "PHY_INTERFACE/phy_interface_vars.h" + +#ifdef SMBV +#include "PHY/TOOLS/smbv.h" +unsigned short config_frames[4] = {2,9,11,13}; +#endif +#include "common/utils/LOG/log.h" +#include "common/utils/LOG/vcd_signal_dumper.h" + +#include "UTIL/OPT/opt.h" +#include "enb_config.h" +//#include "PHY/TOOLS/time_meas.h" + +#ifndef OPENAIR2 + #include "UTIL/OTG/otg_vars.h" +#endif + +#include "intertask_interface.h" +#include "create_tasks.h" + +#include "PHY/INIT/phy_init.h" +#include "system.h" +#include <openair2/RRC/NR_UE/rrc_proto.h> +#include <openair2/LAYER2/NR_MAC_UE/mac_defs.h> +#include <openair2/LAYER2/NR_MAC_UE/mac_proto.h> +#include <openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h> +#include <openair1/SCHED_NR_UE/fapi_nr_ue_l1.h> + +#ifdef XFORMS +#include <forms.h> + +/* Callbacks, globals and object handlers */ + +extern void reset_stats( FL_OBJECT *, long ); + +/* Forms and Objects */ + +typedef struct { + FL_FORM *stats_form; + void *vdata; + char *cdata; + long ldata; + FL_OBJECT *stats_text; + FL_OBJECT *stats_button; +} FD_stats_form; + +extern FD_stats_form *create_form_stats_form( void ); + +#include "PHY/TOOLS/nr_phy_scope.h" +//#include "stats.h" +// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) +// at eNB 0, an UL scope for every UE +FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX]; +//FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; +//FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; +char title[255]; +//unsigned char scope_enb_num_ue = 2; +static pthread_t forms_thread; //xforms +#endif //XFORMS +#include <executables/nr-uesoftmodem.h> + +RAN_CONTEXT_t RC; +volatile int start_eNB = 0; +volatile int start_UE = 0; +volatile int oai_exit = 0; + +static clock_source_t clock_source = internal; +int single_thread_flag=1; + +int threequarter_fs=0; + +uint32_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + +extern int16_t nr_dlsch_demod_shift; + +int UE_scan = 0; +int UE_scan_carrier = 0; +int UE_fo_compensation = 0; +runmode_t mode = normal_txrx; +openair0_config_t openair0_cfg[MAX_CARDS]; + +#if MAX_NUM_CCs == 1 +rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}}; +double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}}; +double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}}; +#else +rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}}; +double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}}; +double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; +#endif + +double rx_gain_off = 0.0; + +double sample_rate=30.72e6; +double bw = 10.0e6; + +static int tx_max_power[MAX_NUM_CCs] = {0}; + +char rf_config_file[1024]; + +int chain_offset=0; +int phy_test = 0; +uint8_t usim_test = 0; + +uint8_t dci_Format = 0; +uint8_t agregation_Level =0xFF; + +uint8_t nb_antenna_tx = 1; +uint8_t nb_antenna_rx = 1; + +char ref[128] = "internal"; +char channels[128] = "0"; + +char *parallel_config = NULL; +char *worker_config = NULL; + +static THREAD_STRUCT thread_struct; +void set_parallel_conf(char *parallel_conf) { + if(strcmp(parallel_conf,"PARALLEL_SINGLE_THREAD")==0) thread_struct.parallel_conf = PARALLEL_SINGLE_THREAD; + else if(strcmp(parallel_conf,"PARALLEL_RU_L1_SPLIT")==0) thread_struct.parallel_conf = PARALLEL_RU_L1_SPLIT; + else if(strcmp(parallel_conf,"PARALLEL_RU_L1_TRX_SPLIT")==0) thread_struct.parallel_conf = PARALLEL_RU_L1_TRX_SPLIT; + + printf("[CONFIG] parallel conf is set to %d\n",thread_struct.parallel_conf); +} +void set_worker_conf(char *worker_conf) { + if(strcmp(worker_conf,"WORKER_DISABLE")==0) thread_struct.worker_conf = WORKER_DISABLE; + else if(strcmp(worker_conf,"WORKER_ENABLE")==0) thread_struct.worker_conf = WORKER_ENABLE; + + printf("[CONFIG] worker conf is set to %d\n",thread_struct.worker_conf); +} +PARALLEL_CONF_t get_thread_parallel_conf(void) { + return thread_struct.parallel_conf; +} +WORKER_CONF_t get_thread_worker_conf(void) { + return thread_struct.worker_conf; +} +int rx_input_level_dBm; + +//static int online_log_messages=0; + +#ifdef XFORMS + extern int otg_enabled; + int do_forms=0; +#else + int otg_enabled; +#endif +//int number_of_cards = 1; + +static NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; +static nfapi_nr_config_request_t *config[MAX_NUM_CCs]; +int16_t node_synch_ref[MAX_NUM_CCs]; + +uint32_t target_dl_mcs = 28; //maximum allowed mcs +uint32_t target_ul_mcs = 20; +uint32_t timing_advance = 0; +uint8_t exit_missed_slots=1; +uint64_t num_missed_slots=0; // counter for the number of missed slots + + +int transmission_mode=1; +int numerology = 0; + +/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */ +//uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD; +/* struct for ethernet specific parameters given in eNB conf file */ +//eth_params_t *eth_params; + +double cpuf; + +char uecap_xer[1024],uecap_xer_in=0; + +int oaisim_flag=0; +int emulate_rf = 0; + +tpool_t *Tpool; + +char *usrp_args=NULL; +char *usrp_clksrc=NULL; + +/* forward declarations */ +void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); + + +/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed + * this is very hackish - find a proper solution + */ +uint8_t abstraction_flag=0; + +/*---------------------BMC: timespec helpers -----------------------------*/ + +struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; +struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + +struct timespec clock_difftime(struct timespec start, struct timespec end) { + struct timespec temp; + + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + + return temp; +} + +void print_difftimes(void) { + LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); +} + +void exit_function(const char *file, const char *function, const int line, const char *s) { + int CC_id; + + if (s != NULL) { + printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); + } + + oai_exit = 1; + + if (PHY_vars_UE_g && PHY_vars_UE_g[0]) { + for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + if (PHY_vars_UE_g[0][CC_id] && PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func) + PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); + } + } + + sleep(1); //allow lte-softmodem threads to exit first + itti_terminate_tasks (TASK_UNKNOWN); +} + +#ifdef XFORMS + + +void reset_stats(FL_OBJECT *button, long arg) { + //int i,j,k; + /*PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0]; + + for (i=0; i<NUMBER_OF_UE_MAX; i++) { + for (k=0; k<8; k++) { //harq_processes + for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) { + phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0; + phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0; + phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0; + } + + phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0; + phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0; + phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0; + + for (j=0; j<phy_vars_eNB->ulsch[i]->Mlimit; j++) { + phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0; + phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0; + } + } + + phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0; + phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0; + phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0; + }*/ +} + +static void *scope_thread(void *arg) { + struct sched_param sched_param; + sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; + sched_setscheduler(0, SCHED_FIFO,&sched_param); + printf("Scope thread has priority %d\n",sched_param.sched_priority); + //wait the modem is runnign + sleep(5); + + while (!oai_exit) { + phy_scope_UE(form_ue[0], + PHY_vars_UE_g[0][0], + 0,0,1); + usleep(100*1000); + } + + pthread_exit((void *)arg); +} +#endif + +void init_scope(void) { +#ifdef XFORMS + int ret; + int fl_argc=1; + + if (do_forms==1) { + char *name="5G-UE-scope"; + fl_initialize (&fl_argc, &name, NULL, 0, 0); + int UE_id = 0; + form_ue[UE_id] = create_lte_phy_scope_ue(); + sprintf (title, "NR DL SCOPE UE"); + fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + fl_set_button(form_ue[UE_id]->button_0,0); + fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); + ret = pthread_create(&forms_thread, NULL, scope_thread, NULL); + + if (ret == 0) + pthread_setname_np( forms_thread, "xforms" ); + + printf("Scope thread created, ret=%d\n",ret); + } + +#endif +} + + +#if defined(ENABLE_ITTI) +void *l2l1_task(void *arg) { + MessageDef *message_p = NULL; + int result; + itti_set_task_real_time(TASK_L2L1); + itti_mark_task_ready(TASK_L2L1); + + do { + // Wait for a message + itti_receive_msg (TASK_L2L1, &message_p); + + switch (ITTI_MSG_ID(message_p)) { + case TERMINATE_MESSAGE: + oai_exit=1; + itti_exit_task (); + break; + + case ACTIVATE_MESSAGE: + start_UE = 1; + break; + + case DEACTIVATE_MESSAGE: + start_UE = 0; + break; + + case MESSAGE_TEST: + LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); + break; + + default: + LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); + break; + } + + result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); + AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + } while(!oai_exit); + + return NULL; +} +#endif + +int16_t dlsch_demod_shift; + +static void get_options(void) { + int CC_id; + int tddflag=0, nonbiotflag; + char *loopfile=NULL; + int dumpframe=0; + uint32_t online_log_messages; + uint32_t glog_level, glog_verbosity; + uint32_t start_telnetsrv=0; + paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ; + paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ; + config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); + + if (strlen(in_path) > 0) { + opt_type = OPT_PCAP; + opt_enabled=1; + printf("Enabling OPT for PCAP with the following file %s \n",in_path); + } + + if (strlen(in_ip) > 0) { + opt_enabled=1; + opt_type = OPT_WIRESHARK; + printf("Enabling OPT for wireshark for local interface"); + } + + config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL); + + if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) { + set_glog_onlinelog(online_log_messages); + } + + if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) { + set_glog(glog_level); + } + + if (start_telnetsrv) { + load_module_shlib("telnetsrv",NULL,0,NULL); + } + + paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC; + paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC; + config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL); + config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL); + + if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue; + + if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med; + + if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags & PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp; + + if (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) + if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach; + + if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) + if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0) mode = no_L2_connect; + + if (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) + if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx; + + if (dumpframe > 0) mode = rx_dump_frame; + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0]; + } + + UE_scan=0; + + if (tddflag > 0) { + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) + frame_parms[CC_id]->frame_type = TDD; + } + + /*if (frame_parms[0]->N_RB_DL !=0) { + if ( frame_parms[0]->N_RB_DL < 6 ) { + frame_parms[0]->N_RB_DL = 6; + printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL); + } + if ( frame_parms[0]->N_RB_DL > 100 ) { + frame_parms[0]->N_RB_DL = 100; + printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL); + } + if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) { + frame_parms[0]->N_RB_DL = 50; + printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL); + } + if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) { + frame_parms[0]->N_RB_DL = 25; + printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL); + } + UE_scan = 0; + frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL; + for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) { + frame_parms[CC_id]->N_RB_DL=frame_parms[0]->N_RB_DL; + frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL; + } + }*/ + + for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) { + tx_max_power[CC_id]=tx_max_power[0]; + rx_gain[0][CC_id] = rx_gain[0][0]; + tx_gain[0][CC_id] = tx_gain[0][0]; + } + +#if T_TRACER + paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ; + config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL); +#endif + + if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) && (!(CONFIG_ISFLAGSET(CONFIG_NOOOPT))) ) { + // Here the configuration file is the XER encoded UE capabilities + // Read it in and store in asn1c data structures + sprintf(uecap_xer,"%stargets/PROJECTS/GENERIC-LTE-EPC/CONF/UE_config.xml",getenv("OPENAIR_HOME")); + printf("%s\n",uecap_xer); + uecap_xer_in=1; + } /* UE with config file */ +} + +#if T_TRACER + int T_nowait = 0; /* by default we wait for the tracer */ + int T_port = 2021; /* default port to listen to to wait for the tracer */ + int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */ +#endif + +void set_default_frame_parms(NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { + int CC_id; + + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + /* Set some default values that may be overwritten while reading options */ + frame_parms[CC_id] = (NR_DL_FRAME_PARMS *) calloc(sizeof(NR_DL_FRAME_PARMS),1); + config[CC_id] = (nfapi_nr_config_request_t *) calloc(sizeof(nfapi_nr_config_request_t),1); + config[CC_id]->subframe_config.numerology_index_mu.value =1; + config[CC_id]->subframe_config.duplex_mode.value = 1; //FDD + config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL + config[CC_id]->rf_config.dl_carrier_bandwidth.value = 106; + config[CC_id]->rf_config.ul_carrier_bandwidth.value = 106; + config[CC_id]->sch_config.physical_cell_id.value = 0; + + frame_parms[CC_id]->eutra_band = 78; + 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 = 106; + frame_parms[CC_id]->N_RB_UL = 106; + 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 = 1;//n_DMRS1 set to 0 + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1; + 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]->pusch_config_common.n_SB = 1; + frame_parms[CC_id]->pusch_config_common.hoppingMode = 0; + frame_parms[CC_id]->pusch_config_common.pusch_HoppingOffset = 0; + frame_parms[CC_id]->pusch_config_common.enable64QAM = 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;*/ + // NR: Init to legacy LTE 20Mhz params + frame_parms[CC_id]->numerology_index = 0; + frame_parms[CC_id]->ttis_per_subframe = 1; + frame_parms[CC_id]->slots_per_tti = 2; + } +} + +void init_openair0(void) { + int card; + int i; + + for (card=0; card<MAX_CARDS; card++) { + openair0_cfg[card].configFilename = NULL; + + if(frame_parms[0]->N_RB_DL == 106) { + if (numerology==0) { + if (frame_parms[0]->threequarter_fs) { + openair0_cfg[card].sample_rate=23.04e6; + openair0_cfg[card].samples_per_frame = 230400; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } else { + openair0_cfg[card].sample_rate=30.72e6; + openair0_cfg[card].samples_per_frame = 307200; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } + } else if (numerology==1) { + openair0_cfg[card].sample_rate=61.44e6; + openair0_cfg[card].samples_per_frame = 307200; + openair0_cfg[card].tx_bw = 20e6; + openair0_cfg[card].rx_bw = 20e6; + } else if (numerology==2) { + openair0_cfg[card].sample_rate=122.88e6; + openair0_cfg[card].samples_per_frame = 307200; + openair0_cfg[card].tx_bw = 40e6; + openair0_cfg[card].rx_bw = 40e6; + } else { + LOG_E(PHY,"Unsupported numerology!\n"); + exit(-1); + } + } else if(frame_parms[0]->N_RB_DL == 50) { + openair0_cfg[card].sample_rate=15.36e6; + openair0_cfg[card].samples_per_frame = 153600; + openair0_cfg[card].tx_bw = 5e6; + openair0_cfg[card].rx_bw = 5e6; + } else if (frame_parms[0]->N_RB_DL == 25) { + openair0_cfg[card].sample_rate=7.68e6; + openair0_cfg[card].samples_per_frame = 76800; + openair0_cfg[card].tx_bw = 2.5e6; + openair0_cfg[card].rx_bw = 2.5e6; + } else if (frame_parms[0]->N_RB_DL == 6) { + openair0_cfg[card].sample_rate=1.92e6; + openair0_cfg[card].samples_per_frame = 19200; + openair0_cfg[card].tx_bw = 1.5e6; + openair0_cfg[card].rx_bw = 1.5e6; + } + + if (frame_parms[0]->frame_type==TDD) + openair0_cfg[card].duplex_mode = duplex_mode_TDD; + else //FDD + openair0_cfg[card].duplex_mode = duplex_mode_FDD; + + printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, + PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx, + PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); + openair0_cfg[card].Mod_id = 0; + openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; + openair0_cfg[card].clock_source = clock_source; + openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx); + openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); + + for (i=0; i<4; i++) { + if (i<openair0_cfg[card].tx_num_channels) + openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i]; + else + openair0_cfg[card].tx_freq[i]=0.0; + + if (i<openair0_cfg[card].rx_num_channels) + openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i]; + else + openair0_cfg[card].rx_freq[i]=0.0; + + openair0_cfg[card].autocal[i] = 1; + openair0_cfg[card].tx_gain[i] = tx_gain[0][i]; + openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off; + openair0_cfg[card].configFilename = rf_config_file; + printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n", + card,i, openair0_cfg[card].tx_gain[i], + openair0_cfg[card].rx_gain[i], + openair0_cfg[card].tx_freq[i], + openair0_cfg[card].rx_freq[i]); + } + + if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args; + + if (usrp_clksrc) { + if (strcmp(usrp_clksrc, "internal") == 0) { + openair0_cfg[card].clock_source = internal; + LOG_D(PHY, "USRP clock source set as internal\n"); + } else if (strcmp(usrp_clksrc, "external") == 0) { + openair0_cfg[card].clock_source = external; + LOG_D(PHY, "USRP clock source set as external\n"); + } else if (strcmp(usrp_clksrc, "gpsdo") == 0) { + openair0_cfg[card].clock_source = gpsdo; + LOG_D(PHY, "USRP clock source set as gpsdo\n"); + } else { + openair0_cfg[card].clock_source = internal; + LOG_I(PHY, "USRP clock source unknown ('%s'). defaulting to internal\n", usrp_clksrc); + } + } else { + openair0_cfg[card].clock_source = internal; + LOG_I(PHY, "USRP clock source not specified. defaulting to internal\n"); + } + } +} + + +int main( int argc, char **argv ) { + //uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; + PHY_VARS_NR_UE *UE[MAX_NUM_CCs]; + start_background_system(); + + if ( load_configmodule(argc,argv) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + set_default_frame_parms(frame_parms); + mode = normal_txrx; + memset(openair0_cfg,0,sizeof(openair0_config_t)*MAX_CARDS); + memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); + // initialize logging + logInit(); + // get options and fill parameters from configuration file + get_options (); //Command-line options, enb_properties +#if T_TRACER + T_Config_Init(); +#endif + //randominit (0); + set_taus_seed (0); + tpool_t pool; + Tpool = &pool; + char params[]="-1,-1,-1,-1"; + initTpool(params, Tpool, false); + cpuf=get_cpu_freq_GHz(); + itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + + if (opt_type != OPT_NONE) { + if (init_opt(in_path, in_ip) == -1) + LOG_E(OPT,"failed to run OPT \n"); + } + +#ifdef PDCP_USE_NETLINK + netlink_init(); +#if defined(PDCP_USE_NETLINK_QUEUES) + pdcp_netlink_init(); +#endif +#endif +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + + // init the parameters + for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx; + frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx; + frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later + LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx); + + get_band(downlink_frequency[CC_id][0], &frame_parms[CC_id]->eutra_band, &uplink_frequency_offset[CC_id][0], &frame_parms[CC_id]->frame_type); + + } + + NB_UE_INST=1; + NB_INST=1; + PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE **)); + PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE *)*MAX_NUM_CCs); + + for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + printf("frame_parms %d\n",frame_parms[CC_id]->ofdm_symbol_size); + nr_init_frame_parms_ue(frame_parms[CC_id],numerology,NORMAL,frame_parms[CC_id]->N_RB_DL,(frame_parms[CC_id]->N_RB_DL-20)>>1,0); + PHY_vars_UE_g[0][CC_id] = init_nr_ue_vars(frame_parms[CC_id], 0,abstraction_flag); + UE[CC_id] = PHY_vars_UE_g[0][CC_id]; + + if (phy_test==1) + UE[CC_id]->mac_enabled = 0; + else + UE[CC_id]->mac_enabled = 1; + + if (UE[CC_id]->mac_enabled == 0) { //set default UL parameters for testing mode + for (int i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) { + //UE[CC_id]->pusch_config_dedicated[i] = malloc(sizeof(PUSCH_CONFIG_DEDICATED)); + //UE[CC_id]->scheduling_request_config[i] = malloc(sizeof(SCHEDULING_REQUEST_CONFIG)); + /*UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; + UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; + UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; + + UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0; + UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3); + UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;*/ + } + } + + UE[CC_id]->UE_scan = UE_scan; + UE[CC_id]->UE_scan_carrier = UE_scan_carrier; + UE[CC_id]->UE_fo_compensation = UE_fo_compensation; + UE[CC_id]->mode = mode; + printf("UE[%d]->mode = %d\n",CC_id,mode); + + for (uint8_t i=0; i<RX_NB_TH_MAX; i++) { + if (UE[CC_id]->mac_enabled == 1) + UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1234; + else + UE[CC_id]->pdcch_vars[i][0]->crnti = 0x1235; + } + + UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; + UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; + + if (frame_parms[CC_id]->frame_type==FDD) { + UE[CC_id]->N_TA_offset = 0; + } else { + if (frame_parms[CC_id]->N_RB_DL == 100) + UE[CC_id]->N_TA_offset = 624; + else if (frame_parms[CC_id]->N_RB_DL == 50) + UE[CC_id]->N_TA_offset = 624/2; + else if (frame_parms[CC_id]->N_RB_DL == 25) + UE[CC_id]->N_TA_offset = 624/4; + } + } + + // printf("tx_max_power = %d -> amp %d\n",tx_max_power[0],get_tx_amp(tx_max_poHwer,tx_max_power)); + init_openair0(); + // 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)*NUMBER_OF_UE_MAX*MAX_NUM_CCs); + mlockall(MCL_CURRENT | MCL_FUTURE); + init_scope(); + number_of_cards = 1; + + for(int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { + PHY_vars_UE_g[0][CC_id]->rf_map.card=0; + PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; +#if defined(OAI_USRP) || defined(OAI_ADRV9371_ZC706) + PHY_vars_UE_g[0][CC_id]->hw_timing_advance = timing_advance; +#else + PHY_vars_UE_g[0][CC_id]->hw_timing_advance = 160; +#endif + } + + // wait for end of program + printf("TYPE <CTRL-C> TO TERMINATE\n"); + init_UE(1); + + while(true) + sleep(3600); + + return 0; +} diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h new file mode 100644 index 0000000000000000000000000000000000000000..df6b2f7282ad4ebd8664892260a8da7dd35a641d --- /dev/null +++ b/executables/nr-uesoftmodem.h @@ -0,0 +1,246 @@ +#ifndef NR_UESOFTMODEM_H +#define NR_UESOFTMODEM_H + +#define _GNU_SOURCE +#include <execinfo.h> +#include <fcntl.h> +#include <getopt.h> +#include <linux/sched.h> +#include <sched.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syscall.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/sysinfo.h> +#include <sys/types.h> +#include <unistd.h> + +#include <sys/sysinfo.h> +#include "../../ARCH/COMMON/common_lib.h" +#undef MALLOC +#include "assertions.h" +#include "PHY/types.h" +#include "PHY/defs_nr_UE.h" +#include "SIMULATION/ETH_TRANSPORT/proto.h" +#include <threadPool/thread-pool.h> + + +#if defined(ENABLE_ITTI) + #if defined(ENABLE_USE_MME) + #include "s1ap_eNB.h" + #ifdef PDCP_USE_NETLINK + #include "SIMULATION/ETH_TRANSPORT/proto.h" + #endif + #endif +#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_ULMAXE "set the eNodeB max ULSCH erros\n" +#define CONFIG_HLP_CALUER "set UE RX calibration\n" +#define CONFIG_HLP_CALUERM "" +#define CONFIG_HLP_CALUERB "" +#define CONFIG_HLP_DBGUEPR "UE run normal prach power ramping, but don't continue random-access\n" +#define CONFIG_HLP_CALPRACH "UE run normal prach with maximum power, but don't continue random-access\n" +#define CONFIG_HLP_NOL2CN "bypass L2 and upper layers\n" +#define CONFIG_HLP_UERXG "set UE RX gain\n" +#define CONFIG_HLP_UERXGOFF "external UE amplifier offset\n" +#define CONFIG_HLP_UETXG "set UE TX gain\n" +#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n" +#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n" +#define CONFIG_HLP_UESCAN "set UE to scan around carrier\n" +#define CONFIG_HLP_UEFO "set UE to enable estimation and compensation of frequency offset\n" +#define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n" +#define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n" +#define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n" +#define CONFIG_HLP_PHYTST "test UE phy layer, mac disabled\n" +#define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n" +#define CONFIG_HLP_EXCCLK "tells hardware to use an external clock reference\n" +#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n" +#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" +#define CONFIG_HLP_TADV "Set timing_advance\n" +#define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" +#define CONFIG_HLP_CHOFF "Channel id offset\n" +#define CONFIG_HLP_SOFTS "Enable soft scope and L1 and L2 stats (Xforms)\n" +#define CONFIG_HLP_EXMCAL "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n" +#define CONFIG_HLP_ITTIL "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n" +#define CONFIG_HLP_DLMCS "Set the maximum downlink MCS\n" +#define CONFIG_HLP_STMON "Enable processing timing measurement of lte softmodem on per subframe basis \n" +#define CONFIG_HLP_PRB "Set the PRB, valid values: 6, 25, 50, 100 \n" +#define CONFIG_HLP_MSLOTS "Skip the missed slots/subframes \n" +#define CONFIG_HLP_ULMCS "Set the maximum uplink MCS\n" +#define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" +#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n" +#define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n" +#define CONFIG_HLP_L2MONP "Enable L2 pcap messages on localhost \n" +#define CONFIG_HLP_VCD "Enable VCD (generated file will is named openair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n" +#define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n" +#define CONFIG_HLP_TPORT "tracer port\n" +#define CONFIG_HLP_NOTWAIT "don't wait for tracer, start immediately\n" +#define CONFIG_HLP_TNOFORK "to ease debugging with gdb\n" + +#define CONFIG_HLP_NUMEROLOGY "adding numerology for 5G\n" +#define CONFIG_HLP_EMULATE_RF "Emulated RF enabled(disable by defult)\n" +#define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n" +#define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n" + +#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n" + +#define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n" +#define CONFIG_HLP_USRP_CLK_SRC "USRP clock source: 'internal' or 'external'\n" + +/***************************************************************************************************************************************/ +/* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument + when calling config_get or config_getlist functions */ + + +/*------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters defining UE running mode */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_UEMODEPARAMS_DESC { \ + {"calib-ue-rx", CONFIG_HLP_CALUER, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + {"calib-ue-rx-med", CONFIG_HLP_CALUERM, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + {"calib-ue-rx-byp", CONFIG_HLP_CALUERB, 0, iptr:&rx_input_level_dBm, defintval:0, TYPE_INT, 0}, \ + {"debug-ue-prach", CONFIG_HLP_DBGUEPR, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + {"no-L2-connect", CONFIG_HLP_NOL2CN, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + {"calib-prach-tx", CONFIG_HLP_CALPRACH, PARAMFLAG_BOOL, uptr:NULL, defuintval:1, TYPE_INT, 0}, \ + {"loop-memory", CONFIG_HLP_UELOOP, 0, strptr:&loopfile, defstrval:"iqs.in", TYPE_STRING,0}, \ + {"ue-dump-frame", CONFIG_HLP_DUMPFRAME, PARAMFLAG_BOOL, iptr:&dumpframe, defintval:0, TYPE_INT, 0}, \ + } +#define CMDLINE_CALIBUERX_IDX 0 +#define CMDLINE_CALIBUERXMED_IDX 1 +#define CMDLINE_CALIBUERXBYP_IDX 2 +#define CMDLINE_DEBUGUEPRACH_IDX 3 +#define CMDLINE_NOL2CONNECT_IDX 4 +#define CMDLINE_CALIBPRACHTX_IDX 5 +#define CMDLINE_MEMLOOP_IDX 6 +#define CMDLINE_DUMPMEMORY_IDX 7 +/*------------------------------------------------------------------------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters specific to UE */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*--------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_UEPARAMS_DESC { \ + {"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ + {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \ + {"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \ + {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&nb_antenna_rx, defuintval:1, TYPE_UINT8, 0}, \ + {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&nb_antenna_tx, defuintval:1, TYPE_UINT8, 0}, \ + {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&UE_scan_carrier, defintval:0, TYPE_INT, 0}, \ + {"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&UE_fo_compensation, defintval:0, TYPE_INT, 0}, \ + {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ + {"r" , CONFIG_HLP_PRB, 0, iptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT, 0}, \ + {"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ + {"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:(char **)&usrp_args, defstrval:"type=b200", TYPE_STRING, 0}, \ + {"usrp-clksrc", CONFIG_HLP_USRP_CLK_SRC,0, strptr:(char **)&usrp_clksrc, defstrval:"internal", TYPE_STRING, 0} \ + } + +#define DEFAULT_DLF 2680000000 + +/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters common to eNodeB and UE */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_PARAMS_DESC { \ + {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \ + {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ + {"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}, \ + {"external-clock", CONFIG_HLP_EXCCLK, PARAMFLAG_BOOL, uptr:&clock_source, defintval:0, TYPE_INT, 0}, \ + {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ + {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ + {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ + {"C" , CONFIG_HLP_DLF, 0, uptr:&(downlink_frequency[0][0]), defuintval:2680000000, TYPE_UINT, 0}, \ + {"a" , CONFIG_HLP_CHOFF, 0, iptr:&chain_offset, defintval:0, TYPE_INT, 0}, \ + {"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, iptr:&do_forms, defintval:0, TYPE_INT, 0}, \ + {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, iptr:&threequarter_fs, defintval:0, TYPE_INT, 0}, \ + {"m" , CONFIG_HLP_DLMCS, 0, uptr:&target_dl_mcs, defintval:0, TYPE_UINT, 0}, \ + {"t" , CONFIG_HLP_ULMCS, 0, uptr:&target_ul_mcs, defintval:0, TYPE_UINT, 0}, \ + {"W" , CONFIG_HLP_L2MONW, 0, strptr:(char **)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, sizeof(in_ip)}, \ + {"P" , CONFIG_HLP_L2MONP, 0, strptr:(char **)&in_path, defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, sizeof(in_path)}, \ + {"q" , CONFIG_HLP_STMON, PARAMFLAG_BOOL, iptr:&opp_enabled, defintval:0, TYPE_INT, 0}, \ + {"S" , CONFIG_HLP_MSLOTS, PARAMFLAG_BOOL, u8ptr:&exit_missed_slots, defintval:1, TYPE_UINT8, 0}, \ + {"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \ + {"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&numerology, defintval:0, TYPE_INT, 0}, \ + {"emulate-rf" , CONFIG_HLP_EMULATE_RF, PARAMFLAG_BOOL, iptr:&emulate_rf, defintval:0, TYPE_INT, 0}, \ + {"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)¶llel_config, defstrval:NULL, TYPE_STRING, 0}, \ + {"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \ + {"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, iptr:&nonbiotflag, defintval:0, TYPE_INT, 0} \ + } + +#define CONFIG_HLP_FLOG "Enable online log \n" +#define CONFIG_HLP_LOGL "Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n" +#define CONFIG_HLP_LOGV "Set the global log verbosity \n" +#define CONFIG_HLP_TELN "Start embedded telnet server \n" +/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* command line parameters for LOG utility */ +/* optname helpstr paramflags XXXptr defXXXval type numelt */ +/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +#define CMDLINE_LOGPARAMS_DESC { \ + {"R" , CONFIG_HLP_FLOG, 0, uptr:&online_log_messages, defintval:1, TYPE_INT, 0}, \ + {"g" , CONFIG_HLP_LOGL, 0, uptr:&glog_level, defintval:0, TYPE_UINT, 0}, \ + {"G" , CONFIG_HLP_LOGV, 0, uptr:&glog_verbosity, defintval:0, TYPE_UINT16, 0}, \ + {"telnetsrv", CONFIG_HLP_TELN, PARAMFLAG_BOOL, uptr:&start_telnetsrv, defintval:0, TYPE_UINT, 0}, \ + } +#define CMDLINE_ONLINELOG_IDX 0 +#define CMDLINE_GLOGLEVEL_IDX 1 +#define CMDLINE_GLOGVERBO_IDX 2 +#define CMDLINE_STARTTELN_IDX 3 + + +extern int T_port; +extern int T_nowait; +extern int T_dont_fork; + + + +/***************************************************************************************************************************************/ + +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; + + +extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; +extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; + +extern int rx_input_level_dBm; +extern uint8_t exit_missed_slots; +extern uint64_t num_missed_slots; // counter for the number of missed slots + +extern int oaisim_flag; +extern volatile int oai_exit; + +extern openair0_config_t openair0_cfg[MAX_CARDS]; +extern pthread_cond_t sync_cond; +extern pthread_mutex_t sync_mutex; +extern int sync_var; +extern int transmission_mode; +extern double cpuf; + +#if defined(ENABLE_ITTI) + extern volatile int start_eNB; + extern volatile int start_UE; +#endif + +// In nr-ue.c +extern int setup_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg); +extern void fill_ue_band_info(void); +extern void init_UE(int); +extern void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char *name); +extern void reset_opp_meas(void); +extern void print_opp_meas(void); +void *UE_thread(void *arg); +PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms, + uint8_t UE_id, + uint8_t abstraction_flag); +extern tpool_t *Tpool; +#endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index f1a3ef42abdb10a6b45277563ee7d141b4897bc4..f3cd1a29f30ce0f01425eed823ded7e3b553d0cf 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -52,9 +52,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, ncoef = 32767 - coef; -//#ifdef DEBUG_PHY - LOG_D(PHY,"AbsSubframe %d.%d: rx_offset (before) = %d\n",ue->proc.proc_rxtx[0].frame_rx%1024,subframe,ue->rx_offset); -//#endif //DEBUG_PHY + LOG_D(PHY,"AbsSubframe %d: rx_offset (before) = %d\n",subframe,ue->rx_offset); // we only use channel estimates from tx antenna 0 here @@ -122,8 +120,7 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, #ifdef DEBUG_PHY - LOG_D(PHY,"AbsSubframe %d.%d: ThreadId %d diff =%i rx_offset (final) = %i : clear %d,max_pos = %d,max_pos_fil = %d (peak %d) max_val %d target_pos %d \n", - ue->proc.proc_rxtx[ue->current_thread_id[subframe]].frame_rx, + LOG_D(PHY,"AbsSubframe %d: ThreadId %d diff =%i rx_offset (final) = %i : clear %d,max_pos = %d,max_pos_fil = %d (peak %d) max_val %d target_pos %d \n", subframe, ue->current_thread_id[subframe], diff, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 7cc6dde893f02584afe8b4e608c3d5639bf3b7aa..e56ccd8af750c0c985af2c65a3640ca7bc553b74 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -39,7 +39,7 @@ #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "SCHED_NR_UE/defs.h" #include "SIMULATION/TOOLS/sim.h" -#include "targets/RT/USER/nr-uesoftmodem.h" +#include "executables/nr-uesoftmodem.h" #include "PHY/CODING/nrLDPC_decoder/nrLDPC_decoder.h" #include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h" //#define DEBUG_DLSCH_DECODING diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index ca0aa50d0e87c3b6995982916e2e73082afdd34d..3a7af2e6bec519c4762f77f12b6f8a333f5cb4b6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -203,14 +203,14 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, #endif } else { - LOG_E(PHY,"[UE][FATAL] Frame %d nr_tti_rx %d: no active DLSCH\n",ue->proc.proc_rxtx[0].frame_rx,nr_tti_rx); + LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n",nr_tti_rx); return(-1); } beamforming_mode = ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id]; break; default: - LOG_E(PHY,"[UE][FATAL] Frame %d nr_tti_rx %d: Unknown PDSCH format %d\n",ue->proc.proc_rxtx[0].frame_rx,nr_tti_rx,type); + LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n",nr_tti_rx,type); return(-1); break; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 0e0676b97243270e66451080d8003e7433d699b2..40cbb0d23ef7813128c95f71147617228bac1f93 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -188,11 +188,6 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, int pbch_initial_symbol, runmode_t mod // ue->pbch_vars[0]->decoded_output[0] = ue->pbch_vars[0]->decoded_output[2]; // ue->pbch_vars[0]->decoded_output[2] = dummy; - for(int i=0; i<RX_NB_TH;i++) - { - - ue->proc.proc_rxtx[i].frame_tx = ue->proc.proc_rxtx[0].frame_rx; - } #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully\n",ue->Mod_id); #endif @@ -379,9 +374,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) if (ue->UE_scan_carrier == 0) { #if UE_AUTOTEST_TRACE - LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n", + LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : rx_offset %d, freq_offset %d \n", ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, ue->rx_offset, ue->common_vars.freq_offset ); #endif @@ -392,30 +386,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) } -#if DISABLE_LOG_X - printf("[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - 10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, - 10*log10(ue->measurements.rssi), - ue->rx_total_gain_dB, - ue->measurements.n0_power_tot_dBm, - 10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB, - (10*log10(ue->measurements.rsrq[0]))); - - - printf("[UE %d] Frame %d MIB Information => %s, %s, NidCell %d, N_RB_DL %d, PHICH DURATION %d, PHICH RESOURCE %s, TX_ANT %d\n", - ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - duplex_string[fp->frame_type], - prefix_string[fp->Ncp], - fp->Nid_cell, - fp->N_RB_DL, - fp->phich_config_common.phich_duration, - phich_string[fp->phich_config_common.phich_resource], - fp->nb_antenna_ports_eNB); -#else - LOG_I(PHY, "[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, + LOG_I(PHY, "[UE %d] RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm, rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id, 10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB, 10*log10(ue->measurements.rssi), ue->rx_total_gain_dB, @@ -433,22 +404,12 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) fp->phich_config_common.phich_duration, phich_string[fp->phich_config_common.phich_resource], fp->nb_antenna_ports_eNB);*/ -#endif #if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706) -# if DISABLE_LOG_X - printf("[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", + LOG_I(PHY, "[UE %d] Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset, - ue->common_vars.freq_offset); -# else - LOG_I(PHY, "[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", - ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset, ue->common_vars.freq_offset); -# endif #endif } else { #ifdef DEBUG_INITIAL_SYNC diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 020205094ea01245c65ef919fda0d4e00fcbabe7..f447c6895eda255d2fc4253dc481a427c2ae11a2 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -267,27 +267,6 @@ typedef struct { uint8_t CC_id; /// Last RX timestamp openair0_timestamp timestamp_rx; - /// pthread attributes for main UE thread - pthread_attr_t attr_ue; - /// scheduling parameters for main UE thread - struct sched_param sched_param_ue; - /// pthread descriptor main UE thread - pthread_t pthread_ue; - /// \brief Instance count for synch thread. - /// \internal This variable is protected by \ref mutex_synch. - int instance_cnt_synch; - /// pthread attributes for synch processing thread - pthread_attr_t attr_synch; - /// scheduling parameters for synch thread - struct sched_param sched_param_synch; - /// pthread descriptor synch thread - pthread_t pthread_synch; - /// condition variable for UE synch thread; - pthread_cond_t cond_synch; - /// mutex for UE synch thread - pthread_mutex_t mutex_synch; - /// set of scheduling variables RXn-TXnp4 threads - UE_nr_rxtx_proc_t proc_rxtx[RX_NB_TH]; } UE_nr_proc_t; typedef enum { diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index ca30ab1cec789a8f2fe05d2e3f39f9a82b13b72f..7c17987980053d2d7df7f001afdb185809c3a70d 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -232,7 +232,6 @@ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){ printf("half frame bit: %d\n", phy_config->config_req.pbch_config.half_frame_bit); printf("-------------------------------\n"); - PHY_vars_UE_g[0][0]->proc.proc_rxtx[0].frame_rx = phy_config->config_req.pbch_config.system_frame_number; } if(phy_config->config_req.config_mask & FAPI_NR_CONFIG_REQUEST_MASK_DL_BWP_COMMON){ diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index c9ea45f03bf0e53fe1d22be809ae34bf2fc49ffe..3b24814951d39e6e8be27e1eb4f8d30d523071f0 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -36,7 +36,7 @@ #include "PHY/defs_UE.h" #include "PHY/phy_extern_ue.h" #include <sched.h> -#include "targets/RT/USER/lte-softmodem.h" +#include "executables/nr-uesoftmodem.h" #include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h" #include "SCHED_UE/sched_UE.h" @@ -5116,13 +5116,13 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u if (msg_p != NULL) { switch (ITTI_MSG_ID(msg_p)) { case PHY_FIND_CELL_REQ: - LOG_I(PHY, "[UE %d] Received %s\n", ITTI_MSG_INSTANCE (msg_p) - NB_eNB_INST, ITTI_MSG_NAME (msg_p)); + LOG_I(PHY, "[UE ] Received %s\n", ITTI_MSG_NAME (msg_p)); /* TODO process the message */ break; default: - LOG_E(PHY, "[UE %d] Received unexpected message %s\n", ITTI_MSG_INSTANCE (msg_p) - NB_eNB_INST, ITTI_MSG_NAME (msg_p)); + LOG_E(PHY, "[UE %d] Received unexpected message %s\n", ITTI_MSG_INSTANCE (msg_p) , ITTI_MSG_NAME (msg_p)); break; } diff --git a/openair2/LAYER2/NR_MAC_UE/mac.h b/openair2/LAYER2/NR_MAC_UE/mac.h index d0b6d4730d182cb048e65e28e674d5c9146e1f9c..fe8e91500a441c3c0e71550103d14606ba64eed7 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac.h +++ b/openair2/LAYER2/NR_MAC_UE/mac.h @@ -43,10 +43,10 @@ /*!\brief UE layer 2 status */ typedef enum { - CONNECTION_OK = 0, - CONNECTION_LOST, - PHY_RESYNCH, - PHY_HO_PRACH + UE_CONNECTION_OK = 0, + UE_CONNECTION_LOST, + UE_PHY_RESYNCH, + UE_PHY_HO_PRACH } NR_UE_L2_STATE_t; typedef struct { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index f34000bc9834ba1abf80159c6665218d71962e04..23792337761a955c8699f3c92fb4949875ab67a3 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -30,8 +30,8 @@ * \warning */ -#ifndef __LAYER2_MAC_PROTO_H__ -#define __LAYER2_MAC_PROTO_H__ +#ifndef __LAYER2_MAC_UE_PROTO_H__ +#define __LAYER2_MAC_UE_PROTO_H__ #include "mac_defs.h" #include "mac.h" diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index e3dad2db706cc19fa8e3199cad4dd393530226ca..7110a35331597195cd6a3f01ae968dc32ee53e6a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -686,7 +686,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler( mac->scheduled_response.dl_config = dl_config; - return CONNECTION_OK; + return UE_CONNECTION_OK; } ////////////// diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 840cb5b4cca4d7dcf17415718f6c10f09cdea6cf..e391cc67b9964b739bf38f6618127eff88c2fe38 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -102,13 +102,13 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info){ 0, 0); // TODO check tx/rx frame/slot is need for NR version switch(ret){ - case CONNECTION_OK: + case UE_CONNECTION_OK: break; - case CONNECTION_LOST: + case UE_CONNECTION_LOST: break; - case PHY_RESYNCH: + case UE_PHY_RESYNCH: break; - case PHY_HO_PRACH: + case UE_PHY_HO_PRACH: break; default: break; diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 685a628b26e63436f609cecaabfd1d88acf0615f..d14b2457c942f61abf65e1e2b9b2d24d5535ebcb 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -424,7 +424,7 @@ extern "C" * \returns 0 in success */ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg); - +#define gettid() syscall(__NR_gettid) /*@}*/ #ifdef __cplusplus