PHY Abstraction

../../_images/phy_abs_api.png
The physical layer (PHY) abstraction method follows a two-step approach:
  1. The signal-to-interference-plus-noise ratio (SINR) that a single codeword experiences across multiple streams, computed via PostEqualizationSINR, is aggregated into a single effective SINR value. The effective SINR is chosen so that, if all subcarriers and streams experienced it uniformly, the resulting block error rate (BLER) would remain approximately the same.

  2. The effective SINR is then mapped to a BLER value via precomputed tables, based on the code block size.

The transport BLER (TBLER) can be finally computed as the probability that at least one of the code blocks in the transport block is not correctly received.

For a usage example of PHY abstraction in Sionna, refer to the Physical Layer Abstraction notebook.

Next, we formally describe the general principle of effective SINR mapping (ESM) and the exponential ESM (EESM) model.

We assume the presence of multiple channel “links” i=1,,N, each characterized by its own SINRi. In principle, different codeword symbols can be transmitted on the same link, meaning they experience the same SINR.
Let I(x) measure the “quality” of a link with SINR value x, the exact interpretation of which will be discussed later.
The effective SINR, SINReff, is defined as the SINR of a single-link channel whose quality matches the average quality of the multi-link channel:
I(SINReff)=1Ni=1NI(SINRi)
  SINReff=I1(1Ni=1NI(SINRi))
The form of the quality measure I depends on the selected ESM method.
In the exponential ESM (EESM) model, the link quality is defined as:
IEESM(x):=exp(x/β).

Thus, the corresponding effective SINR can be expressed as:

(60)SINReffEESM=βlog(1Ni=1NeSINRi/β).
In the following we outline the derivation of this expression, assuming the transmission of BPSK (±1) modulated codewords uA and uB, with a Hamming distance of d.

Single-link channel. In the basic case with one link (N=1), each codeword symbol experiences the same channel gain ρ and complex noise power N0, resulting in the received real signal:

yjk=ρujk+wj,k{A,B}, j
where j indexes the symbols and wjN(0,N0/2) is additive real noise. Hence, the SNR (as well as the SINR, since interference is not considered) is ρ/N0.
Codeword uA is incorrectly decoded as uB when the noise projected along the direction uAuB exceeds the half distance between the two codewords, equal to dρ. Hence, the pairwise error probability PN=1(uAuB) can be expressed as:
(61)PN=1(uAuB)=Pr(ξN0/2>dρ),ξN(0,1)=Q(2dSINR)edSINR
where Q(x) is the tail distribution function of the standard normal distribution and the inequality stems from the Chernoff bound Q(x)ex2/2, for all x.
Two-link channel. We now assume that each symbol is transmitted through channel link 1 or 2 with probabilities p1 and p2, respectively. Link i=1,2 is characterized by its channel gain ρi.
Consider two received noiseless codewords uA,uB where 1= and 2=d symbols experience channel 1 and 2, respectively. Then, their half distance is 1ρ1+2ρ2 and the conditioned pairwise error probability equals:
(62)PN=2(uAuB|1,2)=Pr(N0/2ξ>1ρ1+2ρ2)=Q(21SINR1+22SINR2).

To obtain the pairwise codeword error probability, we average expression (62) across all (1,2) events:

(63)PN=2(uAuB)==0d(d)p1p2dPN=2(uAuB|1=,2=d)=0d(d)(p1eSINR1)(p2eSINR2)d=(p1eSINR1+p2eSINR2)d

where the inequality stems again from the Chernoff bound.

Multi-link channel. Expression (63) extends to a multi-link channel (N2) as follows:

(64)PN(uAuB)(i=1NpieSINRi)d.

EESM expression. By equating the multi-link pairwise error probability bound (64) with the analogous single-link expression (61), we recognize that the multi-link channel is analogous to a single-link channel with SINR:

SINReffEESM:=log(i=1NpieSINRi)
where SINReffEESM is the effective SINR for the multi-link channel under the EESM model.
If we further assume that all links are equiprobable, i.e., pi=1/N for all i, then we obtain expression (60) with β=1.

