Commit 59086151 authored by Laurent THOMAS's avatar Laurent THOMAS Committed by Robert Schmidt

Add generic usage-based gold cache

Add gold sequence cache with dynamic size, private to each thread. It
periodically reorders by call rate. To free the gold sequences after end
of life time of a thread, use the pthread API.
parent 9c1a8733
......@@ -1017,6 +1017,7 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_csi_rs.c
${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/refsig.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
)
......
......@@ -20,6 +20,7 @@
*/
#include "refsig_defs_ue.h"
#include "openair1/PHY/LTE_TRANSPORT/transport_proto.h" // for lte_gold_generic()
void nr_gold_pbch(uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD], int Nid, int Lmax)
{
......
......@@ -25,6 +25,7 @@
#define __NR_REFSIG__H__
#include "PHY/defs_gNB.h"
#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h"
#include "PHY/LTE_REFSIG/lte_refsig.h"
#include "PHY/sse_intrin.h"
......
/*
* 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
*/
/* Definitions for NR Reference signals */
#ifndef __NR_REFSIG_COMMON_H__
#define __NR_REFSIG_COMMON_H__
struct NR_DL_FRAME_PARMS;
typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS;
uint32_t *gold_cache(uint32_t key, int length);
#endif
/*
* 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
*/
#include "nr_refsig.h"
#include "openair1/PHY/LTE_TRANSPORT/transport_proto.h" // for lte_gold_generic()
#define REFRESH_RATE (1000 * 100)
typedef struct {
int key;
int length;
int usage;
} gold_cache_t;
typedef struct {
uint32_t *table;
uint32_t tblSz;
int calls;
int iterate;
} gold_cache_table_t;
static const int roundedHeaderSz = (((sizeof(gold_cache_t) + 63) / 64) * 64) / sizeof(uint32_t);
static const int grain = 64 / sizeof(uint32_t);
// Allocate, also reorder to have the most frequent first, so the cache search is optimized
static void refresh_table(gold_cache_table_t *t, int sizeIncrease)
{
uint32_t *old = t->table;
uint oldSz = t->tblSz;
if (t->tblSz == 0)
t->tblSz = PAGE_SIZE / sizeof(*t->table);
if (sizeIncrease)
t->tblSz += max(sizeIncrease, PAGE_SIZE / sizeof(*t->table));
int ret = posix_memalign((void **)&t->table, 64, t->tblSz * sizeof(*t->table));
AssertFatal(ret == 0, "No more memory");
LOG_D(PHY,
"re-organize gold sequence table to %lu pages of memory calls since last reorder: %d, search rate: %f\n",
t->tblSz * sizeof(*t->table) / PAGE_SIZE,
t->calls,
t->calls ? t->iterate / (float)t->calls : 0.0);
int maxUsage;
uint32_t *currentTmp = t->table;
do {
maxUsage = 0;
gold_cache_t *entryToCopy = NULL;
for (uint32_t *searchmax = old; searchmax < old + oldSz; searchmax += roundedHeaderSz) {
gold_cache_t *tbl = (gold_cache_t *)searchmax;
if (!tbl->length)
break;
if (tbl->usage > maxUsage) {
maxUsage = tbl->usage;
entryToCopy = tbl;
}
searchmax += tbl->length;
}
if (maxUsage) {
memcpy(currentTmp, entryToCopy, (roundedHeaderSz + entryToCopy->length) * sizeof(*t->table));
currentTmp += roundedHeaderSz + entryToCopy->length;
entryToCopy->usage = 0;
}
} while (maxUsage);
const uint usedSz = currentTmp - t->table;
memset(t->table + usedSz, 0, (t->tblSz - usedSz) * sizeof(*t->table));
free(old);
t->calls = 0;
t->iterate = 0;
return;
}
static pthread_key_t gold_table_key;
static pthread_once_t gold_key_once = PTHREAD_ONCE_INIT;
static void delete_table(void *ptr)
{
gold_cache_table_t *table = (gold_cache_table_t *)ptr;
if (table->table)
free(table->table);
free(ptr);
}
static void make_table_key()
{
(void)pthread_key_create(&gold_table_key, delete_table);
}
uint32_t *gold_cache(uint32_t key, int length)
{
(void)pthread_once(&gold_key_once, make_table_key);
gold_cache_table_t *tableCache;
if ((tableCache = pthread_getspecific(gold_table_key)) == NULL) {
tableCache = calloc(1, sizeof(gold_cache_table_t));
(void)pthread_setspecific(gold_table_key, tableCache);
}
// align for AVX512
length = ((length + grain - 1) / grain) * grain;
tableCache->calls++;
// periodic refresh
if (tableCache->calls > REFRESH_RATE)
refresh_table(tableCache, 0);
uint32_t *ptr = tableCache->table;
// check if already cached
for (; ptr < tableCache->table + tableCache->tblSz; ptr += roundedHeaderSz) {
gold_cache_t *tbl = (gold_cache_t *)ptr;
tableCache->iterate++;
if (tbl->length >= length && tbl->key == key) {
tbl->usage++;
return ptr + roundedHeaderSz;
}
if (tbl->key == key) {
// We use a longer sequence, same key
// let's delete the shorter and force reorganize
tbl->usage = 0;
tableCache->calls += REFRESH_RATE;
}
if (!tbl->length)
break;
ptr += tbl->length;
}
// not enough space in the table
if (!ptr || ptr > tableCache->table + tableCache->tblSz - (2 * roundedHeaderSz + length))
refresh_table(tableCache, 2 * roundedHeaderSz + length);
// We will add a new entry
uint32_t *firstFree;
int size = 0;
for (firstFree = tableCache->table; firstFree < tableCache->table + tableCache->tblSz; firstFree += roundedHeaderSz) {
gold_cache_t *tbl = (gold_cache_t *)firstFree;
if (!tbl->length)
break;
firstFree += tbl->length;
size++;
}
if (!tableCache->calls)
LOG_D(PHY, "Number of entries (after reorganization) in gold cache: %d\n", size);
gold_cache_t *new = (gold_cache_t *)firstFree;
*new = (gold_cache_t){.key = key, .length = length, .usage = 1};
unsigned int x1 = 0, x2 = key;
uint32_t *sequence = firstFree + roundedHeaderSz;
*sequence++ = lte_gold_generic(&x1, &x2, 1);
for (int n = 1; n < length; n++)
*sequence++ = lte_gold_generic(&x1, &x2, 0);
LOG_D(PHY, "created a gold sequence, start %d; len %d\n", key, length);
return firstFree + roundedHeaderSz;
}
......@@ -25,7 +25,7 @@
#define __NR_REFSIG_DEFS__H__
#include "PHY/defs_nr_UE.h"
#include "PHY/LTE_REFSIG/lte_refsig.h"
#include "nr_refsig_common.h"
/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS.
@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
......
......@@ -26,6 +26,7 @@
#include "PHY/NR_TRANSPORT/nr_ulsch.h"
#include "PHY/NR_TRANSPORT/nr_dci.h"
#include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
#include "PHY/NR_REFSIG/nr_refsig_common.h"
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
#include "fapi_nr_l1.h"
#include "common/utils/LOG/log.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment