Commit 320f896f authored by Matthieu Kanj's avatar Matthieu Kanj

code separation + creation of three new files:

openair1/PHY/CODING/lte_segmentation_NB_IoT.c
openair1/PHY/CODING/viterbi_lte_NB_IoT.c
openair1/PHY/LTE_TRANSPORT/lte_mcs_NB_IoT.c
parent a9089927
......@@ -1006,6 +1006,7 @@ set(PHY_SRC
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_NB_IoT.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/uci_tools.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs_NB_IoT.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pbch.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_NB_IoT.c
......@@ -1057,6 +1058,7 @@ set(PHY_SRC
${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_mbsfn.c
${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_ul_ref.c
${OPENAIR1_DIR}/PHY/CODING/lte_segmentation.c
${OPENAIR1_DIR}/PHY/CODING/lte_segmentation_NB_IoT.c
${OPENAIR1_DIR}/PHY/CODING/ccoding_byte.c
${OPENAIR1_DIR}/PHY/CODING/ccoding_byte_NB_IoT.c
${OPENAIR1_DIR}/PHY/CODING/ccoding_byte_lte.c
......@@ -1071,6 +1073,7 @@ set(PHY_SRC
${OPENAIR1_DIR}/PHY/CODING/rate_matching.c
${OPENAIR1_DIR}/PHY/CODING/viterbi.c
${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c
${OPENAIR1_DIR}/PHY/CODING/viterbi_lte_NB_IoT.c
${OPENAIR1_DIR}/PHY/INIT/lte_init.c
${OPENAIR1_DIR}/PHY/INIT/lte_init_NB_IoT.c
${OPENAIR1_DIR}/PHY/INIT/lte_parms.c
......
......@@ -172,6 +172,23 @@ unsigned int crc16_NB_IoT (unsigned char * inptr, int bitlen)
return crc;
}
unsigned int crc8_NB_IoT (unsigned char * inptr, int bitlen)
{
int octetlen, resbit;
unsigned int crc = 0;
octetlen = bitlen / 8; /* Change in octets */
resbit = (bitlen % 8);
while (octetlen-- > 0) {
crc = crc8Table_NB_IoT[(*inptr++) ^ (crc >> 24)] << 24;
}
if (resbit > 0)
crc = (crc << resbit) ^ (crc8Table_NB_IoT[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 24);
return crc;
}
//#ifdef DEBUG_CRC
/*******************************************************************/
......
......@@ -119,12 +119,93 @@ uint32_t crc24b_NB_IoT (uint8_t *inPtr, int32_t bitlen);
@param bitlen length of inputs in bits*/
uint32_t crc16_NB_IoT (uint8_t *inPtr, int32_t bitlen);
/*!\fn uint32_t crc8(uint8_t *inPtr, int32_t bitlen)
\brief This computes a 8-bit crc based on 3GPP UMTS specifications.
@param inPtr Pointer to input byte stream
@param bitlen length of inputs in bits*/
uint32_t crc8_NB_IoT (uint8_t *inPtr, int32_t bitlen);
uint32_t crcbit_NB_IoT (uint8_t * ,
int32_t,
uint32_t);
/*!\fn void phy_viterbi_lte_sse2(int8_t *y, uint8_t *decoded_bytes, uint16_t n)
\brief This routine performs a SIMD optmized Viterbi decoder for the LTE 64-state tail-biting convolutional code.
@param y Pointer to soft input (coded on 8-bits but should be limited to 4-bit precision to avoid overflow)
@param decoded_bytes Pointer to decoded output
@param n Length of input/trellis depth in bits*/
//void phy_viterbi_lte_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n);
void phy_viterbi_lte_sse2_NB_IoT(int8_t *y,uint8_t *decoded_bytes,uint16_t n);
/** \fn void sub_block_deinterleaving_cc(uint32_t D, int8_t *d,int8_t *w)
\brief This is the subblock deinterleaving algorithm for convolutionally-coded data from 36-212 (Release 8, 8.6 2009-03), pages 15-16.
This function takes the w-sequence and generates the d-sequence. The nu-sequence from 36-212 is implicit.
\param D Number of input bits
\param d Pointer to output (d-sequence, turbo code output)
\param w Pointer to input (w-sequence, interleaver output)
*/
void sub_block_deinterleaving_cc_NB_IoT(uint32_t D,int8_t *d,int8_t *w);
/*
\brief This is the LTE rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI). It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 )
\param RCC R^CC_subblock from subblock interleaver (number of rows in interleaving matrix)
\param E This the number of coded bits allocated for channel
\param w This is a pointer to the soft w-sequence (second interleaver output) with soft-combined outputs from successive HARQ rounds
\param dummy_w This is the first row of the interleaver matrix for identifying/discarding the "LTE-NULL" positions
\param soft_input This is a pointer to the soft channel output
\returns \f$E\f$, the number of coded bits per segment
*/
void lte_rate_matching_cc_rx_NB_IoT(uint32_t RCC,
uint16_t E,
int8_t *w,
uint8_t *dummy_w,
int8_t *soft_input);
/** \fn generate_dummy_w_cc(uint32_t D, uint8_t *w)
\brief This function generates a dummy interleaved sequence (first row) for receiver (convolutionally-coded data), in order to identify the NULL positions used to make the matrix complete.
\param D Number of systematic bits plus 4 (plus 4 for termination)
\param w This is the dummy sequence (first row), it will contain zeros and at most 31 "LTE_NULL" values
\returns Interleaving matrix cardinality (\f$K_{\pi}\f$ from 36-212)
*/
uint32_t generate_dummy_w_cc_NB_IoT(uint32_t D, uint8_t *w);
/** \fn lte_segmentation(uint8_t *input_buffer,
uint8_t **output_buffers,
uint32_t B,
uint32_t *C,
uint32_t *Cplus,
uint32_t *Cminus,
uint32_t *Kplus,
uint32_t *Kminus,
uint32_t *F)
\brief This function implements the LTE transport block segmentation algorithm from 36-212, V8.6 2009-03.
@param input_buffer
@param output_buffers
@param B
@param C
@param Cplus
@param Cminus
@param Kplus
@param Kminus
@param F
*/
int32_t lte_segmentation_NB_IoT(uint8_t *input_buffer,
uint8_t **output_buffers,
uint32_t B,
uint32_t *C,
uint32_t *Cplus,
uint32_t *Cminus,
uint32_t *Kplus,
uint32_t *Kminus,
uint32_t *F);
/** \fn void sub_block_deinterleaving_turbo(uint32_t D, int16_t *d,int16_t *w)
\brief This is the subblock deinterleaving algorithm from 36-212 (Release 8, 8.6 2009-03), pages 15-16.
This function takes the w-sequence and generates the d-sequence. The nu-sequence from 36-212 is implicit.
......
......@@ -18,7 +18,9 @@
#include <stdlib.h>
#endif
*/
#include "PHY/CODING/defs_NB_IoT.h"
//#include "PHY/CODING/defs_NB_IoT.h"
#include "PHY/defs_NB_IoT.h"
//#include "assertions.h"
//#include "PHY/LTE_REFSIG/defs_NB_IoT.h" // does this file is needed ?
......@@ -86,3 +88,136 @@ uint32_t lte_rate_matching_cc_NB_IoT(uint32_t RCC, // RRC = 2
return(E);
}
//******************* below functions related to uplink transmission , to be reviwed *********
// this function should be adapted to NB-IoT , this deinterleaving is for LTE
void sub_block_deinterleaving_cc_NB_IoT(uint32_t D,int8_t *d,int8_t *w)
{
//WANG_Hao uint32_t RCC = (D>>5), ND, ND3;
uint32_t RCC = (D>>5);
ptrdiff_t ND, ND3;
uint32_t row,col,Kpi,index;
//WANG_Hao uint32_t index3,k;
ptrdiff_t index3;
uint32_t k;
if ((D&0x1f) > 0)
RCC++;
Kpi = (RCC<<5);
// Kpi3 = Kpi*3;
ND = Kpi - D;
ND3 = ND*3;
k=0;
for (col=0; col<32; col++) {
index = bitrev_cc_NB_IoT[col];
index3 = 3*index;
for (row=0; row<RCC; row++) {
d[index3-ND3] = w[k];
d[index3-ND3+1] = w[Kpi+k];
d[index3-ND3+2] = w[(Kpi<<1)+k];
index3+=96;
index+=32;
k++;
}
}
}
void lte_rate_matching_cc_rx_NB_IoT(uint32_t RCC,
uint16_t E,
int8_t *w,
uint8_t *dummy_w,
int8_t *soft_input)
{
uint32_t ind=0,k;
uint16_t Kw = 3*(RCC<<5);
uint32_t acc=1;
int16_t w16[Kw];
memset(w,0,Kw);
memset(w16,0,Kw*sizeof(int16_t));
for (k=0; k<E; k++) {
while(dummy_w[ind] == LTE_NULL_NB_IoT) {
ind++;
if (ind==Kw)
ind=0;
}
w16[ind] += soft_input[k];
ind++;
if (ind==Kw) {
ind=0;
acc++;
}
}
// rescale
for (ind=0; ind<Kw; ind++) {
// w16[ind]=(w16[ind]/acc);
if (w16[ind]>7)
w[ind]=7;
else if (w16[ind]<-8)
w[ind]=-8;
else
w[ind]=(int8_t)w16[ind];
}
}
uint32_t generate_dummy_w_cc_NB_IoT(uint32_t D, uint8_t *w)
{
uint32_t RCC = (D>>5), ND;
uint32_t col,Kpi,index;
int32_t k;
if ((D&0x1f) > 0)
RCC++;
Kpi = (RCC<<5);
// Kpi3 = Kpi*3;
ND = Kpi - D;
// copy d02 to dD2 (for mod Kpi operation from clause (4), p.16 of 36.212
k=0;
for (col=0; col<32; col++) {
index = bitrev_cc_NB_IoT[col];
if (index<ND) {
w[k] = LTE_NULL_NB_IoT;
w[Kpi+k] = LTE_NULL_NB_IoT;
w[(Kpi<<1)+k] = LTE_NULL_NB_IoT;
}
k+=RCC;
}
return(RCC);
}
/*
* 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
*/
/* file: lte_segmentation.c
purpose: Procedures for transport block segmentation for LTE (turbo-coded transport channels)
author: raymond.knopp@eurecom.fr
date: 21.10.2009
*/
#include "PHY/defs_NB_IoT.h"
#include "SCHED/extern_NB_IoT.h"
//#define DEBUG_SEGMENTATION
int lte_segmentation_NB_IoT(unsigned char *input_buffer,
unsigned char **output_buffers,
unsigned int B,
unsigned int *C,
unsigned int *Cplus,
unsigned int *Cminus,
unsigned int *Kplus,
unsigned int *Kminus,
unsigned int *F)
{
unsigned int L,Bprime,Bprime_by_C,r,Kr,k,s,crc;
if (B<=6144) {
L=0;
*C=1;
Bprime=B;
} else {
L=24;
*C = B/(6144-L);
if ((6144-L)*(*C) < B)
*C=*C+1;
Bprime = B+((*C)*L);
}
if ((*C)>MAX_NUM_DLSCH_SEGMENTS_NB_IoT) {
LOG_E(PHY,"lte_segmentation.c: too many segments %d, B %d, L %d, Bprime %d\n",*C,B,L,Bprime);
return(-1);
}
// Find K+
Bprime_by_C = Bprime/(*C);
if (Bprime_by_C <= 40) {
*Kplus = 40;
*Kminus = 0;
} else if (Bprime_by_C<=512) { // increase by 1 byte til here
*Kplus = (Bprime_by_C>>3)<<3;
*Kminus = Bprime_by_C-8;
} else if (Bprime_by_C <=1024) { // increase by 2 bytes til here
*Kplus = (Bprime_by_C>>4)<<4;
if (*Kplus < Bprime_by_C)
*Kplus = *Kplus + 16;
*Kminus = (*Kplus - 16);
} else if (Bprime_by_C <= 2048) { // increase by 4 bytes til here
*Kplus = (Bprime_by_C>>5)<<5;
if (*Kplus < Bprime_by_C)
*Kplus = *Kplus + 32;
*Kminus = (*Kplus - 32);
} else if (Bprime_by_C <=6144 ) { // increase by 8 bytes til here
*Kplus = (Bprime_by_C>>6)<<6;
if (*Kplus < Bprime_by_C)
*Kplus = *Kplus + 64;
*Kminus = (*Kplus - 64);
} else {
msg("lte_segmentation.c: Illegal codeword size !!!\n");
return(-1);
}
if (*C == 1) {
*Cplus = *C;
*Kminus = 0;
*Cminus = 0;
} else {
// printf("More than one segment (%d), exiting \n",*C);
// exit(-1);
*Cminus = ((*C)*(*Kplus) - (Bprime))/((*Kplus) - (*Kminus));
*Cplus = (*C) - (*Cminus);
}
*F = ((*Cplus)*(*Kplus) + (*Cminus)*(*Kminus) - (Bprime));
if ((input_buffer) && (output_buffers)) {
for (k=0; k<*F>>3; k++) {
output_buffers[0][k] = 0;
}
s=0;
for (r=0; r<*C; r++) {
if (r<*Cminus)
Kr = *Kminus;
else
Kr = *Kplus;
while (k<((Kr - L)>>3)) {
output_buffers[r][k] = input_buffer[s];
// printf("encoding segment %d : byte %d (%d) => %d\n",r,k,Kr>>3,input_buffer[s]);
k++;
s++;
}
if (*C > 1) { // add CRC
crc = crc24b_NB_IoT(output_buffers[r],Kr-24)>>8;
output_buffers[r][(Kr-24)>>3] = ((uint8_t*)&crc)[2];
output_buffers[r][1+((Kr-24)>>3)] = ((uint8_t*)&crc)[1];
output_buffers[r][2+((Kr-24)>>3)] = ((uint8_t*)&crc)[0];
}
k=0;
}
}
return(0);
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.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
*/
/* file: viterbit_lte.c
purpose: SIMD optimized LTE Viterbi Decoder for rate 1/3 Tail-biting convolutional code. Performs two iterations
of code. First pass does Viterbi with all initial partial metrics set to zero. Second pass does Viterbi
with initial partial metrics set to values from final state values after first pass. Max is selected at
end to do trace-back.
author: raymond.knopp@eurecom.fr
date: 21.10.2009
*/
#ifdef USER_MODE
#include <stdio.h>
#endif
#ifndef TEST_DEBUG
#include "PHY/defs.h"
#include "PHY/extern.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define msg printf
#endif
#include "PHY/sse_intrin.h"
//extern uint8_t ccodelte_table[128],ccodelte_table_rev[128];
static int8_t m0_table[64*16*16*16] __attribute__ ((aligned(16)));
static int8_t m1_table[64*16*16*16] __attribute__ ((aligned(16)));
void phy_viterbi_lte_sse2_NB_IoT(int8_t *y,uint8_t *decoded_bytes,uint16_t n)
{
#if defined(__x86_64__) || defined(__i386__)
__m128i TB[4*8192];
__m128i *m0_ptr,*m1_ptr,*TB_ptr = &TB[0];
__m128i metrics0_15,metrics16_31,metrics32_47,metrics48_63,even0_30a,even0_30b,even32_62a,even32_62b,odd1_31a,odd1_31b,odd33_63a,odd33_63b,TBeven0_30,TBeven32_62,TBodd1_31,
TBodd33_63;
__m128i min_state,min_state2;
#elif defined(__arm__)
uint8x16x2_t TB[2*8192]; // 2 int8x16_t per input bit, 8 bits / byte, 8192 is largest packet size in bits
uint8x16_t even0_30a,even0_30b,even32_62a,even32_62b,odd1_31a,odd1_31b,odd33_63a,odd33_63b,TBeven0_30,TBeven32_62,TBodd1_31,TBodd33_63;
uint8x16x2_t metrics0_31,metrics32_63;
uint8x16_t min_state;
uint8x16_t *m0_ptr,*m1_ptr;
uint8x16x2_t *TB_ptr = &TB[0];
#endif
int8_t *in = y;
uint8_t prev_state0,maxm,s;
static uint8_t *TB_ptr2;
uint32_t table_offset;
uint8_t iter;
int16_t position;
// set initial metrics
//debug_msg("Doing viterbi\n");
#if defined(__x86_64__) || defined(__i386__)
metrics0_15 = _mm_setzero_si128();
metrics16_31 = _mm_setzero_si128();
metrics32_47 = _mm_setzero_si128();
metrics48_63 = _mm_setzero_si128();
#elif defined(__arm__)
metrics0_31.val[0] = vdupq_n_u8(0);
metrics0_31.val[1] = vdupq_n_u8(0);
metrics32_63.val[0] = vdupq_n_u8(0);
metrics32_63.val[1] = vdupq_n_u8(0);
#endif
for (iter=0; iter<2; iter++) {
in = y;
TB_ptr=&TB[0];
for (position=0; position<n; position++) {
// get branch metric offsets for the 64 states
table_offset = (in[0]+8 + ((in[1]+8)<<4) + ((in[2]+8)<<8))<<6;
#if defined(__x86_64__) || defined(__i386__)
m0_ptr = (__m128i *)&m0_table[table_offset];
m1_ptr = (__m128i *)&m1_table[table_offset];
// even states
even0_30a = _mm_adds_epu8(metrics0_15,m0_ptr[0]);
even32_62a = _mm_adds_epu8(metrics16_31,m0_ptr[1]);
even0_30b = _mm_adds_epu8(metrics32_47,m0_ptr[2]);
even32_62b = _mm_adds_epu8(metrics48_63,m0_ptr[3]);
// odd states
odd1_31a = _mm_adds_epu8(metrics0_15,m1_ptr[0]);
odd33_63a = _mm_adds_epu8(metrics16_31,m1_ptr[1]);
odd1_31b = _mm_adds_epu8(metrics32_47,m1_ptr[2]);
odd33_63b = _mm_adds_epu8(metrics48_63,m1_ptr[3]);
// select maxima
even0_30a = _mm_max_epu8(even0_30a,even0_30b);
even32_62a = _mm_max_epu8(even32_62a,even32_62b);
odd1_31a = _mm_max_epu8(odd1_31a,odd1_31b);
odd33_63a = _mm_max_epu8(odd33_63a,odd33_63b);
// Traceback information
TBeven0_30 = _mm_cmpeq_epi8(even0_30a,even0_30b);
TBeven32_62 = _mm_cmpeq_epi8(even32_62a,even32_62b);
TBodd1_31 = _mm_cmpeq_epi8(odd1_31a,odd1_31b);
TBodd33_63 = _mm_cmpeq_epi8(odd33_63a,odd33_63b);
metrics0_15 = _mm_unpacklo_epi8(even0_30a ,odd1_31a);
metrics16_31 = _mm_unpackhi_epi8(even0_30a ,odd1_31a);
metrics32_47 = _mm_unpacklo_epi8(even32_62a,odd33_63a);
metrics48_63 = _mm_unpackhi_epi8(even32_62a,odd33_63a);
TB_ptr[0] = _mm_unpacklo_epi8(TBeven0_30,TBodd1_31);
TB_ptr[1] = _mm_unpackhi_epi8(TBeven0_30,TBodd1_31);
TB_ptr[2] = _mm_unpacklo_epi8(TBeven32_62,TBodd33_63);
TB_ptr[3] = _mm_unpackhi_epi8(TBeven32_62,TBodd33_63);
in+=3;
TB_ptr += 4;
// rescale by subtracting minimum
/****************************************************
USE SSSE instruction phminpos!!!!!!!
****************************************************/
min_state =_mm_min_epu8(metrics0_15,metrics16_31);
min_state =_mm_min_epu8(min_state,metrics32_47);
min_state =_mm_min_epu8(min_state,metrics48_63);
min_state2 = min_state;
min_state = _mm_unpacklo_epi8(min_state,min_state);
min_state2 = _mm_unpackhi_epi8(min_state2,min_state2);
min_state = _mm_min_epu8(min_state,min_state2);
min_state2 = min_state;
min_state = _mm_unpacklo_epi8(min_state,min_state);
min_state2 = _mm_unpackhi_epi8(min_state2,min_state2);
min_state = _mm_min_epu8(min_state,min_state2);
min_state2 = min_state;
min_state = _mm_unpacklo_epi8(min_state,min_state);
min_state2 = _mm_unpackhi_epi8(min_state2,min_state2);
min_state = _mm_min_epu8(min_state,min_state2);
min_state2 = min_state;
min_state = _mm_unpacklo_epi8(min_state,min_state);
min_state2 = _mm_unpackhi_epi8(min_state2,min_state2);
min_state = _mm_min_epu8(min_state,min_state2);
metrics0_15 = _mm_subs_epu8(metrics0_15,min_state);
metrics16_31 = _mm_subs_epu8(metrics16_31,min_state);
metrics32_47 = _mm_subs_epu8(metrics32_47,min_state);
metrics48_63 = _mm_subs_epu8(metrics48_63,min_state);
#elif defined(__arm__)
m0_ptr = (uint8x16_t *)&m0_table[table_offset];
m1_ptr = (uint8x16_t *)&m1_table[table_offset];
// even states
even0_30a = vqaddq_u8(metrics0_31.val[0],m0_ptr[0]);
even32_62a = vqaddq_u8(metrics0_31.val[1],m0_ptr[1]);
even0_30b = vqaddq_u8(metrics32_63.val[0],m0_ptr[2]);
even32_62b = vqaddq_u8(metrics32_63.val[1],m0_ptr[3]);
// odd states
odd1_31a = vqaddq_u8(metrics0_31.val[0],m1_ptr[0]);
odd33_63a = vqaddq_u8(metrics0_31.val[1],m1_ptr[1]);
odd1_31b = vqaddq_u8(metrics32_63.val[0],m1_ptr[2]);
odd33_63b = vqaddq_u8(metrics32_63.val[1],m1_ptr[3]);
// select maxima
even0_30a = vmaxq_u8(even0_30a,even0_30b);
even32_62a = vmaxq_u8(even32_62a,even32_62b);
odd1_31a = vmaxq_u8(odd1_31a,odd1_31b);
odd33_63a = vmaxq_u8(odd33_63a,odd33_63b);
// Traceback information
TBeven0_30 = vceqq_u8(even0_30a,even0_30b);
TBeven32_62 = vceqq_u8(even32_62a,even32_62b);
TBodd1_31 = vceqq_u8(odd1_31a,odd1_31b);
TBodd33_63 = vceqq_u8(odd33_63a,odd33_63b);
metrics0_31 = vzipq_u8(even0_30a,odd1_31a);
metrics32_63 = vzipq_u8(even32_62a,odd33_63a);
TB_ptr[0] = vzipq_u8(TBeven0_30,TBodd1_31);
TB_ptr[1] = vzipq_u8(TBeven32_62,TBodd33_63);
in+=2;
TB_ptr += 2;
// rescale by subtracting minimum
/****************************************************
USE SSSE instruction phminpos!!!!!!!
****************************************************/
min_state =vminq_u8(metrics0_31.val[0],metrics0_31.val[1]);
min_state =vminq_u8(min_state,metrics32_63.val[0]);
min_state =vminq_u8(min_state,metrics32_63.val[1]);
// here we have 16 maximum metrics from the 64 states
uint8x8_t min_state2 = vpmin_u8(((uint8x8_t*)&min_state)[0],((uint8x8_t*)&min_state)[0]);
// now the 8 maximum in min_state2
min_state2 = vpmin_u8(min_state2,min_state2);
// now the 4 maximum in min_state2, repeated twice
min_state2 = vpmin_u8(min_state2,min_state2);
// now the 2 maximum in min_state2, repeated 4 times
min_state2 = vpmin_u8(min_state2,min_state2);
// now the 1 maximum in min_state2, repeated 8 times
min_state = vcombine_u8(min_state2,min_state2);
// now the 1 maximum in min_state, repeated 16 times
metrics0_31.val[0] = vqsubq_u8(metrics0_31.val[0],min_state);
metrics0_31.val[1] = vqsubq_u8(metrics0_31.val[1],min_state);
metrics32_63.val[0] = vqsubq_u8(metrics32_63.val[0],min_state);
metrics32_63.val[1] = vqsubq_u8(metrics32_63.val[1],min_state);
#endif
}
} // iteration
// Traceback
prev_state0 = 0;
maxm = 0;
#if defined(__x86_64__) || defined(__i386__)
for (s=0; s<16; s++)
if (((uint8_t *)&metrics0_15)[s] > maxm) {
maxm = ((uint8_t *)&metrics0_15)[s];
prev_state0 = s;
}
for (s=0; s<16; s++)
if (((uint8_t *)&metrics16_31)[s] > maxm) {
maxm = ((uint8_t *)&metrics16_31)[s];
prev_state0 = s+16;
}
for (s=0; s<16; s++)
if (((uint8_t *)&metrics32_47)[s] > maxm) {
maxm = ((uint8_t *)&metrics32_47)[s];
prev_state0 = s+32;
}
for (s=0; s<16; s++)
if (((uint8_t *)&metrics48_63)[s] > maxm) {
maxm = ((uint8_t *)&metrics48_63)[s];
prev_state0 = s+48;
}
#elif defined(__arm__)
for (s=0; s<16; s++)
if (((uint8_t *)&metrics0_31.val[0])[s] > maxm) {
maxm = ((uint8_t *)&metrics0_31.val[0])[s];
prev_state0 = s;
}
for (s=0; s<16; s++)
if (((uint8_t *)&metrics0_31.val[1])[s] > maxm) {
maxm = ((uint8_t *)&metrics0_31.val[1])[s];
prev_state0 = s+16;
}
for (s=0; s<16; s++)
if (((uint8_t *)&metrics32_63.val[0])[s] > maxm) {
maxm = ((uint8_t *)&metrics32_63.val[0])[s];
prev_state0 = s+32;
}
for (s=0; s<16; s++)
if (((uint8_t *)&metrics32_63.val[1])[s] > maxm) {
maxm = ((uint8_t *)&metrics32_63.val[1])[s];
prev_state0 = s+48;
}
#endif
TB_ptr2 = (uint8_t *)&TB[(n-1)*4];
for (position = n-1 ; position>-1; position--) {
decoded_bytes[(position)>>3] += (prev_state0 & 0x1)<<(7-(position & 0x7));
if (TB_ptr2[prev_state0] == 0)
prev_state0 = (prev_state0 >> 1);
else
prev_state0 = 32 + (prev_state0>>1);
TB_ptr2-=64;
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty();
_m_empty();
#endif
}
......@@ -17,7 +17,7 @@
//#include "PHY/defs_nb_iot.h"
#include "PHY/LTE_TRANSPORT/dci_NB_IoT.h"
#include "PHY/impl_defs_lte_NB_IoT.h"
#include "openair2/COMMON/platform_types_NB_IoT.h"
#include "openair2/COMMON/platform_types.h"
//#include "dci.h"
#include "PHY/LTE_TRANSPORT/uci_NB_IoT.h"
//#include "dci.h"
......@@ -468,7 +468,7 @@ typedef enum
typedef struct {
rnti_NB_IoT_t rnti;
rnti_t rnti;
//array containing the pdus of DCI
uint8_t *a[2];
//Array containing encoded DCI data
......@@ -481,8 +481,8 @@ typedef struct {
//indicate the corresponding subframe within the repetition (set to 0 when a new NPDCCH pdu is received)
uint16_t repetition_idx;
// uint16_t npdcch_Offset_USS;
// uint16_t npdcch_StartSF_USS;
// uint16_t npdcch_Offset_USS;
// uint16_t npdcch_StartSF_USS;
}NB_IoT_eNB_NPDCCH_t;
......@@ -490,12 +490,12 @@ typedef struct {
typedef struct{
//Number of repetitions (R) for common search space (RAR and PAGING)
uint16_t number_repetition_RA;
uint16_t number_repetition_PAg;
//index of the current subframe among the repetition (set to 0 when we receive the new NPDCCH)
uint16_t repetition_idx_RA;
uint16_t repetition_idx_Pag;
//Number of repetitions (R) for common search space (RAR and PAGING)
uint16_t number_repetition_RA;
uint16_t number_repetition_PAg;
//index of the current subframe among the repetition (set to 0 when we receive the new NPDCCH)
uint16_t repetition_idx_RA;
uint16_t repetition_idx_Pag;
}NB_IoT_eNB_COMMON_NPDCCH_t;
......@@ -509,9 +509,9 @@ typedef struct {
/// Position of first CCE of the dci
int firstCCE;
/// flag to indicate that this is a RA response
boolean_NB_IoT_t ra_flag;
boolean_t ra_flag;
/// rnti
rnti_NB_IoT_t rnti;
rnti_t rnti;
/// Format
DCI_format_NB_IoT_t format;
/// DCI pdu
......
/*
* 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
*/
/*! \file PHY/LTE_TRANSPORT/lte_mcs.c
* \brief Some support routines for MCS computations
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
//#include "PHY/defs.h"
//#include "PHY/extern.h"
#include "PHY/LTE_TRANSPORT/proto_NB_IoT.h"
unsigned char get_Qm_ul_NB_IoT(unsigned char I_MCS)
{
if (I_MCS < 11)
return(2);
else if (I_MCS < 21)
return(4);
else
return(6);
}
......@@ -177,6 +177,11 @@ NB_IoT_eNB_NULSCH_t *new_eNB_ulsch_NB(uint8_t abstraction_flag);
uint8_t subframe2harq_pid_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe);
/** \brief Compute Q (modulation order) based on I_MCS for PUSCH. Implements table 8.6.1-1 from 36.213.
@param I_MCS */
uint8_t get_Qm_ul_NB_IoT(uint8_t I_MCS);
/** \fn dlsch_encoding(PHY_VARS_eNB *eNB,
uint8_t *input_buffer,
LTE_DL_FRAME_PARMS *frame_parms,
......@@ -211,4 +216,13 @@ int32_t dlsch_encoding_NB_IoT(unsigned char *a,
time_stats_t_NB_IoT *te_stats,
time_stats_t_NB_IoT *i_stats);
void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT *phy_vars_eNB,
eNB_rxtx_proc_NB_IoT_t *proc,
uint8_t eNB_id, // this is the effective sector id
uint8_t UE_id,
NB_IoT_eNB_ULSCH_t **ulsch,
uint8_t cooperation_flag);
#endif
......@@ -36,6 +36,7 @@
#include "PHY/defs_NB_IoT.h"
#include "PHY/extern_NB_IoT.h"
#include "PHY/LTE_TRANSPORT/vars_NB_IoT.h"
#include "PHY/CODING/defs_NB_IoT.h"
//#include "PHY/CODING/extern.h"
//#include "extern_NB_IoT.h"
//#include "SCHED/extern.h"
......@@ -988,7 +989,7 @@ unsigned int ulsch_decoding_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
nb_rb = ulsch_harq->nb_rb;
A = ulsch_harq->TBS;
Q_m = get_Qm_ul(ulsch_harq->mcs);
Q_m = get_Qm_ul_NB_IoT(ulsch_harq->mcs);
G = nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch;
......@@ -1007,15 +1008,15 @@ unsigned int ulsch_decoding_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
if (ulsch_harq->round == 0) {
// This is a new packet, so compute quantities regarding segmentation
ulsch_harq->B = A+24;
lte_segmentation(NULL,
NULL,
ulsch_harq->B,
&ulsch_harq->C,
&ulsch_harq->Cplus,
&ulsch_harq->Cminus,
&ulsch_harq->Kplus,
&ulsch_harq->Kminus,
&ulsch_harq->F);
lte_segmentation_NB_IoT(NULL,
NULL,
ulsch_harq->B,
&ulsch_harq->C,
&ulsch_harq->Cplus,
&ulsch_harq->Cminus,
&ulsch_harq->Kplus,
&ulsch_harq->Kminus,
&ulsch_harq->F);
// CLEAR LLR's HERE for first packet in process
}
......@@ -1607,24 +1608,24 @@ unsigned int ulsch_decoding_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
if (Q_CQI>0) {
memset((void *)&dummy_w_cc[0],0,3*(ulsch_harq->Or1+8+32));
O_RCC = generate_dummy_w_cc(ulsch_harq->Or1+8,
&dummy_w_cc[0]);
O_RCC = generate_dummy_w_cc_NB_IoT(ulsch_harq->Or1+8,
&dummy_w_cc[0]);
lte_rate_matching_cc_rx(O_RCC,
Q_CQI,
ulsch_harq->o_w,
dummy_w_cc,
ulsch_harq->q);
lte_rate_matching_cc_rx_NB_IoT(O_RCC,
Q_CQI,
ulsch_harq->o_w,
dummy_w_cc,
ulsch_harq->q);
sub_block_deinterleaving_cc((unsigned int)(ulsch_harq->Or1+8),
&ulsch_harq->o_d[96],
&ulsch_harq->o_w[0]);
sub_block_deinterleaving_cc_NB_IoT((unsigned int)(ulsch_harq->Or1+8),
&ulsch_harq->o_d[96],
&ulsch_harq->o_w[0]);
memset(o_flip,0,1+((8+ulsch_harq->Or1)/8));
phy_viterbi_lte_sse2(ulsch_harq->o_d+96,o_flip,8+ulsch_harq->Or1);
phy_viterbi_lte_sse2_NB_IoT(ulsch_harq->o_d+96,o_flip,8+ulsch_harq->Or1);
if (extract_cqi_crc_NB_IoT(o_flip,ulsch_harq->Or1) == (crc8(o_flip,ulsch_harq->Or1)>>24))
if (extract_cqi_crc_NB_IoT(o_flip,ulsch_harq->Or1) == (crc8_NB_IoT(o_flip,ulsch_harq->Or1)>>24))
ulsch_harq->cqi_crc_status = 1;
if (ulsch->harq_process->Or1<=32) {
......
......@@ -24,7 +24,6 @@
#include "PHY/defs.h"
#include "PHY_INTERFACE/defs.h"
#include "PHY_INTERFACE/IF_Module_NB_IoT.h"
extern char* namepointer_chMag ;
extern char* namepointer_log2;
......@@ -54,7 +53,6 @@ extern PHY_VARS_eNB * PHY_vars_eNB_g[MAX_eNB][MAX_NUM_CCs];
#endif
extern MAC_xface *mac_xface;
extern IF_Module_t *if_inst;
extern short primary_synch0[144];
......
......@@ -56,9 +56,9 @@ extern PHY_VARS_eNB_NB_IoT * PHY_vars_eNB_NB_IoT_g[MAX_eNB_NB_IoT][MAX_NUM_CCs];
extern MAC_xface_NB_IoT *mac_xface_NB_IoT;
/*
extern IF_Module_t *if_inst;
extern IF_Module_t *if_inst;
/*
extern short primary_synch0[144];
extern short primary_synch1[144];
......
......@@ -57,7 +57,6 @@
#endif /* USER_MODE */
#include "defs.h"
//#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
//#include "dlc_engine.h"
extern int openair_sched_status;
......@@ -78,8 +77,4 @@ extern fifo_dump_emos_eNB emos_dump_eNB;
*/
//extern Sched_Rsp_t* Sched_Rsp;
#endif /*__SCHED_EXTERN_H__ */
......@@ -487,18 +487,19 @@ void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_
void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_IoT_t * proc,nfapi_dl_config_request_pdu_t *dl_config_pdu)
{
int UE_id = -1;
NB_IoT_DL_FRAME_PARMS *fp=&eNB->frame_parms_NB_IoT;
int frame = proc->frame_tx;
int subframe = proc->subframe_tx;
DCI_CONTENT *DCI_Content;
DCI_format_NB_IoT_t DCI_format;
NB_IoT_eNB_NDLSCH_t *ndlsch;
NB_IoT_eNB_NPDCCH_t *npdcch;
int UE_id = -1;
NB_IoT_DL_FRAME_PARMS *fp = &eNB->frame_parms_NB_IoT;
int frame = proc->frame_tx;
int subframe = proc->subframe_tx;
DCI_CONTENT *DCI_Content;
DCI_format_NB_IoT_t DCI_format;
NB_IoT_eNB_NDLSCH_t *ndlsch;
NB_IoT_eNB_NPDCCH_t *npdcch;
DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
// check DCI format is N1 (format 0)
if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
{
......@@ -516,7 +517,7 @@ void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_
DCI_Content->DCIN1_RAR.Scheddly = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay;
DCI_Content->DCIN1_RAR.ResAssign = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment;
DCI_Content->DCIN1_RAR.mcs = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs;
DCI_Content->DCIN1_RAR.RepNum = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
DCI_Content->DCIN1_RAR.RepNum = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
DCI_Content->DCIN1_RAR.ndi = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator;
DCI_Content->DCIN1_RAR.HARQackRes = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
DCI_Content->DCIN1_RAR.DCIRep = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;
......@@ -526,8 +527,8 @@ void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_
// fill the dlsch_ra_NB structure for RAR, and packed the DCI PDU
ndlsch= eNB->ndlsch_ra;
ndlsch->ndlsch_type = RAR;
ndlsch = eNB->ndlsch_ra;
ndlsch->ndlsch_type = RAR;
LOG_D(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
......@@ -561,7 +562,7 @@ void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_
DCI_Content->DCIN1.Scheddly = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay;
DCI_Content->DCIN1.ResAssign = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment;
DCI_Content->DCIN1.mcs = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs;
DCI_Content->DCIN1.RepNum = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
DCI_Content->DCIN1.RepNum = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
DCI_Content->DCIN1.ndi = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator;
DCI_Content->DCIN1.HARQackRes = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
DCI_Content->DCIN1.DCIRep = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;
......@@ -672,23 +673,23 @@ void generate_eNB_ulsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_NB_
* ** CQI and PMI are not present in NB-IoT
* ** redundancy version exist only in UL for NB-IoT and not in DL
*/
void npdsch_procedures(PHY_VARS_eNB_NB_IoT *eNB,
eNB_rxtx_proc_NB_IoT_t *proc, //Context data structure for RX/TX portion of subframe processing
NB_IoT_eNB_NDLSCH_t *ndlsch,
//int num_pdcch_symbols, (BCOM says are not needed
uint8_t* pdu
)
void npdsch_procedures(PHY_VARS_eNB_NB_IoT *eNB,
eNB_rxtx_proc_NB_IoT_t *proc, //Context data structure for RX/TX portion of subframe processing
NB_IoT_eNB_NDLSCH_t *ndlsch,
//int num_pdcch_symbols, //(BCOM says are not needed
uint8_t *pdu
)
{
int frame=proc->frame_tx;
int subframe=proc->subframe_tx;
NB_IoT_DL_eNB_HARQ_t *ndlsch_harq =ndlsch->harq_process;
int input_buffer_length = ndlsch_harq->TBS/8; // get in byte //the TBS is set in generate_dlsch_param
NB_IoT_DL_FRAME_PARMS *fp=&eNB->frame_parms_NB_IoT;
int G;
uint8_t *DLSCH_pdu=NULL;
uint8_t DLSCH_pdu_tmp[input_buffer_length+4]; //[768*8];
int frame = proc->frame_tx;
int subframe = proc->subframe_tx;
NB_IoT_DL_eNB_HARQ_t *ndlsch_harq = ndlsch->harq_process;
int input_buffer_length = ndlsch_harq->TBS/8; // get in byte //the TBS is set in generate_dlsch_param
NB_IoT_DL_FRAME_PARMS *fp = &eNB->frame_parms_NB_IoT;
int G;
uint8_t *DLSCH_pdu = NULL;
uint8_t DLSCH_pdu_tmp[input_buffer_length+4]; //[768*8];
//uint8_t DLSCH_pdu_rar[256];
int i;
int i;
LOG_D(PHY,
"[eNB %"PRIu8"][PDSCH rnti%"PRIx16"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", mcs %"PRIu8"(round %"PRIu8")\n",
......@@ -701,9 +702,9 @@ void npdsch_procedures(PHY_VARS_eNB_NB_IoT *eNB,
if(ndlsch_harq->round == 0) { //first transmission so we encode... because we generate the sequence
if (eNB->mac_enabled==1) { // set in lte-softmodem/main line 1646
if (eNB->mac_enabled == 1) { // set in lte-softmodem/main line 1646
DLSCH_pdu =pdu;
DLSCH_pdu = pdu;
/*
* we don't need to manage the RAR here since should be managed in the MAC layer for two reasons:
......
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