Note that the introduction of parameter β in (60) is useful to adapt the EESM formula to different modulation and coding schemes (MCS), since the argument above holds for BPSK modulation only. Hence, β shall depend on the used MCS, as shown in [5GLENA].

class sionna.sys.EffectiveSINR(*args, precision=None, **kwargs)[source]

Class template for computing the effective SINR from input SINR values across multiple subcarriers and streams

Input:
  • sinr ([…, num_ofdm_symbols, num_subcarriers, num_ut, num_streams_per_ut], tf.float) – Post-equalization SINR in linear scale for different OFDM symbols, subcarriers, users and streams. If one entry is zero, the corresponding stream is considered as not utilized.

  • mcs_index ([…, num_ut], tf.int32 (default: None)) – Modulation and coding scheme (MCS) index for each user

  • mcs_table_index ([…, num_ut], tf.int32 (default: None)) – MCS table index for each user. For further details, refer to the Note.

  • mcs_category ([…, num_ut], tf.int32 (default: None)) – MCS table category for each user. For further details, refer to the Note.

  • per_stream (bool (default: False)) – If True, the effective SINR is computed on a per-user and per-stream basis and is aggregated across different subcarriers. If False, the effective SINR is computed on a per-user basis and is aggregated across streams and subcarriers.

  • kwargs (dict) – Additional input parameters

Output:

sinr_eff (([…, num_ut, num_streams_per_ut] | […, num_ut]), tf.float) – Effective SINR in linear scale for each user and associated stream. If per_stream is True, then sinr_eff has shape […, num_ut, num_streams_per_rx], and sinr_eff[..., u, s] is the effective SINR for stream s of user u across all subcarriers. If per_stream is False, then sinr_eff has shape […, num_ut], and sinr_eff[..., u] is the effective SINR for user u across all streams and subcarriers.

calibrate()[source]

Optional method for calibrating the Effective SINR model

class sionna.sys.EESM(load_beta_table_from='default', sinr_eff_min_db=-30, sinr_eff_max_db=30, precision=None)[source]

Computes the effective SINR from input SINR values across multiple subcarriers and streams via the exponential effective SINR mapping (EESM) method

Let SINRu,c,s>0 be the SINR experienced by user u on subcarrier c=1,,C, and stream s=1,,Sc. If per_stream is False, it computes the effective SINR aggregated across all utilized streams and subcarriers for each user u:

SINRueff=βulog(1CSc=1Cs=1SceSINRu,c,sβu),u

where β>0 is a parameter depending on the Modulation and Coding Scheme (MCS) of user u.

If per_stream is True, it computes the effective SINR aggregated across subcarriers, for each user u and associated stream s:

SINRu,seff=βulog(1Cc=1CeSINRu,c,sβu),u,s.
Parameters:
  • load_beta_table_from (str) – File name from which the tables containing the values of β parameters are loaded

  • sinr_eff_min_db (float (default: -30)) – Minimum effective SINR value [dB]. Useful to avoid numerical errors

  • sinr_eff_max_db (float (default: 50)) – Maximum effective SINR value [dB]. Useful to avoid numerical errors

  • precision (None (default) | “single” | “double”) – Precision used for internal calculations and outputs. If set to None, precision is used.

Input:
  • sinr ([…, num_ofdm_symbols, num_subcarriers, num_ut, num_streams_per_ut], tf.float) – Post-equalization SINR in linear scale for different OFDM symbols, subcarriers, users and streams. If one entry is zero, the corresponding stream is considered as not utilized.

  • mcs_index ([…, num_ut], tf.int32) – Modulation and coding scheme (MCS) index for each user

  • mcs_table_index ([…, num_ut], tf.int32 (default: 1)) – MCS table index for each user. For further details, refer to the Note.

  • mcs_category ([…, num_ut], tf.int32 (default: None)) – MCS table category for each user. For further details, refer to the Note.

  • per_stream (bool (default: False)) – If True, then the effective SINR is computed on a per-user and per-stream basis and is aggregated across different subcarriers. If False, then the effective SINR is computed on a per-user basis and is aggregated across streams and subcarriers.

Output:

