Compare commits

...

14 Commits

Author SHA1 Message Date
Raymond Knopp
a2aad91e9a trials for nr_pucchsim in physical-simulators testing 2026-04-30 13:58:30 +02:00
Raymond Knopp
d7bde4425d updated polartest to new API for polar encoder (aggregation_level is E now for PUCCH formats) 2026-04-29 09:16:54 +02:00
Raymond Knopp
c481c36fd6 fixed timeout on ctests for nr_pucchsim 2026-04-28 22:54:33 +02:00
Raymond Knopp
947b6901fb warning removal 2026-04-28 20:36:46 +02:00
Raymond Knopp
21738d5d1e last file from bad merge 2026-04-28 20:25:20 +02:00
Raymond Knopp
690f1a97b1 removed warning in phy_procedures_gNB.c 2026-04-28 20:06:16 +02:00
Raymond Knopp
0ae51d21c3 removed elements from bad merge and reverted them to current develop branch 2026-04-28 19:19:12 +02:00
Raymond Knopp
1c45af1617 Merge remote-tracking branch 'origin/develop' into pucch3_L1 2026-04-28 15:35:39 +02:00
Raymond Knopp
c15cdda6d1 removed warnings in new code in pucch_rx.c 2026-04-28 09:14:02 +02:00
Raymond Knopp
a4a2d94417 added markdown file for PUCCH RX algorithms 2026-03-30 23:04:39 +02:00
Raymond Knopp
822889f8bf Merge remote-tracking branch 'origin/develop' into pucch3_L1 2026-03-28 19:25:19 +01:00
Raymond Knopp
c05c74516f fixed for format 2 (multiple symbols and frequency hopping). Format 1 (frequency-hopping) 2026-03-27 10:44:31 +01:00
Raymond Knopp
eb9f390473 CI tests 2026-03-24 17:59:41 +01:00
Raymond Knopp
25a8ebb64c changes for pucch3 and some debugging of nr_pucchsim for pucch 2 and 3 2026-03-23 16:21:52 +01:00
18 changed files with 1412 additions and 415 deletions

View File

@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
uint32_t decoderState = 0, blockErrorState = 0; // 0 = Success, -1 = Decoding failed, 1 = Block Error.
uint16_t testLength = NR_POLAR_PBCH_PAYLOAD_BITS, coderLength = NR_POLAR_PBCH_E;
uint16_t blockErrorCumulative = 0, bitErrorCumulative = 0;
uint8_t aggregation_level = 8, decoderListSize = 8, logFlag = 0;
uint16_t aggregation_level = 8, decoderListSize = 8, logFlag = 0;
uint16_t rnti = 0;
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
@@ -138,8 +138,8 @@ int main(int argc, char *argv[])
coderLength = 108 * aggregation_level;
} else if (polarMessageType == 2) { // UCI
// pucch2 parameters, 1 symbol, aggregation_level = NPRB
AssertFatal(aggregation_level > 2, "For UCI formats, aggregation (N_RB) should be > 2\n");
coderLength = 16 * aggregation_level;
aggregation_level = 32*4;
coderLength = aggregation_level;
}
// Logging

View File

@@ -35,7 +35,7 @@ int8_t polar_decoder(double *input,
uint8_t listSize,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level)
uint16_t aggregation_level)
{
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
// Assumes no a priori knowledge.
@@ -304,7 +304,7 @@ int8_t polar_decoder_dci(double *input,
uint16_t n_RNTI,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level)
uint16_t aggregation_level)
{
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
@@ -646,7 +646,7 @@ uint32_t polar_decoder_int16(int16_t *input,
uint8_t ones_flag,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level)
uint16_t aggregation_level)
{
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
const uint N = polarParams->N;

View File

@@ -103,14 +103,14 @@ typedef struct nrPolar_params {
} tree_linearization;
} t_nrPolar_params;
void polar_encoder(uint32_t *input, uint32_t *output, int8_t messageType, uint16_t messageLength, uint8_t aggregation_level);
void polar_encoder(uint32_t *input, uint32_t *output, int8_t messageType, uint16_t messageLength, uint16_t aggregation_level);
void polar_encoder_dci(uint32_t *in,
uint32_t *out,
uint16_t n_RNTI,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level);
uint16_t aggregation_level);
void polar_encoder_fast(uint64_t *A,
void *out,
@@ -118,21 +118,21 @@ void polar_encoder_fast(uint64_t *A,
uint8_t ones_flag,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level);
uint16_t aggregation_level);
int8_t polar_decoder(double *input,
uint32_t *output,
uint8_t listSize,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level);
uint16_t aggregation_level);
uint32_t polar_decoder_int16(int16_t *input,
uint64_t *out,
uint8_t ones_flag,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level);
uint16_t aggregation_level);
int8_t polar_decoder_dci(double *input,
uint32_t *out,
@@ -140,7 +140,7 @@ int8_t polar_decoder_dci(double *input,
uint16_t n_RNTI,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level);
uint16_t aggregation_level);
void generic_polar_decoder(t_nrPolar_params *pp, decoder_node_t *node, uint8_t *nr_polar_U);
@@ -159,9 +159,9 @@ void build_polar_tables(t_nrPolar_params *polarParams);
void nr_polar_print_polarParams(void);
t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint8_t aggregation_level);
t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint16_t aggregation_level);
uint16_t nr_polar_aggregation_prime(uint8_t aggregation_level);
uint16_t nr_polar_aggregation_prime(uint16_t aggregation_level);
const uint8_t **nr_polar_kronecker_power_matrices(uint8_t n);

View File

@@ -14,7 +14,7 @@
// input [a_31 a_30 ... a_0]
// output [f_31 f_30 ... f_0] [f_63 f_62 ... f_32] ...
void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t messageLength, uint8_t aggregation_level)
void polar_encoder(uint32_t *in, uint32_t *out, int8_t messageType, uint16_t messageLength, uint16_t aggregation_level)
{
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
uint8_t nr_polar_A[polarParams->payloadBits];
@@ -113,7 +113,7 @@ void polar_encoder_dci(uint32_t *in,
uint16_t n_RNTI,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level)
uint16_t aggregation_level)
{
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);
@@ -446,7 +446,7 @@ void polar_encoder_fast(uint64_t *A,
uint8_t ones_flag,
int8_t messageType,
uint16_t messageLength,
uint8_t aggregation_level)
uint16_t aggregation_level)
{
t_nrPolar_params *polarParams = nr_polar_params(messageType, messageLength, aggregation_level);

View File

@@ -46,7 +46,7 @@ static void nr_polar_delete(void)
pthread_mutex_unlock(&PolarListMutex);
}
t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint8_t aggregation_level)
t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, uint16_t aggregation_level)
{
// The lock is weak, because we never delete in the list, only at exit time
// therefore, returning t_nrPolar_params * from the list is safe for future usage
@@ -113,8 +113,8 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
// %d)\n",newPolarInitNode->payloadBits,newPolarInitNode->encoderLength,aggregation_level);
} else if (messageType == NR_POLAR_UCI_PUCCH_MESSAGE_TYPE) {
AssertFatal(aggregation_level > 2,
"Aggregation level (%d) for PUCCH 2 encoding is NPRB and should be > 2\n",
AssertFatal(aggregation_level > 32,
"Aggregation level (%d) for PUCCH 2 encoding is number of channel bits and should be > 32\n",
aggregation_level);
AssertFatal(messageLength > 11, "Message length %d is too short for polar encoding of UCI\n", messageLength);
@@ -127,7 +127,7 @@ t_nrPolar_params *nr_polar_params(int8_t messageType, uint16_t messageLength, ui
} else {
AssertFatal(1 == 0, "L = %i is an invalid value\n", L);
}
newPolarInitNode->encoderLength = aggregation_level * 16;
newPolarInitNode->encoderLength = aggregation_level;
newPolarInitNode->i_seg = 0;
if ((messageLength >= 360 && newPolarInitNode->encoderLength >= 1088) || (messageLength >= 1013)) {
newPolarInitNode->i_seg = 1;
@@ -250,7 +250,7 @@ void nr_polar_print_polarParams()
return;
}
uint16_t nr_polar_aggregation_prime(uint8_t aggregation_level)
uint16_t nr_polar_aggregation_prime(uint16_t aggregation_level)
{
if (aggregation_level == 0)
return 0;

View File

@@ -115,7 +115,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB)
crcTableInit();
init_byte2m128i();
init_pucch2_luts();
init_pucch2_3_luts();
nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH

View File

@@ -159,7 +159,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy
} //rb
} // symb
int nb_rb=0;
int32_t n0_subband_tot_perANT[frame_parms->nb_antennas_rx];
int64_t n0_subband_tot_perANT[frame_parms->nb_antennas_rx];
memset(n0_subband_tot_perANT, 0, sizeof(n0_subband_tot_perANT));
bool init_meas = measurements->n0_subband_power == NULL;
@@ -171,7 +171,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy
false);
for (int rb = 0 ; rb<frame_parms->N_RB_UL;rb++) {
int32_t n0_subband_tot_perPRB=0;
int64_t n0_subband_tot_perPRB=0;
if (nb_symb[rb] > 0) {
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
tmp_n0_subband[aarx][rb] /= nb_symb[rb];
@@ -192,9 +192,9 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB, int slot, int first_symb, int num_sy
if (nb_rb>0) {
int64_t n0_subband_tot = 0;
for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) {
measurements->n0_subband_power_avg_perANT_dB[aarx] = dB_fixed(n0_subband_tot_perANT[aarx] / nb_rb);
n0_subband_tot += n0_subband_tot_perANT[aarx];
measurements->n0_subband_power_avg_perANT_dB[aarx] = dB_fixed((int32_t)(n0_subband_tot_perANT[aarx] / nb_rb));
n0_subband_tot += (int32_t)(n0_subband_tot_perANT[aarx]/nb_rb);
}
measurements->n0_subband_power_avg_dB = dB_fixed(n0_subband_tot / nb_rb);
measurements->n0_subband_power_avg_dB = dB_fixed(n0_subband_tot/frame_parms->nb_antennas_rx);
}
}

View File

