NR SA UL MIMO
The purpose of this tutorial is to show you how to configure and test UL MIMO for NR SA. At this point, I don't have any commercial UE supporting UL MIMO. So the first test is with Amari Callbox and Amari UEsim and I will add the test with commercial UE as soon as I managed to get a commercial UE.
When you want to try UL MIMO test with your own UE, make it sure that your UE really support UL MIMO and the UE declare the support of UL MIMO in UE capability Information as shown in Precondition section.
Even though the configuration for UL MIMO in Amarisoft gNB is designed to be pretty simple, you need to have detailed understandings on 3GPP lower layer specification if you want to configure the test condition exactly as you intended. The specification you need through understanding for this test are summarized as follows :
- Precoding Matrix : 38.211 - Table 6.3.1.5-1 ~ Table 6.3.1.5-7
- Precoding and number of layers : 38.212 - Table 7.3.1.1.2-2 ~ Table 7.3.1.1.2-5
- Antenna Port : 38.212 - Table 7.3.1.1.2-6 ~ Table 7.3.1.1.2-23
Table of Contents
- NR SA UL MIMO
- Introduction
- Summary of the Tutorial
- Test Setup
- Preconditions
- Key Configuration Parameters
- Test 1 : Reference Test - UL SISO
- Test 2 : UL MIMO - 2x2
- Test 3 : UL MIMO - 4x4
- Test 4 : UL MIMO - 2x2 : TPMI
- Configuration
- Perform the Test
- Log Analysis
- SubTest 1 : Index 0
- SubTest 2 : Index 2
- SubTest 3 : Index 4
- SubTest 4 : Index 6
- SubTest 5 : Index 8
- RRC / NAS Signaling
Introduction
Uplink Multiple-Input Multiple-Output (UL MIMO) technology in 5G New Radio Standalone (NR SA) networks represents a significant advancement in wireless communication, enabling enhanced throughput, spectral efficiency, and reliability by utilizing multiple antennas at both the User Equipment (UE) and the base station (gNB). UL MIMO leverages advanced signal processing techniques and 3GPP-defined procedures to allow simultaneous transmission of multiple data streams from the UE to the network, thereby maximizing the use of available radio resources. In the context of 5G NR, the configuration and testing of UL MIMO require a comprehensive understanding of key physical layer concepts such as precoding matrices, antenna port mapping, and the relationship between transmission layers and supported features as defined in 3GPP specifications (notably TS 38.211 and TS 38.212). This tutorial provides a structured approach to configuring and testing UL MIMO using Amarisoft's Callbox and UEsim, offering both practical steps for lab validation and theoretical background to ensure test accuracy. Mastery of these concepts is essential, as the implementation and validation of UL MIMO directly influence network performance and UE capability validation, impacting the broader 5G ecosystem where efficient use of uplink resources is critical for emerging applications and services.
-
Context of UL MIMO in 5G NR SA
- 5G NR introduces native support for advanced MIMO schemes, including uplink MIMO, as part of the effort to achieve higher data rates and improved link reliability.
- Standalone (SA) operation enables 5G networks to operate independently from LTE, fully utilizing NR features such as flexible spectrum allocation, advanced antenna techniques, and dynamic resource management.
- Amarisoft Callbox and UEsim provide a controlled test environment to emulate both gNB and UE, facilitating feature verification prior to commercial UE availability.
-
Relevance and Importance of UL MIMO Testing
- Ensuring UL MIMO is properly configured and validated is crucial for achieving the expected performance gains in uplink throughput and spectral efficiency.
- Understanding the interplay between 3GPP-defined configurations (e.g., precoding matrices, antenna ports, number of layers) is essential for accurate test execution and troubleshooting.
- Verification with commercial UE is a critical step toward deployment readiness and device interoperability in real-world 5G networks.
-
Learning Outcomes
- Acquire practical skills in configuring UL MIMO scenarios using Amarisoft test equipment.
- Gain a solid grasp of the lower-layer 3GPP specifications relevant to UL MIMO operation (notably TS 38.211 and TS 38.212).
- Develop the ability to analyze and interpret UE capability signaling and gNB configuration relevant to uplink MIMO.
- Build confidence in troubleshooting and validating advanced 5G NR features in a lab setting.
-
Prerequisites
- Fundamental understanding of 5G NR architecture and physical layer concepts.
- Familiarity with Amarisoft Callbox and UEsim operation is highly recommended.
- Working knowledge of 3GPP specifications, particularly TS 38.211 (Physical channels and modulation) and TS 38.212 (Multiplexing and channel coding).
- Basic experience with wireless test equipment and network configuration.
Summary of the Tutorial
This tutorial demonstrates a series of uplink MIMO (Multiple Input Multiple Output) test procedures using Amarisoft Callbox and UEsim for 5G NR Standalone (SA) scenarios. The tests progress from a reference uplink SISO (Single Input Single Output) configuration to 2x2 and 4x4 UL MIMO, including a case focused on TPMI (Transmit Precoding Matrix Indicator). The following summarizes the procedures, steps, and methodologies used in each test.
-
Preconditions
- Verify that the UE (Device Under Test) supports UL MIMO. This is typically checked via the UE capability information, ensuring support for multiple MIMO layers, proper subcarrier spacing, bandwidth, SRS (Sounding Reference Signal) resources, and higher-order modulation (e.g., 256QAM).
-
Key Configuration Parameters
- Familiarize with the following parameters, which are critical for all tests:
- srs_resource: Pay attention to n_ports (number of SRS ports).
- pusch: Key settings include max_rank (maximum MIMO rank/layers) and n_layer (number of transmission layers).
- Familiarize with the following parameters, which are critical for all tests:
-
Test 1: Reference Test - UL SISO
-
Configuration Steps:
- On the gNB, use a configuration file (gnb-sa-ulsiso.cfg) set up for SISO (N_ANTENNA_UL = 1, USE_SRS = 1).
- Enable SRS, ensure n_ports for SRS matches the number of UL antennas.
- Set PUSCH max_rank and n_layer to 1.
- Force the scheduler to allocate all possible UL slots with a fixed MCS for throughput comparison.
- Optionally, extend inactivity_timer to observe PHY throughput.
- On UEsim, match the UL and DL antenna settings to the gNB configuration.
-
Test Execution:
- Verify cell and uplink configuration (number of UL antennas, layers, RX channels, and ports).
- Power on the UE and ensure it attaches successfully.
- Observe and record the uplink throughput for reference.
-
Log Analysis:
- Confirm PUSCH maxRank = 1 in configuration.
- Check SRS resource configuration (should be port1 for SISO).
- At the PHY layer, verify antenna_ports and number of layers (nl = 1 indicates SISO).
-
Configuration Steps:
-
Test 2: UL MIMO - 2x2
-
Configuration Steps:
- On the gNB, use a configuration file for 2x2 MIMO (gnb-sa-ulmimo.cfg), set N_ANTENNA_UL = 2, USE_SRS = 1.
- Set SRS n_ports = 2 and PUSCH max_rank, n_layer = 2.
- Force scheduler for all UL slots with fixed MCS.
- Extend inactivity_timer if needed.
- On UEsim, set both UL and DL antennas to 2.
-
Test Execution:
- Verify the cell's uplink configuration (2 antennas/layers, 2 RX channels).
- Power on UE, ensure attach, and check if throughput improves compared to SISO.
-
Log Analysis:
- Confirm PUSCH maxRank = 2.
- SRS nrofSRS-Ports = 2.
- At the PHY layer, check antenna_ports, precoding_info, and nl = 2 (indicating 2-layer transmission).
-
Configuration Steps:
-
Test 3: UL MIMO - 4x4
-
Configuration Steps:
- On the gNB, use a configuration file for 4x4 MIMO (gnb-sa-ulmimo-4x4.cfg), set N_ANTENNA_UL = 4, USE_SRS = 1.
- Set SRS n_ports = 4 and PUSCH max_rank, n_layer = 4.
- Force scheduler and extend inactivity_timer as needed.
- On UEsim, match UL and DL antennas to 4.
-
Test Execution:
- Verify proper cell configuration (4 antennas/layers, 4 RX channels).
- Power on UE, ensure attach, and compare throughput with SISO/2x2.
-
Log Analysis:
- Confirm PUSCH maxRank = 4.
- SRS nrofSRS-Ports = 4.
- At the PHY layer, check antenna_ports, precoding_info, and nl = 4 (indicating 4-layer transmission).
-
Configuration Steps:
-
Test 4: UL MIMO - 2x2 with TPMI
-
Configuration Steps:
- On the gNB, use gnb-sa-ulmimo-tpmi.cfg for 2x2 MIMO with TPMI configuration.
- Set N_ANTENNA_UL = 2, USE_SRS = 1, SRS n_ports = 2.
- Configure PUSCH with tx_config: "codebook", n_layer: 1, and tpmi: 2.
- Set codebook_subset to "fully_and_partial_and_non_coherent" to use the full range of 3GPP-defined codebook entries.
- Force scheduler and extend inactivity_timer as before.
- On UEsim, match antenna settings to gNB.
-
Test Execution:
- Verify uplink configuration (2 antennas/layers, 2 RX channels).
- Power on UE, ensure attach, and observe throughput.
-
Log Analysis:
- Confirm RRC setup configures txConfig as codebook-based, transformPrecoding disabled (CP-OFDM).
- Check codebookSubset and maxRank (should indicate codebook-based MIMO with max 2 layers).
- In DCI 0_1, ensure precoding_info matches the expected TPMI, confirming the UE is scheduled with the intended codebook index.
-
Configuration Steps:
General Methodology:
- For each test, ensure that the gNB and UEsim configurations match in terms of antenna numbers and SRS resources.
- Validate cell and uplink configuration using cell and RF info commands before starting the UE.
- After test execution, analyze logs to confirm that the intended MIMO configuration, SRS ports, and codebook/precoder selection are correctly applied and signaled to the UE.
Test Setup
Test setup for this tutorial is as shown below.