sinr_eff (([…, num_ut, num_streams_per_ut] | […, num_ut]), tf.float) – Effective SINR in linear scale for each user and associated stream. If per_stream is True, then sinr_eff has shape […, num_ut, num_streams_per_rx], and sinr_eff[..., u, s] is the effective SINR for stream s of user u across all subcarriers. If per_stream is False, then sinr_eff has shape […, num_ut], and sinr_eff[..., u] is the effective SINR for user u across all streams and subcarriers.

Note

If the input SINR is zero for a specific stream, the stream is considered unused and does not contribute to the effective SINR computation.

Example

from sionna.phy import config
from sionna.sys import EESM
from sionna.phy.utils import db_to_lin

batch_size = 10
num_ofdm_symbols = 12
num_subcarriers = 32
num_ut = 15
num_streams_per_ut = 2

# Generate random MCS indices
mcs_index = config.tf_rng.uniform([batch_size, num_ut],
                                  minval=0, maxval=27, dtype=tf.int32)

# Instantiate the EESM object
eesm = EESM()

# Generate random SINR values
sinr_db = config.tf_rng.uniform([batch_size,
                                 num_ofdm_symbols,
                                 num_subcarriers,
                                 num_ut,
                                 num_streams_per_ut],
                                 minval=-5, maxval=30)
sinr = db_to_lin(sinr_db)

# Compute the effective SINR for each receiver
# [batch_size, num_rx]
sinr_eff = eesm(sinr, mcs_index, mcs_table_index=1, per_stream=False)
print(sinr_eff.shape)
# (10, 15)

# Compute the per-stream effective SINR for each receiver
# [batch_size, num_rx, num_streams_per_rx]
sinr_eff_per_stream = eesm(sinr, mcs_index, mcs_table_index=2, per_stream=True)
print(sinr_eff_per_stream.shape)
# (10, 15, 2)
property beta_table

Maps MCS indices to the corresponding parameters, commonly called β, calibrating the Exponential Effective SINR Map (EESM) method. It has the form beta_table['index'][mcs_table_index][mcs]

Type:

dict (read-only)

property beta_table_filenames

Get/set the absolute path name of the JSON file containing the mapping between MCS and EESM beta parameters, stored in beta

Type:

str | list of str

property beta_tensor

Tensor corresponding to self.beta_table

Type:

[n_tables, n_mcs], tf.float (read-only)

validate_beta_table()[source]

Validates the EESM beta parameter dictionary self.beta_table

Output:

bool | ValueError – Returns True if self.beta_table has a valid structure. Else, a ValueError is raised

class sionna.sys.PHYAbstraction(interp_fun=None, mcs_decoder_fun=None, transport_block_fun=None, sinr_effective_fun=None, load_bler_tables_from='default', snr_db_interp_min_max_delta=(-5, 30.01, 0.1), cbs_interp_min_max_delta=(24, 8448, 100), bler_interp_delta=0.01, precision=None, **kwargs)[source]

Class for physical layer abstraction

For a given signal-to-interference-plus-noise-ratio (SINR) provided on a per-stream basis, and for a given modulation order, coderate, and number of coded bits specified for each user, it produces the corresponding number of successfully decoded bits, HARQ feedback, effective SINR, block error rate (BLER), and transport BLER (TBLER).

At object instantiation, precomputed BLER tables are loaded and interpolated on a fine (SINR, code block size) grid for each modulation and coding scheme (MCS) index.

When the object is called, the post-equalization SINR is first converted to an effective SINR. Then, the effective SINR is used to retrieve the BLER from pre-computed and interpolated tables. Finally, the BLER determines the TBLER, which represents the probability that at least one code block is incorrectly received.