@@ -53,6 +53,6 @@ void nr_codeword_unscrambling_init(int16_t *s, uint32_t size, uint8_t q, uint32_
/**@}*/
void init_pucch2_luts(void);
void init_pucch2_3_luts(void);
void set_prach_tables(int N_ZC, c16_t** ru, uint32_t** zc_inv);
#endif

View File

@@ -227,12 +227,12 @@ void nr_decode_pucch1(PHY_VARS_gNB *gNB,
nfapi_nr_pucch_pdu_t *pucch_pdu);
void nr_decode_pucch2(PHY_VARS_gNB *gNB,
c16_t **rxdataF,
int frame,
int slot,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu,
const nfapi_nr_pucch_pdu_t* pucch_pdu);
void nr_decode_pucch2_3(PHY_VARS_gNB *gNB,
c16_t **rxdataF,
int frame,
int slot,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu,
const nfapi_nr_pucch_pdu_t* pucch_pdu);
void nr_decode_pucch0(PHY_VARS_gNB *gNB,
c16_t **rxdataF,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,562 @@
# PUCCH Receiver Algorithms — `pucch_rx.c`
This document describes the physical-layer receiver algorithms in
`openair1/PHY/NR_TRANSPORT/pucch_rx.c` for the 5G NR gNB.
The file implements UCI reception for PUCCH Formats 0, 1, 2, and 3
as specified in 3GPP TS 38.211, 38.212, and 38.213.
---
## Table of Contents
1. [Overview](#1-overview)
2. [Format 0 — `nr_decode_pucch0`](#2-pucch-format-0--nr_decode_pucch0)
3. [Format 1 — `nr_decode_pucch1`](#3-pucch-format-1--nr_decode_pucch1)
4. [Formats 2 & 3 — `nr_decode_pucch2_3`](#4-pucch-formats-2--3--nr_decode_pucch2_3)
5. [Helper / Initialisation Functions](#5-helper--initialisation-functions)
6. [Data Types and Key Structures](#6-data-types-and-key-structures)
7. [Standards References](#7-standards-references)
---
## 1. Overview
PUCCH carries HARQ acknowledgements (ACK/NACK), Scheduling Requests (SR), and
Channel State Information (CSI) from UE to gNB.
| Format | Symbols | PRBs | Bits | Encoding | Main use |
|--------|---------|------|------|----------|----------|
| 0 | 12 | 1 | 02 | Sequence selection | SR, 12 HARQ bits |
| 1 | 414 | 1 | 12 | OCC + sequence | SR, 12 HARQ bits |
| 2 | 12 | 116 | 364 | RM / polar + QPSK | HARQ + SR + CSI |
| 3 | 414 | 116 | 364 | RM / polar + QPSK | HARQ + SR + CSI |
All decoders read from `gNB->common_vars.rxdataF` and write decoded UCI into
an `nfapi_nr_uci_pucch_pdu_*` output structure.
### Non-Coherent Block Detection
All four formats use a common detection philosophy: **non-coherent block
detection**. The fundamental assumption is that the channel is approximately
constant over a *coherence block* — a contiguous set of REs in time and
frequency over which the phase of the channel can be treated as unknown but
fixed. The receiver therefore integrates signal energy within each block
without relying on phase knowledge, which avoids the need for explicit
per-subcarrier channel estimation on every resource.
For **Formats 0 and 1**, the PUCCH spans only a single PRB (12 subcarriers).
The entire PRB constitutes one coherence block, and detection is a
non-coherent correlation against the set of candidate sequences. Within a
single PRB, however, the channel *is* assumed coherent across symbols that
share the same PRB, so those symbols are combined **coherently** (phases are
summed before squaring). When **intra-slot frequency hopping** is used, the
two hops occupy different PRBs and the channels across the two hops cannot be
assumed phase-coherent; the contributions from each hop are therefore combined
**non-coherently** (squared magnitudes are summed).
For **Formats 2 and 3**, the PUCCH spans multiple PRBs and symbols. The
receiver accumulates the correlation metric over all groups and all symbols
non-coherently, summing the squared magnitudes of each group's contribution,
so no inter-group phase alignment is assumed or required. The coherence block
size depends on format and payload length:
- **Format 2, short block (311 bits):** 2 PRBs per coherence block.
- **Format 2, polar code (1264 bits):** a sub-PRB group of 4 REs is the
coherence block, allowing the LLR computation to remain non-coherent at
fine granularity.
- **Format 3:** a full PRB (12 subcarriers) is the coherence block.
---
## 2. PUCCH Format 0 — `nr_decode_pucch0`
**Lines 129466** | **12 symbols, 1 PRB, 02 bits**
Format 0 encodes information in the *cyclic shift index* of a 12-element
low-PAPR sequence. No data symbols are transmitted; the receiver performs
maximum-likelihood sequence detection.
### 2.1 Cyclic-Shift LUT (`get_pucch0_cs_lut_index`, lines 71100)
Before detection, the cyclic-shift hopping sequence is pre-computed for the
entire frame and cached, keyed by `pucch_GroupHopping` / `hoppingId`.
`nr_cyclic_shift_hopping()` is called once per (slot, symbol) pair and the
result is stored as an integer LUT (divided by $\pi/6$). Subsequent
calls for the same hopping ID return immediately.
### 2.2 Candidate Sequence Generation
For each OFDM symbol, sequences are generated for all cyclic shifts
$m_\text{cs} \in \{0, \ldots, 11\}$:
$$s_{m_\text{cs}}[n] = e^{j\,\alpha(m_\text{cs})\,n} \cdot r_{u,v}[n], \quad n = 0,\ldots,11$$
where $\alpha(m_\text{cs}) = 2\pi(m_\text{cs,initial} + m_\text{cs} + m_\text{cs,hop})/12$
and $r_{u,v}[n]$ is the base sequence from TS 38.211 Table 5.2.2.2-2.
The number of tested hypotheses depends on payload size:
| Payload | Hypotheses |
|---------|-----------|
| SR only (0 HARQ bits) | 1 |
| 1 HARQ bit ± SR | 4 |
| 2 HARQ bits | 8 |
### 2.3 Received Signal Extraction
Twelve subcarriers starting at the configured PRB are extracted from
`rxdataF` per antenna and per PUCCH symbol. Frequency hopping switches the
PRB offset on the second symbol.
### 2.4 Correlation via 12-Point IDFT
The received vector $\mathbf{y}$ is correlated against each candidate sequence using
a 12-point IDFT with pre-computed integer tables (`idft12_re`, `idft12_im`):
$$C_{aa}[m_\text{cs}] = \sum_{n=0}^{11} y_{aa}[n] \cdot s_{m_\text{cs}}^*[n]$$
implemented in fixed-point as:
$$C_{aa}[m_\text{cs}].\mathrm{re} = \sum_n \bigl( y[n].\mathrm{re} \cdot \texttt{idft12\_re}[m_\text{cs}][n] + y[n].\mathrm{im} \cdot \texttt{idft12\_im}[m_\text{cs}][n] \bigr)$$
$$C_{aa}[m_\text{cs}].\mathrm{im} = \sum_n \bigl( y[n].\mathrm{im} \cdot \texttt{idft12\_re}[m_\text{cs}][n] - y[n].\mathrm{re} \cdot \texttt{idft12\_im}[m_\text{cs}][n] \bigr)$$
### 2.5 Multi-Symbol Combining
| Configuration | Combining method |
|---------------|-----------------|
| 1 symbol | Non-coherent: $\Lambda = \sum_{aa} \lvert C_{aa} \rvert^2$ |
| 2 symbols, no hop | Coherent: $\Lambda = \sum_{aa} \lvert C_{aa}^{(0)} + C_{aa}^{(1)} \rvert^2$ |
| 2 symbols, freq hop | Non-coherent: $\Lambda = \sum_{aa} \bigl(\lvert C_{aa}^{(0)} \rvert^2 + \lvert C_{aa}^{(1)} \rvert^2\bigr)$ |
The ML decision is $\hat{m}_\text{cs} = \arg\max_{m_\text{cs}} \Lambda(m_\text{cs})$.
### 2.6 Bit Extraction
| `nb_harq_bits` | SR present | Decision |
|----------------|------------|----------|
| 0 | yes | SR $= 1$ if $\Lambda_\max > \text{threshold}$, else $0$ |
| 1 | no/yes | HARQ $= \hat{m}_\text{cs} \gg 3$; SR $= \hat{m}_\text{cs} \mathbin{\&} 1$ |
| 2 | no/yes | HARQ bits from $(\hat{m}_\text{cs} \gg 2)\mathbin{\&}1$, $(\hat{m}_\text{cs} \gg 3)\mathbin{\&}1$; SR $= \hat{m}_\text{cs} \mathbin{\&} 1$ |
SNR is computed from the peak-to-average metric ratio and mapped to a CQI
value (0255, covering $-64$ to $+63.5$ dB). A configurable threshold
`gNB->pucch0_thres` gates the SR decision.
---
## 3. PUCCH Format 1 — `nr_decode_pucch1`
**Lines 4681074** | **414 symbols, 1 PRB, 12 bits**
Format 1 modulates 1 or 2 HARQ bits onto a low-PAPR sequence and spreads the
result across OFDM symbols with an orthogonal cover code (OCC). Alternating
symbols carry DM-RS for channel estimation.
### 3.1 Symbol Layout
Even symbols (0, 2, 4, …) within the PUCCH allocation carry DM-RS; odd
symbols carry data. Both use the same 12-subcarrier PRB.
### 3.2 Sequence Generation
For each symbol, the group hopping indices $u$, $v$ are obtained from
`nr_group_sequence_hopping()`. The cyclic shift $\alpha$ from
`nr_cyclic_shift_hopping()` is applied to the base sequence:
$$r_{u,v,\alpha}[n] = e^{j\alpha n} \cdot r_{u,v}[n], \quad n = 0,\ldots,11$$
implemented in fixed-point using a pre-computed $(\cos\alpha n,\,\sin\alpha n)$
pair at each subcarrier and `c16mulShift()`.
### 3.3 OCC Spreading / Despreading
The OCC weight for data symbol index $m$ within spreading factor $N_\text{SF}$ is:
$$w_i(m) = e^{j 2\pi i m / N_\text{SF}}$$
Two operating modes:
- **No intra-slot hopping** — single OCC table
`table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop` covers all symbols.
- **Intra-slot frequency hopping** — separate tables for $m'=0$
(first half-slot) and $m'=1$ (second half-slot).
Received symbols are multiplied by $w_i^*(m)$ and the conjugate of the
reference sequence to despread both DM-RS and data.
### 3.4 Channel Estimation
The DM-RS symbols, after despreading, are averaged across all DM-RS symbols
and subcarriers to yield a per-antenna channel estimate:
$$\hat{h}_r = \frac{1}{N_\text{DM-RS} \cdot 12} \sum_{m,n} z_\text{DM-RS}[r][12m+n]$$
For frequency hopping, independent estimates $\hat{h}_r$ and $\hat{h}_r^{(1)}$
are computed for each hop.
### 3.5 ML Detection
The despread data accumulation across all data symbols gives $y_r$.
**1 HARQ bit (BPSK)** — two hypotheses $d \in \{+1, -1\}$:
$$\Lambda_d = \sum_r \left\lvert \hat{h}_r + \frac{d}{\sqrt{2}}\, y_r \right\rvert^2$$
The sign with the larger metric gives the decoded bit.
**2 HARQ bits (QPSK)** — four hypotheses
$d \in \{+1+j,\; +1-j,\; -1+j,\; -1-j\} / \sqrt{2}$:
$$\Lambda_d = \sum_r \left\lvert \hat{h}_r + d\, y_r \right\rvert^2$$
The maximum-metric index maps to the 2-bit Gray-coded HARQ word.
For frequency hopping, metrics from both hops are summed non-coherently.
---
## 4. PUCCH Formats 2 & 3 — `nr_decode_pucch2_3`
**Lines 11381999** | **Variable symbols and PRBs, 364 bits**
Formats 2 and 3 share a single decoder function. Both apply QPSK modulation
and either a Reed-Muller small-block code (311 bits) or a polar code
(1264 bits). The key difference is their time-frequency structure:
| | Format 2 | Format 3 |
|---|---|---|
| Symbols | 12 | 414 |
| DM-RS density | Every symbol, RE positions 1,4,7,10 per PRB | Sparse: 2 or 4 dedicated DMRS symbols |
| DM-RS generation | Gold sequence (TS 38.211 §6.4.1.3.2) | Low-PAPR sequence with group/cyclic-shift hopping |
| Data transform | None (frequency domain directly) | FFT across groups of 4 time-domain symbols |
### 4.1 Signal Extraction and Scaling
All received REs are extracted per antenna and symbol into
`rp[Prx][nb_symbols][nb_re_pucch]`. Total signal energy is accumulated:
$$E = \sum_{aa,\,l} \texttt{signal\_energy\_nodc}(\mathbf{r}_{aa,l})$$
A scaling exponent is derived to keep subsequent fixed-point products in range:
$$\texttt{scaling} = \max\!\left(\left\lfloor \tfrac{1}{2}\log_2 E \right\rfloor - 8,\; 0\right)$$
### 4.2 DM-RS Position Selection (Format 3)
DMRS symbol positions within the PUCCH allocation are selected from
standardised tables based on the number of symbols and the
`additional_dmrs` flag:
| `nr_of_symbols` | `additional_dmrs` | DMRS symbols (relative) |
|-----------------|-------------------|-------------------------|
| 49 | either | 2 symbols |
| 1014 | 0 | 2 symbols |
| 1014 | 1 | 4 symbols |
### 4.3 Data Scrambling
A Gold sequence is initialised with:
$$c_\text{init} = (\text{RNTI} \ll 15) + \text{data\_scrambling\_id}$$
The binary scrambling sequence is packed into SIMD registers and applied to
data REs via `simde_mm_sign_epi16()` (multiply by $\pm 1$ per bit).
### 4.4 DM-RS Processing and Channel Estimation
**Format 2:** The Gold-sequence pilot values are generated on-the-fly. Each
pilot RE is multiplied by the conjugate of the expected pilot, and an integer
delay estimate is computed via `nr_est_delay()` (128-tap correlation). A
pre-computed frequency-domain phase-ramp filter (`delay_table128`) compensates
the detected delay across all data REs.
**Format 3:** The low-PAPR DM-RS sequence is generated per DMRS symbol using
group/cyclic-shift hopping (same as Format 1). The received DMRS REs are
multiplied by the conjugate of the expected sequence and accumulated into
per-group, per-antenna correlation values `corr32[symb][group][aa]`.
### 4.5 Format 3 FFT Processing
For data symbols, Format 3 uses time-domain OCC spreading (analogous to
Format 1). Groups of 4 consecutive data symbols are collected into an IDFT
input buffer per antenna. When the buffer is full (or at end of PUCCH):
1. Conjugates are taken to convert to IDFT input form.
2. A 12-, 24-, or 36-point FFT is applied via `dft()`.
3. The output is transposed using SIMD unpack/shuffle operations to convert
from time-interleaved to subcarrier-interleaved order.
4. The gold scrambling sequence is removed with `simde_mm_sign_epi16()`.
The result is equivalent to the de-spread, unscrambled data RE grid used by
Format 2.
### 4.6 Decoding — Short Blocks (311 bits), Format 2
`init_pucch2_3_luts()` pre-encodes every information word with
`encodeSmallBlock()` (Reed-Muller / simplex code) and stores the BPSK-mapped
symbols $b[k] \in \{1,-1\}$ in `pucch2_3_lut[N-3][cw]`. Note that $b[i]$ in TS 38.211 is a binary ${0,1}$ sequence which is mapped to BPSK here for convenience in the receiver.
#### Signal model and group structure
The non-coherent group size is $N_g = 2$ PRBs, giving
$N_\text{group} = \lfloor P/2 \rfloor$ groups (where $P$ is `prb_size`).
Each group spans 2 consecutive PRBs: $N_p = 8$ DMRS REs and $N_d = 16$ data
REs per OFDM symbol.
The channel is assumed flat within a group. For group $g$, symbol $l$,
and receive antenna $aa$:
$$r_\text{DM-RS}[aa,l,k] = h_{g,aa} \cdot p[k] + n[k], \quad k \in \mathcal{K}_\text{DM-RS}(g)$$
$$r_\text{data}[aa,l,k] = h_{g,aa} \cdot d[k] + n[k], \quad k \in \mathcal{K}_\text{data}(g)$$
where $p[k] = (1-2c(2k)+j(1-2c(2k+1)))/\sqrt{2}$ is the QPSK pilot value
generated from the Gold sequence $c(i)$ (TS 38.211 §6.4.1.3.2.1), and
$d[k] \in \{(\pm 1 \pm j)/\sqrt{2}\}$ is the QPSK-modulated codeword symbol
corresponding to $d(i)$-sequence in TS 38.211 §6.3.2.5.2.
#### DMRS-assisted coherent reference per group
The DMRS REs within each group are correlated with the conjugate of the known
pilot sequence to form a channel reference:
$$H[g,l,aa] = \sum_{k \in \mathcal{K}_\text{DM-RS}(g)} r_\text{DM-RS}[aa,l,k] \cdot p^*[k] \;\approx\; h_{g,aa} \cdot N_p$$
(stored as `corr32[l][g][aa]` in the code).
This reference is combined across OFDM symbols to initialise the detection
statistic $Z$:
| Configuration | Initialisation of $Z[g,aa]$ |
|---------------|------------------------------|
| 1 symbol | $H[g,0,aa]$ |
| 2 symbols, no freq hop | $H[g,0,aa] + H[g,1,aa]$ (coherent) |
| 2 symbols, freq hop (hop $d$) | $H[g,d,aa]$ (separate per hop) |
#### Codeword correlation
The transmitted QPSK data symbol $d[k]$ encodes two scrambled bits per subcarrier:
$$d[k] = \frac{(1-2\tilde{b}(2k)) + j\,(1-2\tilde{b}(2k+1))}{\sqrt{2}}$$
where $\tilde{b}(i) = (b(i) + c_\text{scr}(i)) \bmod 2$ is the scrambled bit sequence
(TS 38.211 §6.3.2.5.1) and $c_\text{scr}(i)$ is the Gold scrambling sequence
initialised with $c_\text{init}$ from Section 4.3.
To follow the steps of the correlation with unscrambling
Let $b'(i) = (1-2b(i))$ and $c'(i) = (1-2c(i))$ so that $\tilde{b}'(i)=(1-2b(i))(1-2c(i))$, and the $k^{\text{th}}$ received
dimension is
$$r_\text{data}(k) =(b'(2k)c'(2k)+jb'(2k+1)c'(2k+1))h(k) + z(k)$$
The $k^{\text{th}}$ component of the desired correlation is
$$\begin{align}r_\text{data}(k)(b'(2k)c'(2k) -jb'(2k+1)c'(2k+1)) = & \text{Re}(r_\text{data}(k))c'(2k)b'(2k) + \text{Im}(r_\text{data}(k))c'(2k+1)b'(2k+1) + \\
& j(\text{Im}(r_\text{data}(k))c'(2k)b'(2k) - \text{Re}(r_\text{data}(k))c'(2k+1)b'(2k+1))\end{align}$$
The receiver first applies the Gold sequence (`c_ptr`) to descramble the received
REs, splitting into components which will later allow for separation of the real and imaginary components (`r_ext` and `r_ext2`
in the code). These two components correspond to the real and imaginary parts of the $k^\text{th}$ component of the overall correlation shown above and are
$$r_\text{ext}[aa,l,k] = c'(2k) \cdot\text{Re}(r_\text{data}[aa,l,k]) +j c'(2k+1) \cdot\text{Im}(r_\text{data}[aa,l,k])$$
$$r_\text{ext2}[aa,l,k] = c'(2k) \cdot\text{Im}(r_\text{data}[aa,l,k]) - jc'(2k+1)\text{Re}(r_\text{data}[aa,l,k])$$
and are implemented using the `simde_mm_sign_epi16`, `oai_mm_conj` and `simde_mm_shuffle_epi8` SIMD methods on the received data samples.
For each candidate codeword
$\mathbf{b}$, the descrambled REs are correlated against the LUT and accumulated
into $Z$:
$$\begin{align} Z[g,aa](\mathbf{b}) \mathrel{+}= \sum_{l} \sum_{k \in \mathcal{K}_\text{data}(g)}
\bigl(&\mathrm{Re}(r_\text{ext}[aa,l,k]) \cdot b'[2k] + \mathrm{Im}(r_\text{ext}[aa,l,k]) \cdot b'[2k+1] + \bigr. \\
& j(\mathrm{Re}(r_\text{ext2}[aa,l,k]) \cdot b'[2k] + \mathrm{Im}(r_\text{ext2}[aa,l,k]) \cdot b'[2k+1]) \bigr)
\end{align}$$
where $L$ is the number of data symbols. After both DMRS initialisation and
data accumulation:
$$Z[g,aa](\mathbf{b}) \approx h_{g,aa} \cdot \bigl(L \cdot N_p + L \cdot N_d \cdot \mathbf{1}\{\mathbf{b} = \mathbf{b}_\text{tx}\}\bigr) + \text{noise}$$
#### ML metric and decision
The per-group squared magnitude is summed non-coherently across groups and
antennas:
$$\Lambda(\mathbf{b}) = \sum_{g,\,aa} \left\lvert Z[g,aa](\mathbf{b}) \right\rvert^2 \qquad \text{(no freq hop)}$$
$$\Lambda(\mathbf{b}) = \sum_{g,\,aa,\,\delta} \left\lvert Z[g,\delta,aa](\mathbf{b}) \right\rvert^2 \qquad \text{(freq hop, hop index } \delta\text{)}$$
Every codeword receives a baseline contribution of $|h|^2 (L N_p)^2$, while
the correct codeword gains an additional $|h|^2 L^2 N_d (2 N_p + N_d)$.
The decision is:
$$\hat{\mathbf{b}} = \arg\max_{\mathbf{b}}\; \Lambda(\mathbf{b})$$
### 4.6.1 Decoding — Short Blocks (311 bits), Format 3
Format 3 feeds the same LUT-based correlator as Format 2. The differences are
in the coherence group geometry, the pilot type, and the data pre-processing
that precedes the descrambling step.
#### Group structure
The coherence group is one full PRB (12 subcarriers), so $N_g = 1$ and
$N_\text{group} = P$ (one group per PRB). Within each group every subcarrier
carries either DM-RS or data depending on the symbol type:
$N_p = 12$ DM-RS REs and $N_d = 12$ data REs per group per symbol.
#### DM-RS pilot and channel reference
The pilot sequence is the low-PAPR sequence $r_{u,v,\alpha}[k]$
(TS 38.211 §6.3.2.6.3 / §6.4.1.3.2.2), generated with the same
group/cyclic-shift hopping as Format 1. The channel reference per DMRS
symbol $l_\text{DM-RS}$ is:
$$H[g, l_\text{DM-RS}, aa] = \sum_{k=0}^{11} r_\text{DM-RS}[aa, l_\text{DM-RS}, 12g+k]\cdot r_{u,v,\alpha}^*[k]
\;\approx\; h_{g,aa} \cdot N_p$$
accumulated into `corr32[l_dmrs][g][aa]`. Contributions from the 2 or 4
DMRS symbols (Section 4.2) are combined coherently to initialise $Z[g,aa]$,
exactly as in the Format 2 table of Section 4.6.
#### OCC despreading (Section 4.5)
Before the descrambling step, the received data symbols are OCC-despread via
IDFT. Each group of (up to) 4 consecutive data symbols is stacked into the
IDFT input buffer with stride 4 (one sample per symbol per subcarrier), the
input is conjugated, and a length-$N_d$ DFT is applied. The output is
transposed to produce a subcarrier-interleaved layout equivalent to the
single-symbol, frequency-domain data grid of Format 2.
#### Descrambling and codeword correlation
After IDFT despreading the Gold scrambling sequence (`c_ptr`) is applied
identically to Format 2 to produce `r_ext` and `r_ext2`:
$$r_\text{ext}[aa,l,k] = c'(2k)\cdot\text{Re}(r_\text{data}[aa,l,k]) + j\,c'(2k+1)\cdot\text{Im}(r_\text{data}[aa,l,k])$$
$$r_\text{ext2}[aa,l,k] = c'(2k)\cdot\text{Im}(r_\text{data}[aa,l,k]) - j\,c'(2k+1)\cdot\text{Re}(r_\text{data}[aa,l,k])$$
The codeword correlation, ML metric, and decision are then **identical** to
Section 4.6 with the Format 3 group parameters substituted:
| Parameter | Format 2 | Format 3 |
|-----------|----------|----------|
| Coherence group size | 2 PRBs | 1 PRB |
| $N_p$ per group | 8 | 12 |
| $N_d$ per group | 16 | 12 |
| Pilot $p[k]$ | Gold-sequence QPSK: $(1-2c(2k)+j(1-2c(2k+1)))/\sqrt{2}$ | Low-PAPR $r_{u,v,\alpha}[k]$ |
| Data pre-processing | None | IDFT despreading across 4 symbols |
### 4.7 Decoding — Polar Code (1264 bits)
**LLR computation** (per 4-RE group):
For each group of 4 data REs and all 256 possible 8-bit partial codewords,
a correlation is computed between the received vector and the coded pattern.
LLR numerator and denominator for each bit $b$ are:
$$\lambda_b^+ = \max_{\mathbf{c}:\,c_b=1} \rho(\mathbf{c}), \qquad
\lambda_b^- = \max_{\mathbf{c}:\,c_b=0} \rho(\mathbf{c})$$
$$\text{LLR}[b] = \lambda_b^+ - \lambda_b^-$$
where $\rho(\mathbf{c})$ is the per-group correlation energy. LUT tables
(`pucch2_3_polar_llr_num_lut`) pre-encode the bit-to-pattern mapping as SIMD
registers, enabling vectorised accumulation.
**Polar decoding:**
```c
polar_decoder_int16(llrs, decodedPayload, NR_POLAR_UCI_PUCCH_MESSAGE_TYPE, ...)
```
The decoded bit vector is bit-reversed to match the TS 38.212 interleaving
convention.
### 4.8 UCI Payload Extraction
The decoded bitstream is partitioned in order:
| Field | Length |
|-------|--------|
| HARQ-ACK | `bit_len_harq` bits |
| SR | 1 bit (if `sr_flag`) |
| CSI Part 1 | `bit_len_csi_part1` bits |
| CSI Part 2 | flagged in output bitmap |
---
## 5. Helper / Initialisation Functions
### `get_pucch0_cs_lut_index()` (lines 71100)
Maintains a per-hopping-ID cache of cyclic-shift values for the entire frame.
On first call for a given `hoppingId`, iterates over all slots and symbols,
calls `nr_cyclic_shift_hopping()`, converts to an integer index (dividing by
$\pi/6$), and stores in a flat LUT. Returns the cache slot index for use by
`nr_decode_pucch0`.
### `init_pucch2_3_luts()` (lines 10981129)
Called once at gNB startup. Populates:
- `pucch2_3_lut[N-3][cw]` — QPSK-mapped small-block codewords
for $N = 3,\ldots,11$ bits (8 to 2048 entries each).
- `pucch2_3_polar_llr_num_lut[256]` — 8-bit partial-codeword patterns packed
into SIMD registers for use in the polar LLR computation.
### `nr_fill_pucch()` (lines 3469)
Finds a free slot in `gNB->pucch[]`, copies the incoming
`nfapi_nr_pucch_pdu_t`, and allocates a beam index if beamforming is active.
Aborts with `AssertFatal` if the PUCCH queue is full.
### `nr_dump_uci_stats()` (lines 20012064)
Writes per-UE UCI counters (trial counts, DTX events, noise powers, SR
positive rates) to a file or stdout for monitoring.
---
## 6. Data Types and Key Structures
| Type | Description |
|------|-------------|
| `c16_t` | Complex 16-bit integer (`.r`, `.i`) |
| `c32_t` | Complex 32-bit integer |
| `c64_t` | Complex 64-bit integer |
| `cd_t` | Complex double (used in Format 1 equalization) |
| `cw_t` | Struct holding 16 $\times$ `c16_t` — one small-block codeword |
| `nfapi_nr_pucch_pdu_t` | FAPI input: format, PRBs, symbols, RNTI, hopping config, payload lengths |
| `nfapi_nr_uci_pucch_pdu_format_0_1_t` | UCI output for Formats 0 and 1 |
| `nfapi_nr_uci_pucch_pdu_format_2_3_4_t` | UCI output for Formats 2, 3, and 4 |
| `PHY_VARS_gNB` | gNB context; holds `rxdataF`, `pucch[]` queue, thresholds, statistics |
Fixed-point arithmetic is used throughout. Powers-of-two shifts replace
division. SIMD acceleration (AVX2/SSE via the `simde` portability layer) is
used in the Format 2/3 scrambling removal, LLR accumulation, and FFT transpose
loops. Format 1 equalization uses `cd_t` (double) for the final channel
estimate and hypothesis metrics.
---
## 7. Standards References
| Reference | Scope |
|-----------|-------|
| TS 38.211 §5.2.2 | Low-PAPR base sequences |
| TS 38.211 §6.3.2.2 | Group and sequence hopping |
| TS 38.211 §6.3.2.3 | PUCCH Format 0 sequence |
| TS 38.211 §6.3.2.4 | PUCCH Format 1 (OCC, spreading) |
| TS 38.211 §6.3.2.5 | PUCCH Format 2 |
| TS 38.211 §6.3.2.6 | PUCCH Format 3 |
| TS 38.211 §6.4.1.3 | PUCCH DM-RS |
| TS 38.212 §6.3 | UCI channel coding (polar, Reed-Muller) |
| TS 38.213 §9 | PUCCH procedures and resource allocation |
Key tables used in the implementation:
| Symbol | Standard table |
|--------|---------------|
| `table_5_2_2_2_2` | Base sequences (TS 38.211 Table 5.2.2.2-2) |
| `table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_noHop` | OCC spreading factors, no hop (TS 38.211 Table 6.3.2.4.1-1) |
| `table_6_3_2_4_1_1_N_SF_mprime_PUCCH_1_m0Hop` | OCC spreading factors, hop $m'=0$ |
| `table_6_3_2_4_1_2_Wi` | OCC weights (TS 38.211 Table 6.3.2.4.1-2) |

View File

@@ -1191,7 +1191,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
nr_uci_encoding(pusch_pdu->pusch_uci.harq_payload,
pusch_pdu->pusch_uci.harq_ack_bit_length,
pucch_pdu->prb_size,
true,
rm_info.E_uci_ACK,
mod_order,
@@ -1211,7 +1210,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
if (pusch_pdu->pusch_uci.csi_payload.p1_bits != 0) {
nr_uci_encoding(pusch_pdu->pusch_uci.csi_payload.part1_payload,
pusch_pdu->pusch_uci.csi_payload.p1_bits,
pucch_pdu->prb_size,
true,
rm_info.E_uci_CSI1,
mod_order,
@@ -1221,7 +1219,6 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
if (pusch_pdu->pusch_uci.csi_payload.p2_bits > 0)
nr_uci_encoding(pusch_pdu->pusch_uci.csi_payload.part2_payload,
pusch_pdu->pusch_uci.csi_payload.p2_bits,
pucch_pdu->prb_size,
true,
rm_info.E_uci_CSI2,
mod_order,

View File

@@ -420,7 +420,7 @@ void nr_generate_pucch1(c16_t **txdataF,
}
if ((startingPRB > (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) + 6;
re_offset = ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size) + (12*(startingPRB-(frame_parms->N_RB_DL>>1))) - 6;
}
if ((startingPRB == (frame_parms->N_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 1)) { // if number RBs in bandwidth is odd and current PRB contains DC
@@ -436,8 +436,8 @@ void nr_generate_pucch1(c16_t **txdataF,
if (l%2 == 1) { // mapping PUCCH according to TS38.211 subclause 6.4.1.3.1
txdataF[0][re_offset] = z[i + n];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, i + n, re_offset,
printf("\t [nr_generate_pucch1] mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u/%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, i + n, re_offset, re_offset - ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size),
l, n, txdataF[0][re_offset].r, txdataF[0][re_offset].i);
#endif
}
@@ -445,8 +445,8 @@ void nr_generate_pucch1(c16_t **txdataF,
if (l % 2 == 0) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.1
txdataF[0][re_offset] = z_dmrs[i + n];
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, i+n, re_offset,
printf("\t [nr_generate_pucch1] mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d \tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u/%u)=(x_n(l=%d,n=%d)=(%d,%d))\n",
amp, frame_parms->ofdm_symbol_size, frame_parms->N_RB_DL, frame_parms->first_carrier_offset, i+n, re_offset, re_offset - ((l+startingSymbolIndex)*frame_parms->ofdm_symbol_size),
l, n, txdataF[0][re_offset].r, txdataF[0][re_offset].i);
#endif
// printf("gNb l=%d\ti=%d\treoffset=%d\tre=%d\tim=%d\n",l,i,re_offset,z_dmrs_re[i+n],z_dmrs_im[i+n]);
@@ -505,7 +505,7 @@ static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit, uint16_t rnti, uint1
const int roundedSz = (M_bit + 31) / 32;
uint32_t *seq = gold_cache((rnti << 15) + n_id, roundedSz);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence s=%x, M_bit %d\n", *seq, M_bit);
printf("\t\t [nr_pucch2_3_4_scrambling] gold sequence (%x) s=%x, M_bit %d\n", (rnti << 15) + n_id, *seq, M_bit);
#endif
uint8_t *btildep = btilde;
@@ -535,7 +535,7 @@ static inline void nr_pucch2_3_4_scrambling(uint16_t M_bit, uint16_t rnti, uint1
#endif
}
void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci_on_pusch, uint16_t E, uint8_t Qm, uint64_t *b)
void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, bool uci_on_pusch, uint16_t E, uint8_t Qm, uint64_t *b)
{
/*
* Implementing TS 38.212 Subclause 6.3.1.2 and 6.3.2
@@ -548,7 +548,7 @@ void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci
// E is the rate matching output sequence length as given in TS 38.212 subclause 6.3.1.4.1
// int I_seg;
#ifdef DEBUG_NR_PUCCH_TX
printf("\t\t [nr_uci_encoding] start function with encoding A=%d bits into M_bit=%d (where nrofPRB=%d)\n", A, E, nrofPRB);
printf("\t\t [nr_uci_encoding] start function with encoding A=%d bits into M_bit=%d (E)\n", A, E);
#endif
// For A=1 case (single bit UCI)
@@ -659,7 +659,7 @@ void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci
b[i] = 0;
}
} else {
// repetition for rate-matching up to 16 PRB
// repetition for rate-matching up to 256 channel bits
b[0] = b0 | (b0<<32);
b[1] = b[0];
b[2] = b[0];
@@ -668,16 +668,15 @@ void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci
b[5] = b[0];
b[6] = b[0];
b[7] = b[0];
AssertFatal(nrofPRB<=16,"Number of PRB >16\n");
//AssertFatal(E<=256,"Number of channelbits >32\n");
}
} else if (A >= 12) {
// Encoder reversal
payload = reverse_bits(payload, A);
polar_encoder_fast(&payload, b, 0,0,
NR_POLAR_UCI_PUCCH_MESSAGE_TYPE,
A,
nrofPRB);
E);
}
if (uci_on_pusch) {
@@ -692,7 +691,7 @@ void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci
N = 32;
} else {
// For polar-coded UCI, output depends on nrofPRB
N = 16 * nrofPRB;
N = E;
}
if ((nr_bit == 1 || nr_bit == 2) && Qm > 1) {
@@ -740,7 +739,7 @@ void nr_generate_pucch2(c16_t **txdataF,
uint64_t b[16] = {0}; // limit to 1024-bit encoded length
// M_bit is the number of bits of block b (payload after encoding)
uint16_t M_bit = nr_pucch_output_sequence_length(pucch_pdu->format_type, pucch_pdu->nr_of_symbols, pucch_pdu->prb_size, 0, 0, 0);
nr_uci_encoding(pucch_pdu->payload, pucch_pdu->n_bit, pucch_pdu->prb_size, false, M_bit, 0, &b[0]);
nr_uci_encoding(pucch_pdu->payload, pucch_pdu->n_bit, false, M_bit, 0, &b[0]);
/*
* Implementing TS 38.211
* Subclauses 6.3.2.5.1 Scrambling (PUCCH format 2)
@@ -810,9 +809,10 @@ void nr_generate_pucch2(c16_t **txdataF,
// int32_t *txptr;
int outSample = 0;
uint8_t startingSymbolIndex = pucch_pdu->start_symbol_index;
uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
int secondHopPRB = pucch_pdu->freq_hop_flag ? pucch_pdu->second_hop_prb : pucch_pdu->prb_start;
for (int l=0; l<pucch_pdu->nr_of_symbols; l++) {
uint16_t startingPRB = ((l==0) ? pucch_pdu->prb_start : secondHopPRB) + pucch_pdu->bwp_start;
// c_init calculation according to TS38.211 subclause
uint64_t temp_x2 = 1ll << 17;
temp_x2 *= 14UL * nr_slot_tx + l + startingSymbolIndex + 1;
@@ -827,22 +827,9 @@ void nr_generate_pucch2(c16_t **txdataF,
const bool nb_rb_is_even = frame_parms->N_RB_DL & 1;
const int halfRBs = frame_parms->N_RB_DL / 2;
const int baseRB = rb + startingPRB;
int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size + 12 * baseRB;
if (nb_rb_is_even) {
if (baseRB < halfRBs) // if number RBs in bandwidth is even and current PRB is lower band
re_offset += frame_parms->first_carrier_offset;
else
re_offset -= halfRBs;
} else {
if (baseRB < halfRBs) // if number RBs in bandwidth is odd and current PRB is lower band
re_offset += frame_parms->first_carrier_offset;
else if (baseRB > halfRBs) // if number RBs in bandwidth is odd and current PRB is upper band
re_offset += -halfRBs + 6;
else
re_offset += frame_parms->first_carrier_offset;
}
int re_offset = (l + startingSymbolIndex) * frame_parms->ofdm_symbol_size;
re_offset += ((12 * baseRB + frame_parms->first_carrier_offset)% frame_parms->ofdm_symbol_size);
//txptr = &txdataF[0][re_offset];
int k=0;
#ifdef DEBUG_NR_PUCCH_TX
int kk=0;
@@ -949,6 +936,28 @@ void nr_generate_pucch3_4(c16_t **txdataF,
uint16_t nrofPRB = pucch_pdu->prb_size;
uint16_t startingPRB = pucch_pdu->prb_start + pucch_pdu->bwp_start;
uint8_t add_dmrs = pucch_pdu->add_dmrs_flag;
#ifdef DEBUG_NR_PUCCH_TX
int ndmrs=0;
#endif
uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] = {
{(intraSlotFrequencyHopping==0)?0:1,(intraSlotFrequencyHopping==0)?1:0,(intraSlotFrequencyHopping==0)?0:1,0,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 4
{1,0,0,1,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 5
{0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 6
{0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 7
{0,1,0,0,0,1,0,0,0,0,0,0,0,0}, // PUCCH length = 8
{0,1,0,0,0,0,1,0,0,0,0,0,0,0}, // PUCCH length = 9
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,0,0,0}, // PUCCH length = 10
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0,0}, // PUCCH length = 11
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0}, // PUCCH length = 12
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0}, // PUCCH length = 13
{0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0} // PUCCH length = 14
};
#ifdef DEBUG_NR_PUCCH_TX
for (int l=0;l<nrofSymbols;l++)
if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) ndmrs++;
printf("\t [nr_generate_pucch3_4] nrofSymbols %d, nrofPRB %d, startingPRB %d, add_dmrs %d is_pi_over_2_bpsk_enabled %d\n",nrofSymbols,nrofPRB,startingPRB,add_dmrs,is_pi_over_2_bpsk_enabled);
#endif
M_bit = nr_pucch_output_sequence_length(pucch_pdu->format_type,
nrofSymbols,
@@ -957,7 +966,10 @@ void nr_generate_pucch3_4(c16_t **txdataF,
is_pi_over_2_bpsk_enabled,
add_dmrs);
nr_uci_encoding(pucch_pdu->payload, pucch_pdu->n_bit, nrofPRB, false, M_bit, 0, b);
#ifdef DEBUG_NR_PUCCH_TX
printf("\t [nr_generate_pucch3_4] nrofSymbols %d, nrofPRB %d, startingPRB %d, add_dmrs %d, ndmrs %d, is_pi_over_2_bpsk_enabled %d, M_bit %d\n",nrofSymbols,nrofPRB,startingPRB,add_dmrs,ndmrs,is_pi_over_2_bpsk_enabled,M_bit);
#endif
nr_uci_encoding(pucch_pdu->payload, pucch_pdu->n_bit, false, M_bit, 0, b);
/*
* Implementing TS 38.211
* Subclauses 6.3.2.6.1 Scrambling (PUCCH formats 3 and 4)
@@ -997,7 +1009,7 @@ void nr_generate_pucch3_4(c16_t **txdataF,
if (is_pi_over_2_bpsk_enabled == 0) {
// using QPSK if PUCCH format 3,4 and pi/2-BPSK is not configured, according to subclause 6.3.2.6.2
c16_t qpskSymbols[4] = {{baseVal, baseVal}, {-baseVal, baseVal}, {-baseVal, baseVal}, {-baseVal, -baseVal}};
c16_t qpskSymbols[4] = {{baseVal, baseVal}, {baseVal, -baseVal}, {-baseVal, baseVal}, {-baseVal, -baseVal}};
for (int i=0; i < m_symbol; i++) { // QPSK modulation subclause 5.1.3
int tmp = (btilde[2 * i] & 1) * 2 + (btilde[(2 * i) + 1] & 1);
d[i] = qpskSymbols[tmp];
@@ -1141,9 +1153,10 @@ void nr_generate_pucch3_4(c16_t **txdataF,
c16_t *yPtr = y_n + l * 12 * nrofPRB;
c16_t *zPtr = z + l * 12 * nrofPRB + k;
*zPtr = (c16_t){0};
for (int m = l * 12 * nrofPRB; m < (l + 1) * 12 * nrofPRB; m++) {
// for (int m = l * 12 * nrofPRB; m < (l + 1) * 12 * nrofPRB; m++) {
for (int m = 0; m < (12 * nrofPRB); m++) {
const c16_t angle = {lround(32767 * cos(2 * M_PI * m * k / (12 * nrofPRB))),
lround(32767 * sin(2 * M_PI * m * k / (12 * nrofPRB)))};
lround(-32767 * sin(2 * M_PI * m * k / (12 * nrofPRB)))};
c16_t tmp = c16mulShift(yPtr[m], angle, 15);
csum(*zPtr, *zPtr, c16mulRealShift(tmp, base, 15));
}
@@ -1195,19 +1208,6 @@ void nr_generate_pucch3_4(c16_t **txdataF,
int N_ZC = 12 * nrofPRB;
c16_t r_u_v_base[N_ZC];
uint32_t re_offset = 0;
uint8_t table_6_4_1_3_3_2_1_dmrs_positions[11][14] = {
{(intraSlotFrequencyHopping==0)?0:1,(intraSlotFrequencyHopping==0)?1:0,(intraSlotFrequencyHopping==0)?0:1,0,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 4
{1,0,0,1,0,0,0,0,0,0,0,0,0,0}, // PUCCH length = 5
{0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 6
{0,1,0,0,1,0,0,0,0,0,0,0,0,0}, // PUCCH length = 7
{0,1,0,0,0,1,0,0,0,0,0,0,0,0}, // PUCCH length = 8
{0,1,0,0,0,0,1,0,0,0,0,0,0,0}, // PUCCH length = 9
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,0,0,0}, // PUCCH length = 10
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0,0}, // PUCCH length = 11
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,0}, // PUCCH length = 12
{0,(add_dmrs==0?0:1),(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0}, // PUCCH length = 13
{0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0,0,(add_dmrs==0?0:1),0,(add_dmrs==0?1:0),0,(add_dmrs==0?0:1),0} // PUCCH length = 14
};
int k = 0;
for (int l=0; l<nrofSymbols; l++) {
@@ -1218,7 +1218,7 @@ void nr_generate_pucch3_4(c16_t **txdataF,
nr_group_sequence_hopping(pucch_GroupHopping,pucch_pdu->hopping_id,n_hop,nr_slot_tx,&u,&v); // calculating u and v value
// Next we proceed to calculate base sequence for DM-RS signal, according to TS 38.211 subclause 6.4.1.33
if (nrofPRB >= 3) { // TS 38.211 subclause 5.2.2.1 (Base sequences of length 36 or larger) applies
if (l==0 && nrofPRB >= 3) { // TS 38.211 subclause 5.2.2.1 (Base sequences of length 36 or larger) applies
int i = 4;
while (list_of_prime_numbers[i] < (12*nrofPRB)) i++;
@@ -1242,7 +1242,7 @@ void nr_generate_pucch3_4(c16_t **txdataF,
}
}
if (nrofPRB == 2) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-4) applies
if (l==0 && nrofPRB == 2) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-4) applies
for (int n = 0; n < 12 * nrofPRB; n++) {
c16_t table = {table_5_2_2_2_4_Re[u][n], table_5_2_2_2_4_Im[u][n]};
r_u_v_base[n] = c16mulRealShift(table, amp, 15);
@@ -1256,7 +1256,7 @@ void nr_generate_pucch3_4(c16_t **txdataF,
}
}
if (nrofPRB == 1) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-2) applies
if (l==0 && nrofPRB == 1) { // TS 38.211 subclause 5.2.2.2 (Base sequences of length less than 36 using table 5.2.2.2-2) applies
for (int n = 0; n < 12 * nrofPRB; n++) {
c16_t table = {table_5_2_2_2_2_Re[u][n], table_5_2_2_2_2_Im[u][n]};
r_u_v_base[n] = c16mulRealShift(table, amp, 15);
@@ -1275,12 +1275,12 @@ void nr_generate_pucch3_4(c16_t **txdataF,
alpha = nr_cyclic_shift_hopping(pucch_pdu->hopping_id,m0,mcs,l,startingSymbolIndex,nr_slot_tx);
for (int rb=0; rb<nrofPRB; rb++) {
const bool nb_rb_is_even = frame_parms->N_RB_DL & 1;
const bool nb_rb_is_even = (frame_parms->N_RB_DL & 1)==0;
const int halfRBs = frame_parms->N_RB_DL / 2;
const int baseRB = rb + startingPRB;
if ((intraSlotFrequencyHopping == 1) && (l<floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB
startingPRB = startingPRB + pucch_pdu->second_hop_prb;
if ((intraSlotFrequencyHopping == 1) && (l>=floor(nrofSymbols/2))) { // intra-slot hopping enabled, we need to calculate new offset PRB
startingPRB = pucch_pdu->second_hop_prb;
}
const int baseRB = rb + startingPRB;
re_offset = ((l + startingSymbolIndex) * frame_parms->ofdm_symbol_size);
//startingPRB = startingPRB + rb;
if (nb_rb_is_even) {
@@ -1304,7 +1304,7 @@ void nr_generate_pucch3_4(c16_t **txdataF,
printf("3 ");
#endif
} else if (baseRB > halfRBs) { // if number RBs in bandwidth is odd and current PRB is upper band
re_offset += 12 * (baseRB - halfRBs) + 6;
re_offset += 12 * (baseRB - halfRBs) - 6;
#ifdef DEBUG_NR_PUCCH_TX
printf("4 ");
#endif
@@ -1317,7 +1317,7 @@ void nr_generate_pucch3_4(c16_t **txdataF,
}
#ifdef DEBUG_NR_PUCCH_TX
printf("re_offset=%u,baseRB=%d\n", re_offset, baseRB);
printf("re_offset=%u,baseRB=%d\n", re_offset-((l + startingSymbolIndex) * frame_parms->ofdm_symbol_size), baseRB);
#endif
//txptr = &txdataF[0][re_offset];
@@ -1332,10 +1332,10 @@ void nr_generate_pucch3_4(c16_t **txdataF,
txdataF[0][re_offset] = z[n + k];
#ifdef DEBUG_NR_PUCCH_TX
printf(
"\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
"\tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(z(l=%d,n=%d)=(%d,%d))\n",
"\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,k=%d) mapping PUCCH DATA to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
"\tfirst_carrier_offset=%d \tz_pucch[%d]=txptr(%u)=(z(l=%d,n=%d)=(%d,%d))[%d]\n",
l,
rb,
startingPRB+rb,
n,
k,
amp,
@@ -1347,7 +1347,8 @@ void nr_generate_pucch3_4(c16_t **txdataF,
l,
n,
txdataF[0][re_offset].r,
txdataF[0][re_offset].i);
txdataF[0][re_offset].i,
re_offset-(l + startingSymbolIndex) * frame_parms->ofdm_symbol_size);
#endif
}
if (table_6_4_1_3_3_2_1_dmrs_positions[nrofSymbols-4][l] == 1) { // mapping DM-RS signal according to TS38.211 subclause 6.4.1.3.2
@@ -1355,12 +1356,13 @@ void nr_generate_pucch3_4(c16_t **txdataF,
txdataF[0][re_offset] = c16mulShift(angle, r_u_v_base[n + j], 15);
#ifdef DEBUG_NR_PUCCH_TX
printf(
"\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d) mapping DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
"\t [nr_generate_pucch3_4] (l=%d,rb=%d,n=%d,j=%d,alpha %f) mapping PUCCH DM-RS to RE \t amp=%d \tofdm_symbol_size=%d \tN_RB_DL=%d "
"\tfirst_carrier_offset=%d \tz_dm-rs[%d]=txptr(%u)=(r_u_v(l=%d,n=%d)=(%d,%d))\n",
l,
rb,
rb+startingPRB,
n,
j,
alpha,
amp,
frame_parms->ofdm_symbol_size,
frame_parms->N_RB_DL,
@@ -1370,7 +1372,8 @@ void nr_generate_pucch3_4(c16_t **txdataF,
l,
n,
txdataF[0][re_offset].r,
txdataF[0][re_offset].i);
txdataF[0][re_offset].i,
re_offset-(l + startingSymbolIndex) * frame_parms->ofdm_symbol_size);
#endif
}

View File

@@ -42,7 +42,7 @@ void nr_generate_pucch3_4(c16_t **txdataF,
const int nr_slot_tx,
const fapi_nr_ul_config_pucch_pdu *pucch_pdu);
void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, uint8_t nrofPRB, bool uci_on_pusch, uint16_t E, uint8_t Qm, uint64_t *b);
void nr_uci_encoding(uint64_t payload, uint8_t nr_bit, bool uci_on_pusch, uint16_t E, uint8_t Qm, uint64_t *b);
static const uint8_t list_of_prime_numbers[46] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,

View File

@@ -133,7 +133,7 @@ void nr_common_signal_procedures(PHY_VARS_gNB *gNB, int frame, int slot, const n
bitmap);
nr_generate_pss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg, fp);
nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg->cell_config.phy_cell_id.value, fp);
nr_generate_sss(txdataF[beam_nb][0], gNB->TX_AMP, ssb_start_symbol, cfg->cell_config.phy_cell_id.value, fp);
uint16_t slots_per_hf = (fp->slots_per_frame) >> 1;
int n_hf = slot < slots_per_hf ? 0 : 1;
@@ -681,8 +681,10 @@ nr_srs_info_t nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
*srs_est = nr_get_srs_signal(gNB, rxdataF, slot_rx, srs_pdu, &nr_srs_info, srs_received_signal, srs_received_noise);
stop_meas(&gNB->get_srs_signal_stats);
uint32_t signal_power_avg = 0;
c16_t srs_ls_estimated_channel[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS];
uint32_t signal_power_avg = 0;
int16_t noise_power_per_rb[srs_pdu->bwp_size];
memset(noise_power_per_rb, 0, srs_pdu->bwp_size * sizeof(int16_t));
if (*srs_est >= 0) {
start_meas(&gNB->srs_channel_estimation_stats);
@@ -732,7 +734,7 @@ nr_srs_info_t nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
T_INT(gNB->Mod_id),
T_INT(srs_pdu->rnti),
T_INT(frame_rx),
T_INT(0),
T_INT(slot_rx),
T_INT(ant_rx_ind),
T_INT(p_ind),
T_BUFFER(srs_estimated_channel_freq[ant_rx_ind][p_ind], N_symb_SRS * ofdm_symbol_size * sizeof(c16_t)));
@@ -741,14 +743,13 @@ nr_srs_info_t nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
T_INT(gNB->Mod_id),
T_INT(srs_pdu->rnti),
T_INT(frame_rx),
T_INT(0),
T_INT(slot_rx),
T_INT(ant_rx_ind),
T_INT(p_ind),
T_BUFFER(srs_estimated_channel_time_shifted[ant_rx_ind][p_ind],
NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size * sizeof(c16_t)));
}
}
signal_power_avg /= (nb_antennas_rx * N_ap);
signal_power_avg = max(signal_power_avg, 1);
@@ -931,10 +932,11 @@ static void handle_pucch(PHY_VARS_gNB *gNB, c16_t **rxdataF, const NR_gNB_PUCCH_
nr_decode_pucch0(gNB, rxdataF, pucch->frame, pucch->slot, uci_pdu_format0, pucch_pdu);
break;
case 2:
case 3:
uci->pdu_type = NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE;
uci->pdu_size = sizeof(nfapi_nr_uci_pucch_pdu_format_2_3_4_t);
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2 = &uci->pucch_pdu_format_2_3_4;
nr_decode_pucch2(gNB, rxdataF, pucch->frame, pucch->slot, uci_pdu_format2, pucch_pdu);
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu_format2_3_4 = &uci->pucch_pdu_format_2_3_4;
nr_decode_pucch2_3(gNB, rxdataF, pucch->frame, pucch->slot, uci_pdu_format2_3_4, pucch_pdu);
break;
default:
AssertFatal(1 == 0, "Only PUCCH formats 0 and 2 are currently supported\n");

View File

@@ -86,7 +86,7 @@ int main(int argc, char **argv)
__attribute__((unused)) struct sigaction oldaction;
sigaction(SIGINT, &sigint_action, &oldaction);
int i;
int i;
double SNR, snr0 = -2.0, snr1 = 2.0;
double cfo = 0;
uint8_t snr1set = 0;
@@ -100,7 +100,7 @@ int main(int argc, char **argv)
channel_desc_t *UE2gNB;
int format = 0;
FILE *input_fd = NULL;
int16_t amp = 0x7FFF;
int16_t amp = 0x1000;
int nr_slot_tx = 0;
int nr_frame_tx = 0;
uint64_t actual_payload = 0, payload_received = 0;
@@ -108,11 +108,8 @@ int main(int argc, char **argv)
int nr_bit = 1; // maximum value possible is 2
uint8_t m0 = 0; // higher layer paramater initial cyclic shift
uint8_t nrofSymbols = 1; // number of OFDM symbols can be 1-2 for format 1
// resource allocated see 9.2.1, 38.213 for more info.should be actually present in the resource set provided
uint8_t startingSymbolIndex = 0;
uint16_t startingPRB = 0;
// PRB number not sure see 9.2.1, 38.213 for more info. Should be actually present in the resource set provided
uint16_t startingPRB_intraSlotHopping = 0;
uint8_t startingSymbolIndex = 0;
uint16_t startingPRB = 0, startingPRB_intraSlotHopping = 0;
uint16_t nrofPRB = 2;
uint8_t timeDomainOCC = 0;
SCM_t channel_model = AWGN; // Rayleigh1_anticorr;
@@ -123,7 +120,9 @@ int main(int argc, char **argv)
int N_RB_DL = 273, mu = 1;
float target_error_rate = 0.001;
int frame_length_complex_samples;
// int frame_length_complex_samples_no_prefix;
NR_DL_FRAME_PARMS *frame_parms;
// unsigned char frame_type = 0;
int loglvl = OAILOG_WARNING;
int sr_flag = 0;
int pucch_DTX_thres = 0;
@@ -139,7 +138,8 @@ int main(int argc, char **argv)
int c;
int nrofSymbols_set = 0;
while ((c = getopt(argc, argv, "--:O:f:hA:f:g:i:I:P:B:b:t:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:cd:C")) != -1) {
int freq_hop_flag=0;
while ((c = getopt(argc, argv, "--:O:f:hA:f:g:i:I:P:B:b:t:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:cd:CH:")) != -1) {
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
if (c == 1 || c == '-' || c == 'O')
@@ -299,6 +299,9 @@ int main(int argc, char **argv)
if ((format == 1 || format == 3) && nrofSymbols_set == 0)
nrofSymbols = 14;
break;
case 'H':
freq_hop_flag = 1;
break;
case 'm':
m0 = atoi(optarg);
break;
@@ -374,12 +377,14 @@ int main(int argc, char **argv)
printf("Initializing gNodeB for mu %d, N_RB_DL %d, n_rx %d\n", mu, N_RB_DL, n_rx);
if ((format != 0) && (format != 1) && (format != 2)) {
if ((format != 0) && (format != 1) && (format != 2) && (format != 3)) {
printf("PUCCH format %d not supported\n", format);
exit(0);
}
AssertFatal(((format < 2) && (nr_bit < 3) && (actual_payload < 5)) || ((format == 2) && (nr_bit > 2) && (nr_bit < 65)),
AssertFatal(((format < 2) && (nr_bit < 3) && (actual_payload < 5)) ||
((format == 2) && (nr_bit > 2) && (nr_bit < 65)) ||
((format == 3) && (nr_bit > 2) && (nr_bit < 65)),
"illegal combination format %d, nr_bit %d\n",
format,
nr_bit);
@@ -463,7 +468,7 @@ int main(int argc, char **argv)
AssertFatal(1 == 0, "Either nr_bit %d or sr_flag %d must be non-zero\n", nr_bit, sr_flag);
}
startingPRB_intraSlotHopping = N_RB_DL - 1;
startingPRB_intraSlotHopping = N_RB_DL - 1;
uint32_t hopping_id = Nid_cell;
uint32_t dmrs_scrambling_id = 0;
uint32_t data_scrambling_id = 0;
@@ -488,7 +493,6 @@ int main(int argc, char **argv)
pucch_tx_pdu.hopping_id = hopping_id;
pucch_tx_pdu.group_hop_flag = 0;
pucch_tx_pdu.sequence_hop_flag = 0;
pucch_tx_pdu.freq_hop_flag = 0;
pucch_tx_pdu.mcs = mcs;
pucch_tx_pdu.initial_cyclic_shift = 0;
pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping;
@@ -503,8 +507,6 @@ int main(int argc, char **argv)
pucch_tx_pdu.prb_start = startingPRB;
pucch_tx_pdu.hopping_id = hopping_id;
pucch_tx_pdu.group_hop_flag = 0;
pucch_tx_pdu.sequence_hop_flag = 0;
pucch_tx_pdu.freq_hop_flag = 1;
pucch_tx_pdu.initial_cyclic_shift = m0;
pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping;
pucch_tx_pdu.time_domain_occ_idx = timeDomainOCC;
@@ -521,11 +523,33 @@ int main(int argc, char **argv)
pucch_tx_pdu.hopping_id = hopping_id;
pucch_tx_pdu.group_hop_flag = 0;
pucch_tx_pdu.sequence_hop_flag = 0;
pucch_tx_pdu.freq_hop_flag = 0;
pucch_tx_pdu.dmrs_scrambling_id = dmrs_scrambling_id;
pucch_tx_pdu.data_scrambling_id = data_scrambling_id;
pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping;
}
if (format == 3) {
pucch_tx_pdu.format_type = 3;
pucch_tx_pdu.rnti = 0x1234;
pucch_tx_pdu.n_bit = nr_bit;
pucch_tx_pdu.payload = actual_payload;
pucch_tx_pdu.nr_of_symbols = nrofSymbols;
pucch_tx_pdu.start_symbol_index = startingSymbolIndex;
pucch_tx_pdu.bwp_start = 0;
pucch_tx_pdu.prb_start = startingPRB;
pucch_tx_pdu.prb_size = nrofPRB;
pucch_tx_pdu.hopping_id = hopping_id;
pucch_tx_pdu.sequence_hop_flag = 0;
pucch_tx_pdu.freq_hop_flag = 1;
pucch_tx_pdu.dmrs_scrambling_id = dmrs_scrambling_id;
pucch_tx_pdu.data_scrambling_id = data_scrambling_id;
pucch_tx_pdu.second_hop_prb = startingPRB_intraSlotHopping;
}
if (freq_hop_flag > 0 && nrofSymbols > 1) {
pucch_tx_pdu.freq_hop_flag = 1;
pucch_tx_pdu.second_hop_prb = N_RB_DL - nrofPRB;
} else
pucch_tx_pdu.freq_hop_flag = 0;
pucch_GroupHopping_t PUCCH_GroupHopping = pucch_tx_pdu.group_hop_flag + (pucch_tx_pdu.sequence_hop_flag << 1);
double tx_level_fp = 100.0;
@@ -542,8 +566,10 @@ int main(int argc, char **argv)
nr_generate_pucch0(txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu);
} else if (format == 1 && do_DTX == 0) {
nr_generate_pucch1(txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu);
} else if (do_DTX == 0) {
} else if (format == 2 && do_DTX == 0) {
nr_generate_pucch2(txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu);
} else if (format == 3 && do_DTX == 0) {
nr_generate_pucch3_4(txdataF, frame_parms, amp, nr_slot_tx, &pucch_tx_pdu);
}
// SNR Computation
@@ -576,7 +602,7 @@ int main(int argc, char **argv)
}
random_channel(UE2gNB, 0);
freq_channel(UE2gNB, N_RB_DL, 2 * N_RB_DL + 1, 15 << mu);
freq_channel(UE2gNB, N_RB_DL, 12 * N_RB_DL + 1, 15 << mu);
for (int symb = 0; symb < nrofSymbols; symb++) {
int i0 = (startingSymbolIndex + symb) * gNB->frame_parms.ofdm_symbol_size;
for (int re = 0; re < N_RB_DL * 12; re++) {
@@ -588,10 +614,10 @@ int main(int argc, char **argv)
double txr = (double)(((int16_t *)txdataF[0])[(i << 1)]);
double txi = (double)(((int16_t *)txdataF[0])[1 + (i << 1)]);
double rxr = {0}, rxi = {0};
for (int l = 0; l < UE2gNB->channel_length; l++) {
rxr = txr * UE2gNB->chF[aarx][l].r - txi * UE2gNB->chF[aarx][l].i;
rxi = txr * UE2gNB->chF[aarx][l].i + txi * UE2gNB->chF[aarx][l].r;
}
//for (int l = 0; l < UE2gNB->channel_length; l++) {
rxr = txr * UE2gNB->chF[aarx][re].r - txi * UE2gNB->chF[aarx][re].i;
rxi = txr * UE2gNB->chF[aarx][re].i + txi * UE2gNB->chF[aarx][re].r;
//}
double rxr_tmp = rxr * phasor.r - rxi * phasor.i;
rxi = rxr * phasor.i + rxi * phasor.r;
rxr = rxr_tmp;
@@ -686,7 +712,8 @@ int main(int argc, char **argv)
pucch_pdu.prb_size = 1;
pucch_pdu.bwp_start = 0;
pucch_pdu.bwp_size = N_RB_DL;
if (nrofSymbols > 1) {
if (freq_hop_flag > 0 && nrofSymbols > 1) {
pucch_pdu.freq_hop_flag = 1;
pucch_pdu.second_hop_prb = N_RB_DL - 1;
} else
@@ -730,8 +757,11 @@ int main(int argc, char **argv)
pucch_pdu.prb_size = 1;
pucch_pdu.bwp_start = 0;
pucch_pdu.bwp_size = N_RB_DL;
pucch_pdu.freq_hop_flag = 1;
pucch_pdu.second_hop_prb = N_RB_DL - 2;
if (freq_hop_flag > 0)
pucch_pdu.freq_hop_flag = 1;
else
pucch_pdu.freq_hop_flag = 0;
pucch_pdu.second_hop_prb = N_RB_DL - 1;
pucch_pdu.time_domain_occ_idx = timeDomainOCC;
nr_decode_pucch1(gNB, rxdataF, nr_frame_tx, nr_slot_tx, &uci_pdu, &pucch_pdu);
@@ -748,11 +778,11 @@ int main(int argc, char **argv)
else if ((!confidence_lvl && !harq_list[0].harq_value) || (!confidence_lvl && nr_bit == 2 && !harq_list[1].harq_value))
ack_nack_errors++;
}
} else if (format == 2) {
} else if (format == 2 || format == 3) {
nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu = {0};
nfapi_nr_pucch_pdu_t pucch_pdu = {0};
pucch_pdu.rnti = 0x1234;
pucch_pdu.format_type = format;
pucch_pdu.subcarrier_spacing = 1;
pucch_pdu.group_hop_flag = PUCCH_GroupHopping & 1;
pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping >> 1) & 1;
@@ -768,12 +798,12 @@ int main(int argc, char **argv)
pucch_pdu.prb_start = startingPRB;
pucch_pdu.dmrs_scrambling_id = dmrs_scrambling_id;
pucch_pdu.data_scrambling_id = data_scrambling_id;
if (nrofSymbols > 1) {
if (freq_hop_flag > 0 && nrofSymbols > 1) {
pucch_pdu.freq_hop_flag = 1;
pucch_pdu.second_hop_prb = N_RB_DL - 1;
pucch_pdu.second_hop_prb = N_RB_DL - nrofPRB;
} else
pucch_pdu.freq_hop_flag = 0;
nr_decode_pucch2(gNB, rxdataF, nr_frame_tx, nr_slot_tx, &uci_pdu, &pucch_pdu);
nr_decode_pucch2_3(gNB, rxdataF, nr_frame_tx, nr_slot_tx, &uci_pdu, &pucch_pdu);
int csi_part1_bytes = pucch_pdu.bit_len_csi_part1 >> 3;
if ((pucch_pdu.bit_len_csi_part1 & 7) > 0)
csi_part1_bytes++;

View File

@@ -632,7 +632,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = calloc(chan_desc->channel_length, sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = calloc(1200, sizeof(struct complexd));
chan_desc->chF[i] = calloc(273*12, sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = calloc(nb_tx*nb_rx, sizeof(struct complexd));
@@ -694,7 +694,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd));
chan_desc->chF[i] = (struct complexd *) malloc(273*12 * sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));
@@ -791,7 +791,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd));
chan_desc->chF[i] = (struct complexd *) malloc(273*12 * sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));
@@ -847,7 +847,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd));
chan_desc->chF[i] = (struct complexd *) malloc(273*12 * sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));
@@ -902,7 +902,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd));
chan_desc->chF[i] = (struct complexd *) malloc(273*12 * sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));
@@ -957,7 +957,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd));
chan_desc->chF[i] = (struct complexd *) malloc(273*12 * sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));
@@ -1012,7 +1012,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd));
chan_desc->chF[i] = (struct complexd *) malloc(273*12 * sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));
@@ -1068,7 +1068,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd));
chan_desc->chF[i] = (struct complexd *) malloc(273*12 * sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));
@@ -1124,7 +1124,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
chan_desc->ch[i] = (struct complexd *) malloc(chan_desc->channel_length * sizeof(struct complexd));
for (i = 0; i<nb_tx*nb_rx; i++)
chan_desc->chF[i] = (struct complexd *) malloc(1200 * sizeof(struct complexd));
chan_desc->chF[i] = (struct complexd *) malloc(273*12 * sizeof(struct complexd));
for (i = 0; i<chan_desc->nb_taps; i++)
chan_desc->a[i] = (struct complexd *) malloc(nb_tx*nb_rx * sizeof(struct complexd));

View File

@@ -236,53 +236,56 @@ add_physim_test(physim.5g.nr_ulschsim.test4 "106 PRBs 4-layer MIMO" nr_ulschsim
###### nr_pucchsim unit test ######
####################################################################################
add_physim_test(physim.5g.nr_pucchsim.test1 "Format 0 1-bit ACK miss 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 1 -s-2 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test2 "Format 0 2-bit ACK miss 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 2 -s-2 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test3 "Format 0 2-bit ACK miss, 1-bit SR 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 2 -s-2 -c -n3000)
add_physim_test(physim.5g.nr_pucchsim.test4 "Format 2 3-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 3 -s0 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test5 "Format 2 4-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 4 -s0 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test6 "Format 2 5-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 5 -s1 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test7 "Format 2 6-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 6 -s2 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test8 "Format 2 7-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 7 -s3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test9 "Format 2 8-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 8 -s4 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test10 "Format 2 9-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 9 -s5 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test11 "Format 2 10-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 10 -s6 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test12 "Format 2 11-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 11 -s6 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test13 "Format 2 12-bit 4/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q4 -b 12 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test14 "Format 2 19-bit 4/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q4 -b 19 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test15 "Format 2 12-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 12 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test16 "Format 2 19-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 19 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test17 "Format 2 32-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 32 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test18 "Format 2 32-bit 16/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q16 -b 32 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test19 "Format 2 64-bit 16/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q16 -b 64 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test20 "Format 0 1-bit Ack miss 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 1 -s-2 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test21 "Format 0 2-bit Ack miss 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 2 -s-2 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test22 "Format 0 2-bit Ack miss+SR 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 2 -s-2 -c -n3000)
add_physim_test(physim.5g.nr_pucchsim.test23 "Format 2 4-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 4 -s-8 -S0 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test24 "Format 2 7-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 7 -s3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test25 "Format 2 11-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 11 -s6 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test26 "Format 2 12-bit 8/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q8 -b 12 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test27 "Format 2 19-bit 8/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q8 -b 19 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test28 "Format 2 64-bit 16/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test29 "Format 2 64-bit 16/273 PRB Delay 2us" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s0 -S7 -d 2 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test30 "Format 1 NACK number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 1 -B 0 -s-8 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test31 "Format 1 ACK number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 1 -B 1 -s-8 -n3000)
add_physim_test(physim.5g.nr_pucchsim.test32 "Format 1 (NACK,NACK) number of symbols = 4, 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test33 "Format 1 (ACK,NACK) number of symbols = 4, 273PRB with SR" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 1 -s-8 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test34 "Format 1 (NACK,ACK) number of symbols = 4, 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 2 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test35 "Format 1 (ACK,ACK) number of symbols = 4, 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 3 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test36 "Format 1 NACK number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 1 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test37 "Format 1 ACK number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 1 -B 1 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test38 "Format 1 (NACK,NACK) number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test39 "Format 1 (ACK,NACK) number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 1 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test40 "Format 1 (NACK,ACK) number of symbols = 8, 273PRB with SR" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 2 -s-8 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test41 "Format 1 (ACK,ACK) number of symbols = 8, 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 3 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test42 "Format 1 NACK number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 1 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test43 "Format 1 ACK number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 1 -B 1 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test44 "Format 1 (NACK,NACK) number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 0 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test45 "Format 1 (ACK,NACK) number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 1 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test46 "Format 1 (NACK,ACK) number of symbols = 14, 273PRB with SR" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 2 -s-8 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test47 "Format 1 (ACK,ACK) number of symbols = 14, 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 3 -s-8 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test1 "Format 0 1-bit ACK miss 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 1 -s-2 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test2 "Format 0 2-bit ACK miss 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 2 -s-2 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test3 "Format 0 2-bit ACK miss, 1-bit SR 106 PRB" nr_pucchsim -R 106 -i 1 -P 0 -b 2 -s-2 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test4 "Format 2 3-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 3 -s0 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test5 "Format 2 4-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 4 -s0 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test6 "Format 2 5-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 5 -s1 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test7 "Format 2 6-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 6 -s2 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test8 "Format 2 7-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 7 -s3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test9 "Format 2 8-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 8 -s4 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test10 "Format 2 9-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 9 -s5 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test11 "Format 2 10-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 10 -s6 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test12 "Format 2 11-bit 2/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -b 11 -s6 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test13 "Format 2 12-bit 4/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q4 -b 12 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test14 "Format 2 19-bit 4/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q4 -b 19 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test15 "Format 2 12-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 12 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test16 "Format 2 19-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 19 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test17 "Format 2 32-bit 8/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q8 -b 32 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test18 "Format 2 32-bit 16/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q16 -b 32 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test19 "Format 2 64-bit 16/106 PRB" nr_pucchsim -R 106 -i 1 -P 2 -q16 -b 64 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test20 "Format 0 1-bit Ack miss 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 1 -s-2 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test21 "Format 0 2-bit Ack miss 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 2 -s-2 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test22 "Format 0 2-bit Ack miss+SR 273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 0 -b 2 -s-2 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test23 "Format 2 4-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 4 -s-8 -S0 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test24 "Format 2 7-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 7 -s3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test25 "Format 2 11-bit 2/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -b 11 -s6 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test26 "Format 2 12-bit 8/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q8 -b 12 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test27 "Format 2 19-bit 8/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q8 -b 19 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test28 "Format 2 64-bit 16/273 PRB" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s-3 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test29 "Format 2 64-bit 16/273 PRB Delay 2us" nr_pucchsim -R 273 -z8 -i 1 -P 2 -q16 -b 64 -s0 -S7 -d 2 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test30 "Format 1 NACK number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 1 -B 0 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test31 "Format 1 ACK number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 1 -B 1 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test32 "Format 1 (NACK,NACK) number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 0 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test33 "Format 1 (ACK,NACK) number of symbols = 4 273PRB with SR" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 1 -s-10 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test34 "Format 1 (NACK,ACK) number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 2 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test35 "Format 1 (ACK,ACK) number of symbols = 4 273PRB" nr_pucchsim -R 273 -z8 -i 4 -P 1 -b 2 -B 3 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test36 "Format 1 NACK number of symbols = 8 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 1 -B 0 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test37 "Format 1 ACK number of symbols = 8 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 1 -B 1 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test38 "Format 1 (NACK,NACK) number of symbols = 8 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 0 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test39 "Format 1 (ACK,NACK) number of symbols = 8 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 1 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test40 "Format 1 (NACK,ACK) number of symbols = 8 273PRB with SR" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 2 -s-10 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test41 "Format 1 (ACK,ACK) number of symbols = 8 273PRB" nr_pucchsim -R 273 -z8 -i 8 -P 1 -b 2 -B 3 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test42 "Format 1 NACK number of symbols = 14 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 1 -B 0 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test43 "Format 1 ACK number of symbols = 14 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 1 -B 1 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test44 "Format 1 (NACK,NACK) number of symbols = 14 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 0 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test45 "Format 1 (ACK,NACK) number of symbols = 14 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 1 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test46 "Format 1 (NACK,ACK) number of symbols = 14 273PRB with SR" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 2 -s-10 -c -n1000)
add_physim_test(physim.5g.nr_pucchsim.test47 "Format 1 (ACK,ACK) number of symbols = 14 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 1 -b 2 -B 3 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test48 "Format 3 4-bits number of symbols = 14 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 3 -q1 -b 3 -B 3 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test49 "Format 3 7-bits number of symbols = 14 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 3 -q1 -b 7 -B 3 -s-10 -n1000)
add_physim_test(physim.5g.nr_pucchsim.test50 "Format 3 11-bits number of symbols = 14 273PRB" nr_pucchsim -R 273 -z8 -i 14 -P 3 -q1 -b 7 -B 3 -s-10 -n1000)
####################################################################################
###### nr_ulsim unit test ######