Preconditions
Before you try any test in this tutorial, make it sure that your UE (DUT) support UL MIMO. An easy way to check if the UE support UL MIMO or not is to check following IE in UE capability Information.
featureSetsUplinkPerCC {
{
supportedSubcarrierSpacingUL kHz30,
supportedBandwidthUL fr1: mhz20,
mimo-CB-PUSCH {
maxNumberMIMO-LayersCB-PUSCH twoLayersmaxNumberSRS-ResourcePerSet 1
},
supportedModulationOrderUL qam256
}
},
Key Configuration Parameters
Followings are important configuration parameters for this tutorial. You may click on the items for the descriptions from Amarisoft documents.
Test 1 : Reference Test - UL SISO
This test is not for UL MIMO, but I decided to perform this test as a reference (i.e, comparative purpose with the test result for MIMO case) before trying UL MIMO. It would be helpful to understand the concept of UL MIMO if you compare this reference with other test cases.
Configuration
I used the gnb-sa-ulsiso.cfg on gNB which is copied and modified from gnb-sa.cfg

In gnb-sa-ulsiso.cfg , the configuration is done as follows. I set UL to SISO for reference and enabled SRS as well. Set N_ANTENNA_UL to 1 to configure for SISO and USE_SRS to 1 to enable SRS.