Parameters:
  • interp_fun (instance of Interpolate | None (default)) – Function for interpolating data defined on rectangular or unstructured grids, used for BLER and SINR interpolation. If None, it is set to an instance of SplineGriddataInterpolation.

  • mcs_decoder_fun (instance of MCSDecoder | None (default)) – Function mapping MCS indices to modulation order and coderate. If None, it is set to an instance of MCSDecoderNR.

  • transport_block_fun (instance of TransportBlock | None (default)) – Function computing the number and size (measured in bits) of code blocks within a transport block. If None, it is set to an instance of TransportBlockNR.

  • sinr_effective_fun (instance of EffectiveSINR | None (default)) – Function computing the effective SINR. If None, it is set to an instance of EESM.

  • load_bler_tables_from (str | list of str (default: “default”)) – Name of file(s) containing pre-computed SINR-to-BLER tables for different categories, tables indices, MCS indices, SINR and code block sizes. If “default”, then the pre-computed tables stored in “phy/abstraction/bler_tables/” folder are loaded.

  • snr_db_interp_min_max_delta ([3], tuple (default: (-5, 30.01, .1))) – Tuple of (min, max, delta) values [dB] defining the list of SINR [dB] values at which the BLER is interpolated, as min, min+delta, min+2*delta,…, up until max

  • cbs_interp_min_max_delta ([3], tuple (default: (24, 8448, 100))) – Tuple of (min, max, delta) values defining the list of code block size values at which the BLER and SINR are interpolated, as min, min+delta, min+2*delta,…,max

  • bler_interp_delta (float (default: 0.01)) – Spacing of the BLER grid at which SINR is interpolated

  • precision (None (default) | “single” | “double”) – Precision used for internal calculations and outputs. If set to None, precision is used.

  • kwargs – Additional inputs for bler_snr_interp_fun, mcs_decoder_fun, transport_block_fun

Input:
  • mcs_index ([…, num_ut], tf.int32) – MCS index for each user

  • sinr ([…, num_ofdm_symbols, num_subcarriers, num_ut, num_streams_per_ut], tf.float | None (default)) – Post-equalization SINR in linear scale for each OFDM symbol, subcarrier, user and stream. If None, then sinr_eff and num_allocated_re are both required.

  • sinr_eff ([…, num_ut], tf.float | None (default)) – Effective SINR in linear scale for each user. If None, then sinr is required.

  • num_allocated_re ([…, num_ut], tf.int32 | None (default)) – Number of allocated resources in a slot, computed across OFDM symbols, subcarriers and streams, for each user. If None, then sinr is required.

  • mcs_table_index ([…, num_ut], tf.int32 | int (default: 1)ß) – MCS table index. For further details, refer to the Note.

  • mcs_category ([…, num_ut], tf.int32 | int (default: 0)) – MCS table category. For further details, refer to the Note.

  • check_mcs_index_validity (bool (default: True)) – If True, an ValueError is thrown is the input MCS indices are not valid for the given configuration

Output:
  • num_decoded_bits ([…, num_ut], tf.int32) – Number of successfully decoded bits for each user

  • harq_feedback ([…, num_ut], -1 | 0 | 1) – If 0 (1, resp.), then a NACK (ACK, resp.) is received. If -1, feedback is missing since the user is not scheduled for transmission.

  • sinr_eff ([…, num_ut], tf.float) – Effective SINR in linear scale for each user

  • tbler ([…, num_ut], tf.float) – Transport block error rate (BLER) for each user

  • bler ([…, num_ut], tf.float) – Block error rate (BLER) for each user

Note

In this class, the terms SNR (signal-to-noise ratio) and SINR (signal-to-interference-plus-noise ratio) can be used interchangeably. This is because the equivalent AWGN model used for BLER mapping does not explicitly account for interference.

Example

import numpy as np
from sionna.sys import PHYAbstraction, EESM
from sionna.phy.nr.utils import MCSDecoderNR, TransportBlockNR
from sionna.phy.utils import SplineGriddataInterpolation

# Instantiate the class for BLER and SINR interpolation
bler_snr_interp_fun = SplineGriddataInterpolation()
# Instantiate the class for mapping MCS to modulation order and coderate
# in 5G NR
mcs_decoder_fun = MCSDecoderNR()
# Instantiate the class for computing the number and size of code blocks
# within a transport block in 5G NR
transport_block_fun = TransportBlockNR()
# Instantiate the class for computing the effective SINR
sinr_effective_fun = EESM()

# By instantiating a PHYAbstraction object, precomputed BLER tables are
# loaded and interpolated on a fine (SINR, code block size) grid for each MCS
phy_abs = PHYAbstraction(
    bler_snr_interp_fun=bler_snr_interp_fun,
    mcs_decoder_fun=mcs_decoder_fun,
    transport_block_fun=transport_block_fun,
    sinr_effective_fun=sinr_effective_fun)

# Plot a BLER table
phy_abs.plot(plot_subset={'category': {0: {'index': {1: {'MCS': 14}}}}},
                show=True);
../../_images/category0_table1_mcs14.png
# One can also compute new BLER tables
# SINR values and code block sizes @ new simulations are performed
snr_dbs = np.linspace(-5, 25, 5)
cb_sizes = np.arange(24, 8448, 1000)
# MCS values @ new simulations are performed
sim_set = {'category': {
    0:
    {'index': {
        1: {'MCS': [15]}
    }}}}

# Compute new tables
new_table = phy_abs.new_bler_table(
    snr_dbs,
    cb_sizes,
    sim_set,
    max_mc_iter=15,
    batch_size=10,
    verbose=True)
property bler_interp_delta

Get/set the spacing of the BLER grid at which SINR is interpolated

Type:

float

property bler_table

Collection of tables containing BLER values for different values of SNR, MCS table, MCS index and CB size. bler_table['category'][cat]['index'][mcs_table_index]['MCS'][mcs]['CBS'][cb_size] contains the lists of BLER values. bler_table['category'][cat]['index'][mcs_table_index]['MCS'][mcs]['SNR_db'] contains the list of SNR values. bler_table['category'][cat]['index'][mcs_table_index]['MCS'][mcs]['EbN0_db'] contains the list of Eb/N0 values

Type:

dict (read-only)

property bler_table_filenames

Get/set the absolute path name of the files containing BLER tables

Type:

str | list of str

property bler_table_interp

Tensor containing BLER values interpolated across SINR and CBS values, for different categories and MCS table indices. The first axis accounts for the category, e.g., ‘PDSCH’ or ‘PUSCH’ in 5G-NR, the second axis corresponds to the 38.214 MCS table index while the third axis carries the MCS index.

Type:

[n_categories,n_tables,n_mcs,n_cbs_index,n_snr], tf.float (read-only)

property cbs_interp_min_max_delta

Get/set the tuple of (min, max, delta) values defining the list of code block size values at which the BLER and SINR are interpolated, as min, min+delta, min+2*delta,…, up until max.

Type:

[3], tuple

get_bler(mcs_index, mcs_table_index, mcs_category, cb_size, snr_eff)[source]

Retrieves from interpolated tables the BLER corresponding to a certain table index, MCS, CB size, and SINR values provided as input. If the corresponding interpolated table is not available, it returns Inf.

Input:
  • mcs_index ([…], tf.int32) – MCS index for each user

  • mcs_table_index ([…], tf.int.32 | int) – MCS table index for each user. For further details, refer to the Note.

  • mcs_category ([…], tf.int32) – MCS table category for each user. For further details, refer to the Note.

  • cb_size ([…], tf.int32) – Code block size for each user

  • snr_eff ([…], tf.float) – Effective SINR for each user

Output:

bler ([…], tf.float) – BLER corresponding to the input channel type, table index, MCS, CB size and SINR, retrieved from internal interpolation tables

get_idx_from_grid(val, which)[source]

Retrieves the index of a SINR of CBS value in the interpolation grid.

Input:
  • val ([…], tf.float) – Values to be quantized

  • which (“snr | “cbs”) – Whether the values are SNR (equivalent to SINR) or CBS

Output:

idx ([…], tf.int32) – Index of the values in the interpolation grid

static load_table(filename)[source]

Loads a table stored in JSON file.

Input:

filename (str) – Name of the JSON file containing the table

Output:

dict – table loaded from file

new_bler_table(snr_dbs, cb_sizes, sim_set, channel=None, filename=None, write_mode='w', batch_size=1000, max_mc_iter=100, target_bler=None, graph_mode='graph', early_stop=True, filename_log=None, verbose=True)[source]