It is not mandatory but I forced UL PHY/MAC to schedule every possible UL slots with fixed mcs to compare this reference with other test in terms of throughput.

One important thing to note is that number of srs port (n_ports) in srs_resource configuration is same as the number of MIMO antenna (N_ANTENNA_UL).

I also set max_rank and n_layer of pusch configuration to be same as the number of UL antenna. These configuration (max_rank and n_layer) will be reflected into RRC message. (

This is not mandatory either. I extended inactivity_timer for long enough to check phy throughput without generating IP throughput.

I used the ue-nr-sa-ulsiso.cfg on UEsim which is copied and modified from ue-nr-sa.cfg

In ue-nr-sa-ulsiso.cfg , the configuration is done as follows.
I set the number of ULand DL antenna of UEsim to be same as the number of UL and DL antenna of Callbox(gNB) by setting the value of N_ANTENNA_DL and N_ANTENNA_UL.


Perform the Test
Check if the cell is configured as intended. The important thing in this test is Uplink configuration. Check out the number of UL ANT and NL(number of layers) with cell phy command and check out RX channels and port with rf_info command.

Power on UE on UE sim if everything is configured as you intended.

Confirm that the UE completes the attach and check the throughput. It would be better to remember the UL throughput of this test as a reference.

Log Analysis
Now let's look into the log and see how the configuration is reflected in signaling message.
The first important thing to check is maxRank value in pusch-Config of RRC Setup. Since this test is SISO, it is set to 1.

Next to check is the number of srs port. You can confirm on it with nrofSRS-Ports of srs-ResourceToAddModList. In this test, it is set to port1 since it is SISO.

Lastly let's check about the operation at PHY layer.
First thing you need to check is the field antenna_ports in DCI 0_1. Interpretation of the value is a little bit complicated. Check out this note for the interpretation of this field.

Next thing to check is the number of layers for PUSCH. Number of layers for PUSCH is informed via nl field in PUSCH log. In this case, nl field is not printed in the log. It means the value of nl is 1 which indicates SISO.

Test 2 : UL MIMO - 2x2
This test is to show how to configure and validate UL 2x2 MIMO.
Configuration
I used the gnb-sa-ulmimo.cfg on gNB which is copied and modified from gnb-sa.cfg

In gnb-sa-ulmimo.cfg , the configuration is done as follows. I set UL to 2x2 MIMO for reference and enabled SRS as well. Set N_ANTENNA_UL to 2 to configure for SISO and USE_SRS to 1 to enable SRS.

It is not mandatory but I forced UL PHY/MAC to schedule every possible UL slots with fixed mcs to compare this reference with other test in terms of throughput.

One important thing to note is that number of srs port (n_ports) in srs_resource configuration is same as the number of MIMO antenna (N_ANTENNA_UL).

I also set max_rank and n_layer of pusch configuration to be same as the number of UL antenna. These configuration (max_rank and n_layer) will be reflected into RRC message. (

This is not mandatory either. I extended inactivity_timer for long enough to check phy throughput without generating IP throughput.

I used the ue-nr-sa-ulmimo.cfg on UEsim which is copied and modified from ue-nr-sa.cfg

In ue-nr-sa-ulmimo.cfg, the configuration is done as follows.
I set the number of ULand DL antenna of UEsim to be same as the number of UL and DL antenna of Callbox(gNB) by setting the value of N_ANTENNA_DL and N_ANTENNA_UL.


Perform the Test
Check if the cell is configured as intended.
Check if the cell is configured as intended. The important thing in this test is Uplink configuration. Check out the number of UL ANT and NL(number of layers) with cell phy command and check out RX channels and port with rf_info command. You see 2 RX channels are configured.

Power on UE on UE sim.

Confirm that the UE completes the attach and check the throughput. Confirm that the UE completes the attach and check the throughput. Compare the throughput with the reference throughput that you had with SISO.

Log Analysis
Now let's look into the log and see how the configuration is reflected in signaling message.
The first important thing to check is maxRank value in pusch-Config of RRC Setup. Since this test is 2x2 MIMO, it is set to 2.

Next to check is the number of srs port. You can confirm on it with nrofSRS-Ports of srs-ResourceToAddModList. In this test, it is set to port2 since it is 2x2 MIMO.

Lastly let's check about the operation at PHY layer.
First thing you need to check is the field antenna_ports and precoding_info in DCI 0_1 (

Next thing to check is the number of layers for PUSCH. Number of layers for PUSCH is informed via nl field in PUSCH log. In this case, nl field is set to 2 which indicates 2 layers. 2 layer indicates it is 2x2 or 2x4 or 2x8 MIMO etc.

Test 3 : UL MIMO - 4x4
This test is to show how to configure and validate UL 4x4 MIMO.
Configuration
I used the gnb-sa-ulmimo-4x4.cfg on gNB which is copied and modified from gnb-sa.cfg

In gnb-sa-ulmimo-4x4.cfg , the configuration is done as follows. I set UL to 4x4 MIMO for reference and enabled SRS as well. Set N_ANTENNA_UL to 4 to configure for SISO and USE_SRS to 1 to enable SRS.

It is not mandatory but I forced UL PHY/MAC to schedule every possible UL slots with fixed mcs to compare this reference with other test in terms of throughput.

One important thing to note is that number of srs port (n_ports) in srs_resource configuration is same as the number of MIMO antenna (N_ANTENNA_UL).

I also set max_rank and n_layer of pusch configuration to be same as the number of UL antenna. These configuration (max_rank and n_layer) will be reflected into RRC message. (

This is not mandatory either. I extended inactivity_timer for long enough to check phy throughput without generating IP throughput.

I used the ue-nr-sa-ulmimo-4x4.cfg on UEsim which is copied and modified from ue-nr-sa.cfg

In ue-nr-sa-ulmimo-4x4.cfg, the configuration is done as follows.
I set the number of ULand DL antenna of UEsim to be same as the number of UL and DL antenna of Callbox(gNB) by setting the value of N_ANTENNA_DL and N_ANTENNA_UL.


Perform the Test
Check if the cell is configured as intended.
Check if the cell is configured as intended. The important thing in this test is Uplink configuration. Check out the number of UL ANT and NL(number of layers) with cell phy command and check out RX channels and port with rf_info command. You see 4 RX channels are configured.


Power on UE on UE sim.

Confirm that the UE completes the attach and check the throughput. Confirm that the UE completes the attach and check the throughput. Confirm that the UE completes the attach and check the throughput. Compare the throughput with the reference throughput that you had with SISO.

Log Analysis
Now let's look into the log and see how the configuration is reflected in signaling message.
The first important thing to check is maxRank value in pusch-Config of RRC Setup. Since this test is 4x4 MIMO, it is set to 4

Next to check is the number of srs port. You can confirm on it with nrofSRS-Ports of srs-ResourceToAddModList. In this test, it is set to port4 since it is 4x4 MIMO.

Lastly let's check about the operation at PHY layer.
First thing you need to check is the field antenna_ports and precoding_info in DCI 0_1 (

Next thing to check is the number of layers for PUSCH. Number of layers for PUSCH is informed via nl field in PUSCH log. In this case, nl field is set to 4 which indicates 4 layers. 4 layer indicates it is 4x4 or 4x8 MIMO etc.

Test 4 : UL MIMO - 2x2 : TPMI
This test is to show how to configure and test TPMI for UL 2x2 MIMO.
Configuration
I used the gnb-sa-ulmimo-tpmi.cfg on gNB which is copied and modified from gnb-sa.cfg

In gnb-sa-ulmimo-tpmi.cfg , the configuration is done as follows. I set UL to 2x2 MIMO for reference and enabled SRS as well. Set N_ANTENNA_UL to 2 to configure for SISO and USE_SRS to 1 to enable SRS.

It is not mandatory but I forced UL PHY/MAC to schedule every possible UL slots with fixed mcs to compare this reference with other test in terms of throughput.

One important thing to note is that number of srs port (n_ports) in srs_resource configuration is same as the number of MIMO antenna (N_ANTENNA_UL).

I also set max_rank and n_layer of pusch configuration to be same as the number of UL antenna. These configuration (max_rank and n_layer) will be reflected into RRC message. (
The important part is the SRS and codebook configuration. USE_SRS enables uplink sounding, so the gNB can estimate the UL channel. tx_config: "codebook" means the UE uses a standardized UL precoder, not an arbitrary one. n_layer: 1 configures one-layer PUSCH transmission. tpmi: 2 forces TPMI index 2. With codebook_subset: "fully_and_partial_and_non_coherent", this TPMI is interpreted using the wide UL codebook subset defined by 3GPP. "fully_and_partial_and_non_coherent" determines the column of the 3GPP table. The combination of n_layer and tpmi value determines the row of the table. In this case, n_layer :1 and tpmi:2 corresponds to 'Bit field mapped to index' : 3.
So, in short, this configuration makes the UE transmit one-layer PUSCH using a specific UL codebook precoder selected by TPMI 2. It is useful for checking whether the UE correctly applies the TPMI indicated by the gNB.

This is not mandatory either. I extended inactivity_timer for long enough to check phy throughput without generating IP throughput.

Perform the Test
Check if the cell is configured as intended.
Check if the cell is configured as intended. The important thing in this test is Uplink configuration. Check out the number of UL ANT and NL(number of layers) with cell phy command and check out RX channels and port with rf_info command. You see 2 RX channels are configured.

Power on UE on UE sim.

Confirm that the UE completes the attach and check the throughput. Confirm that the UE completes the attach and check the throughput.
Log Analysis
In the RRC setup the UE receives pusch-Config setup. Inside that, txConfig codebook indicates codebook-based UL transmission. Then transformPrecoder disabled confirms that CP-OFDM PUSCH is used, not DFT-s-OFDM.
This is important because the TPMI interpretation depends on this condition. With transform precoding disabled, the UE should apply the UL codebook rule from 38.212 Table 7.3.1.1.2-4.
In short, this log is the RRC-level confirmation that the UE was configured for codebook-based UL MIMO PUSCH, CP-OFDM operation, and TPMI-based precoder selection.

txConfig codebook configures the UE to use codebook-based uplink PUSCH transmission. This means the uplink precoder is not chosen freely by the UE. It is selected from the standardized UL codebook and can be controlled by TPMI in the UL grant.
codebookSubset fullyAndPartialAndNonCoherent tells the UE which group of UL codebook entries is allowed. In this case, the widest subset is enabled. So fully coherent, partially coherent, and non-coherent precoding candidates can be used.
maxRank 2 configures the maximum number of UL PUSCH layers as 2. This does not mean every PUSCH is transmitted with 2 layers. It means the UE may be scheduled with up to 2 layers, depending on the UL grant and the selected TPMI.

This image shows the actual UL grant decoding on PDCCH.
The highlighted PDCCH message has dci=0_1, so this is an uplink scheduling grant for PUSCH. In the decoded DCI fields, precoding_info=3 is highlighted. This value is the bit-field index used to select the corresponding UL TPMI entry from the 38.212 table. For codebookSubset = fullyAndPartialAndNonCoherent, index 3 maps to 1 layer: TPMI=2.
So this log indicates that the gNB scheduled PUSCH using DCI 0_1, and the UE was instructed to transmit one-layer PUSCH with TPMI 2.

SubTest 1 : Index 0
The main purpose of this sub text is to show how to set the 'Bit field mapped index' to 0 which indicates 1 layer, TPMI 0
The important part is the SRS and codebook configuration. USE_SRS enables uplink sounding, so the gNB can estimate the UL channel. tx_config: "codebook" means the UE uses a standardized UL precoder, not an arbitrary one. n_layer: 1 configures one-layer PUSCH transmission. tpmi: 0 forces TPMI index 0. With codebook_subset: "fully_and_partial_and_non_coherent", this TPMI is interpreted using the wide UL codebook subset defined by 3GPP. "fully_and_partial_and_non_coherent" determines the column of the 3GPP table. The combination of n_layer and tpmi value determines the row of the table. In this case, n_layer :1 and tpmi:2 corresponds to 'Bit field mapped to index' : 0.
So, in short, this configuration makes the UE transmit one-layer PUSCH using a specific UL codebook precoder selected by TPMI 0. It is useful for checking whether the UE correctly applies the TPMI indicated by the gNB.

txConfig codebook configures the UE to use codebook-based uplink PUSCH transmission. This means the uplink precoder is not chosen freely by the UE. It is selected from the standardized UL codebook and can be controlled by TPMI in the UL grant.
codebookSubset fullyAndPartialAndNonCoherent tells the UE which group of UL codebook entries is allowed. In this case, the widest subset is enabled. So fully coherent, partially coherent, and non-coherent precoding candidates can be used.
maxRank 2 configures the maximum number of UL PUSCH layers as 2. This does not mean every PUSCH is transmitted with 2 layers. It means the UE may be scheduled with up to 2 layers, depending on the UL grant and the selected TPMI.

This log shows the actual UL grant decoding on PDCCH.
The highlighted PDCCH message has dci=0_1, so this is an uplink scheduling grant for PUSCH. In the decoded DCI fields, precoding_info=0 is highlighted. This value is the bit-field index used to select the corresponding UL TPMI entry from the 38.212 table. For codebookSubset = fullyAndPartialAndNonCoherent, index 0 maps to 1 layer: TPMI=0.
So this log indicates that the gNB scheduled PUSCH using DCI 0_1, and the UE was instructed to transmit one-layer PUSCH with TPMI 2.

SubTest 2 : Index 2
The main purpose of this sub text is to show how to set the 'Bit field mapped index' to 2 which indicates 2 layer, TPMI 0
The important part is the SRS and codebook configuration. USE_SRS enables uplink sounding, so the gNB can estimate the UL channel. tx_config: "codebook" means the UE uses a standardized UL precoder, not an arbitrary one. n_layer: 2 configures one-layer PUSCH transmission. tpmi: 0 forces TPMI index 0. With codebook_subset: "fully_and_partial_and_non_coherent", this TPMI is interpreted using the wide UL codebook subset defined by 3GPP. "fully_and_partial_and_non_coherent" determines the column of the 3GPP table. The combination of n_layer and tpmi value determines the row of the table. In this case, n_layer :2 and tpmi:0 corresponds to 'Bit field mapped to index' : 2.
So, in short, this configuration makes the UE transmit one-layer PUSCH using a specific UL codebook precoder selected by TPMI 0. It is useful for checking whether the UE correctly applies the TPMI indicated by the gNB.

txConfig codebook configures the UE to use codebook-based uplink PUSCH transmission. This means the uplink precoder is not chosen freely by the UE. It is selected from the standardized UL codebook and can be controlled by TPMI in the UL grant.
codebookSubset fullyAndPartialAndNonCoherent tells the UE which group of UL codebook entries is allowed. In this case, the widest subset is enabled. So fully coherent, partially coherent, and non-coherent precoding candidates can be used.
maxRank 2 configures the maximum number of UL PUSCH layers as 2. This does not mean every PUSCH is transmitted with 2 layers. It means the UE may be scheduled with up to 2 layers, depending on the UL grant and the selected TPMI.

This log shows the actual UL grant decoding on PDCCH.
The highlighted PDCCH message has dci=0_1, so this is an uplink scheduling grant for PUSCH. In the decoded DCI fields, precoding_info=2 is highlighted. This value is the bit-field index used to select the corresponding UL TPMI entry from the 38.212 table. For codebookSubset = fullyAndPartialAndNonCoherent, index 2 maps to 2 layer: TPMI=0.
So this log indicates that the gNB scheduled PUSCH using DCI 0_1, and the UE was instructed to transmit two-layer PUSCH with TPMI 0.

SubTest 3 : Index 4
The main purpose of this sub text is to show how to set the 'Bit field mapped index' to 4 which indicates 1 layer, TPMI 3
The important part is the SRS and codebook configuration. USE_SRS enables uplink sounding, so the gNB can estimate the UL channel. tx_config: "codebook" means the UE uses a standardized UL precoder, not an arbitrary one. n_layer: 1 configures one-layer PUSCH transmission. tpmi: 3 forces TPMI index 0. With codebook_subset: "fully_and_partial_and_non_coherent", this TPMI is interpreted using the wide UL codebook subset defined by 3GPP. "fully_and_partial_and_non_coherent" determines the column of the 3GPP table. The combination of n_layer and tpmi value determines the row of the table. In this case, n_layer :1 and tpmi:3 corresponds to 'Bit field mapped to index' : 4
So, in short, this configuration makes the UE transmit one-layer PUSCH using a specific UL codebook precoder selected by TPMI 3. It is useful for checking whether the UE correctly applies the TPMI indicated by the gNB.

txConfig codebook configures the UE to use codebook-based uplink PUSCH transmission. This means the uplink precoder is not chosen freely by the UE. It is selected from the standardized UL codebook and can be controlled by TPMI in the UL grant.
codebookSubset fullyAndPartialAndNonCoherent tells the UE which group of UL codebook entries is allowed. In this case, the widest subset is enabled. So fully coherent, partially coherent, and non-coherent precoding candidates can be used.
maxRank 2 configures the maximum number of UL PUSCH layers as 2. This does not mean every PUSCH is transmitted with 2 layers. It means the UE may be scheduled with up to 2 layers, depending on the UL grant and the selected TPMI.

This log shows the actual UL grant decoding on PDCCH.
The highlighted PDCCH message has dci=0_1, so this is an uplink scheduling grant for PUSCH. In the decoded DCI fields, precoding_info=4 is highlighted. This value is the bit-field index used to select the corresponding UL TPMI entry from the 38.212 table. For codebookSubset = fullyAndPartialAndNonCoherent, index 4 maps to 1 layer: TPMI=3.
So this log indicates that the gNB scheduled PUSCH using DCI 0_1, and the UE was instructed to transmit one-layer PUSCH with TPMI 3.

SubTest 4 : Index 6
The main purpose of this sub text is to show how to set the 'Bit field mapped index' to 4 which indicates 1 layer, TPMI 5
The important part is the SRS and codebook configuration. USE_SRS enables uplink sounding, so the gNB can estimate the UL channel. tx_config: "codebook" means the UE uses a standardized UL precoder, not an arbitrary one. n_layer: 1 configures one-layer PUSCH transmission. tpmi: 5 forces TPMI index 5. With codebook_subset: "fully_and_partial_and_non_coherent", this TPMI is interpreted using the wide UL codebook subset defined by 3GPP. "fully_and_partial_and_non_coherent" determines the column of the 3GPP table. The combination of n_layer and tpmi value determines the row of the table. In this case, n_layer :1 and tpmi:5 corresponds to 'Bit field mapped to index' : 6
So, in short, this configuration makes the UE transmit one-layer PUSCH using a specific UL codebook precoder selected by TPMI 5. It is useful for checking whether the UE correctly applies the TPMI indicated by the gNB.

txConfig codebook configures the UE to use codebook-based uplink PUSCH transmission. This means the uplink precoder is not chosen freely by the UE. It is selected from the standardized UL codebook and can be controlled by TPMI in the UL grant.
codebookSubset fullyAndPartialAndNonCoherent tells the UE which group of UL codebook entries is allowed. In this case, the widest subset is enabled. So fully coherent, partially coherent, and non-coherent precoding candidates can be used.
maxRank 2 configures the maximum number of UL PUSCH layers as 2. This does not mean every PUSCH is transmitted with 2 layers. It means the UE may be scheduled with up to 2 layers, depending on the UL grant and the selected TPMI.

This log shows the actual UL grant decoding on PDCCH.
The highlighted PDCCH message has dci=0_1, so this is an uplink scheduling grant for PUSCH. In the decoded DCI fields, precoding_info=6 is highlighted. This value is the bit-field index used to select the corresponding UL TPMI entry from the 38.212 table. For codebookSubset = fullyAndPartialAndNonCoherent, index 6 maps to 1 layer: TPMI=5.
So this log indicates that the gNB scheduled PUSCH using DCI 0_1, and the UE was instructed to transmit one-layer PUSCH with TPMI 5.

SubTest 5 : Index 8
The main purpose of this sub text is to show how to set the 'Bit field mapped index' to 4 which indicates 2 layer, TPMI 2
The important part is the SRS and codebook configuration. USE_SRS enables uplink sounding, so the gNB can estimate the UL channel. tx_config: "codebook" means the UE uses a standardized UL precoder, not an arbitrary one. n_layer: 2 configures one-layer PUSCH transmission. tpmi: 2 forces TPMI index 2. With codebook_subset: "fully_and_partial_and_non_coherent", this TPMI is interpreted using the wide UL codebook subset defined by 3GPP. "fully_and_partial_and_non_coherent" determines the column of the 3GPP table. The combination of n_layer and tpmi value determines the row of the table. In this case, n_layer :2 and tpmi:2 corresponds to 'Bit field mapped to index' : 8
So, in short, this configuration makes the UE transmit one-layer PUSCH using a specific UL codebook precoder selected by TPMI 2. It is useful for checking whether the UE correctly applies the TPMI indicated by the gNB.

txConfig codebook configures the UE to use codebook-based uplink PUSCH transmission. This means the uplink precoder is not chosen freely by the UE. It is selected from the standardized UL codebook and can be controlled by TPMI in the UL grant.
codebookSubset fullyAndPartialAndNonCoherent tells the UE which group of UL codebook entries is allowed. In this case, the widest subset is enabled. So fully coherent, partially coherent, and non-coherent precoding candidates can be used.
maxRank 2 configures the maximum number of UL PUSCH layers as 2. This does not mean every PUSCH is transmitted with 2 layers. It means the UE may be scheduled with up to 2 layers, depending on the UL grant and the selected TPMI.

This log shows the actual UL grant decoding on PDCCH.
The highlighted PDCCH message has dci=0_1, so this is an uplink scheduling grant for PUSCH. In the decoded DCI fields, precoding_info=8 is highlighted. This value is the bit-field index used to select the corresponding UL TPMI entry from the 38.212 table. For codebookSubset = fullyAndPartialAndNonCoherent, index 8 maps to 2 layer: TPMI=2.
So this log indicates that the gNB scheduled PUSCH using DCI 0_1, and the UE was instructed to transmit two-layer PUSCH with TPMI 2.

RRC / NAS Signaling
RrcSetup (SA)
: This is the RrcSetup message sent by gNB to configure NR SA. (
{
message c1: rrcSetup: {
rrc-TransactionIdentifier 0,
criticalExtensions rrcSetup: {
radioBearerConfig {
...
},
masterCellGroup {
cellGroupId 0,
rlc-BearerToAddModList {
...
},
mac-CellGroupConfig {
...
},
physicalCellGroupConfig {
pdsch-HARQ-ACK-Codebook dynamic
},
spCellConfig {
spCellConfigDedicated {
initialDownlinkBWP {
pdcch-Config setup: {
...
},
pdsch-Config setup: {
...
}
},
firstActiveDownlinkBWP-Id 0,
uplinkConfig {
initialUplinkBWP {
pucch-Config setup: {
...
},
pusch-Config setup: {
txConfig codebook,
dmrs-UplinkForPUSCH-MappingTypeA setup: {
dmrs-AdditionalPosition pos1,
transformPrecodingDisabled {
}
},
pusch-PowerControl {
...
},
resourceAllocation resourceAllocationType1,
codebookSubset nonCoherent,
maxRank 4,
uci-OnPUSCH setup: {
...
}
},
srs-Config setup: {
...
},
firstActiveUplinkBWP-Id 0,
pusch-ServingCellConfig setup: {
}
},
pdcch-ServingCellConfig setup: {
},
pdsch-ServingCellConfig setup: {
...
},
csi-MeasConfig setup: {
...
},
tag-Id 0
}