Computes static tables mapping SNR values of an AWGN channel to the corresponding block error rate (BLER) via Monte-Carlo simulations for different MCS indices, code block sizes and channel types. Note that the newly computed table is merged with the internal self.bler_table.

The simulation continues with the next SNR point after max_mc_iter batches of size batch_size have been simulated. Early stopping allows to stop the simulation after the first error-free SNR point or after reaching a certain target_ber or target_bler. For more details, please see sim_ber().

Input:
  • snr_dbs (list | float) – List of SNR [dB] value(s) at which the BLER is computed

  • cb_sizes (list | int) – List of code block (CB) size(s) at which the BLER is computed

  • sim_set (dict) – Dictionary contains the list of the MCS indices at which the BLER is computed via simulation. The dictionary structure is of the kind: sim_set['category'][category]['index'][mcs_table_index]['MCS'][mcs_list].

  • channel (instance of SingleLinkChannel | None) – Object for simulating single-link i.e., single-carrier and single-stream, channels. If None, it is set to an instance of CodedAWGNChannelNR.

  • filename (str | None (default)) – Name of JSON file where the BLER tables are saved. If None, results are not saved.

  • write_mode (‘w’ (default) | ‘a’) – If ‘w’, then bler_table_filename is rewritten. If ‘a’, then the produced results are appended to bler_table_filename.

  • batch_size (int (default: 2000)) – Batch size for Monte-Carlo BLER simulations

  • max_mc_iter (int (default: 100)) – Maximum number of Monte-Carlo iterations per SNR point

  • target_bler (None (default) | tf.float32) – The simulation stops after the first SNR point which achieves a lower block error rate as specified by target_bler. This requires early_stop to be True.

  • graph_mode (None | “graph” (default) | “xla”) – Execution mode of EquivalentChannel call method. If None, then EquivalentChannel is executed as is.

  • num_iter_decoder (int (default: 20)) – Number of decoder iterations. See LDPC5GDecoder for more details.

  • cn_update (“boxplus-phi” (default) | “boxplus” | “minsum” | “offset-minsum” | “identity” | callable) – Check node update rule. See LDPC5GDecoder for more details.

  • filename_log (str | None (default)) – Name of logging file. If None, logs are not produced.

  • verbose (bool (default: True)) – If True, the simulation progress is visualized, as well as the names of files of results and figures

Output:

new_table (dict) – Newly computed BLER table

plot(plot_subset='all', show=True, save_path=None)[source]

Visualizes and/or saves to file the SINR-to-BLER tables

Input:
  • plot_subset (dict | “all”) – Dictionary containing the list of MCS indices to consider, stored at plot_subset['category'][category]['index'][mcs_table_index]['MCS']. If “all”, then plots are produced for all available BLER tables.

  • show (bool (default: True)) – If True, then plots are visualized

  • save_path (str | None (default)) – Folder path where BLER plots are saved. If None, then plots are not saved

Output:

fignames (list) – List of names of files containing BLER plots

property snr_db_interp_min_max_delta

Get/set the tuple of (min, max, delta) values [dB] defining the list of SINR values at which the BLER is interpolated, as min, min+delta, min+2*delta,…, up until max

Type:

[3], tuple

property snr_table_interp

Tensor containing SINR values interpolated across BLER and CBS values, for different categories and MCS table indices. The first axis accounts for the category, e.g., ‘PDSCH’ or ‘PUSCH’ in 5G-NR, the second axis corresponds to the 38.214 MCS table index and the third axis accounts for the MCS index.

Type:

[n_categories,n_tables,n_mcs,n_cbs_index,n_bler], tf.float (read-only)

validate_bler_table()[source]

Validates the dictionary structure of self.bler_table

Output:

bool | ValueError – Returns True if self.bler_table has a valid structure. Else, a ValueError is raised

References:
[5GLENA]

S. Lagen, K. Wanuga, H. Elkotby, S. Goyal, N. Patriciello, L. Giupponi. “New radio physical layer abstraction for system-level simulations of 5G networks”. IEEE International Conference on Communications (ICC), 2020