Upper PHY (DU-Low) architecture
15 minute read
Target audience: RAN engineers. Scope: the Upper PHY (DU-Low) implementation in OCUDU under lib/phy/upper/ and lib/phy/generic_functions/ — class ownership, DL and UL processing chains, channel coding (LDPC, polar, CRC), modulation and demodulation, channel estimation, DFT backends, resource grid and buffer management, hardware acceleration hooks, and concurrency model. Lower PHY (OFDM, front-end IQ) and OFH/eCPRI transport are separate compilation units and out of scope here.
1. What the Upper PHY Does
The Upper PHY (also called DU-Low in O-RAN terminology) implements all symbol-level baseband processing that sits between the MAC scheduler and the radio unit. On the downlink it takes transport blocks and control words from the MAC/scheduler and outputs a modulated, precoded resource grid ready for the RU to transmit. On the uplink it accepts time-domain samples from the RU, demodulates them, decodes LDPC or polar-coded payloads, and delivers soft decisions and decoded bits to the MAC.
2. Top-Level Architecture
upper_phy_impl
File: lib/phy/upper/upper_phy_impl.h/.cpp
upper_phy_impl
├── dl_rg_pool resource_grid_pool Pre-allocated DL resource grids
├── dl_processor_pool downlink_processor_pool One processor per SCS x slot-round-robin
├── ul_processor_pool uplink_processor_pool Circular array of 16 UL processors
├── rx_buf_pool rx_buffer_pool_controller Soft-bit HARQ buffers per UE per HARQ ID
├── ul_request_processor uplink_request_processor_impl UL slot/PRACH entry point
├── rx_results_notifier upper_phy_rx_results_notifier_wrapper Callback to DU-Low
├── rx_symbol_handler upper_phy_rx_symbol_handler Symbol capture from RU
├── dl_pdu_validator downlink_pdu_validator
├── ul_pdu_validator uplink_pdu_validator
├── timing_handler upper_phy_timing_handler_impl
└── error_handler upper_phy_error_handler_impl
3. Downlink Processing Chain
3.1 Processor Pool and Dispatch
downlink_processor_pool_impl (lib/phy/upper/downlink_processor_pool_impl.h) groups processors by SCS. The MAC selects a processor for a given slot with:
unique_downlink_processor dp =
pool.get_processor_controller(slot)
.configure_resource_grid(context, shared_resource_grid);
This returns an RAII unique_downlink_processor. When that object is destroyed (end of slot), finish_processing_pdus() fires and the fully assembled resource grid is sent to the RU gateway.
3.2 downlink_processor_multi_executor_impl
File: lib/phy/upper/downlink_processor_multi_executor_impl.h/.cpp
Each PDU type (PDCCH, PDSCH, SSB, CSI-RS, PRS) has a dedicated task_executor. PDU processing tasks are enqueued asynchronously; a downlink_processor_multi_executor_state counter tracks pending tasks. When the pending count reaches zero and the finish flag is set, the grid is sent.
This design means PDCCH and PDSCH tasks can run on different CPU cores in parallel for the same slot.
3.3 PDSCH Processor
File: lib/phy/upper/channel_processors/pdsch/pdsch_processor_impl.h/.cpp
pdsch_processor_impl
├── pdsch_encoder → segmentation → CRC → LDPC encode → rate match → scramble
├── pdsch_modulator → QAM map → layer map → precoding → RE mapping
├── dmrs_pdsch_processor → DM-RS sequence generation and insertion
└── ptrs_pdsch_generator → PT-RS (optional)
Processing steps:
- Segmentation — transport block split into codeblocks per TS 38.212 Section 5.2.2; 24-bit CB CRC added if more than one CB.
- LDPC encoding — BG1 or BG2 selected by CB size; lifting size selected from eight options up to 384; high-rate parity bits computed first, extended parity optional.
- Rate matching — circular buffer model (TS 38.212 Section 5.4.2.1); puncture or repeat bits to reach target coded size E.
- Scrambling — Gold sequence XOR keyed by cell ID and RNTI (TS 38.211 Section 5.2.1).
- QAM modulation — QPSK, 16-QAM, 64-QAM, or 256-QAM via LUT or SIMD mapper.
- Layer mapping — up to 4 spatial layers.
- Precoding and resource mapping —
resource_grid_mapperwrites complex symbols into the DL resource grid at the correct subcarrier, OFDM symbol, and antenna port positions. - DM-RS insertion — pseudo-random (Gold) sequence keyed by cell ID and PDSCH RNTI, pattern by CDM group and density (TS 38.211 Section 7.4.1.1).
- PT-RS insertion — phase tracking reference signals (optional, depends on UE configuration).
pdsch_processor_notifier.on_finish_processing() is called when the grid contribution is complete.
3.4 PDCCH Processor
File: lib/phy/upper/channel_processors/pdcch/pdcch_processor_impl.h/.cpp
pdcch_processor_impl
├── pdcch_encoder → DCI bits → polar code → scramble
├── pdcch_modulator → QPSK → CORESET RE mapping
└── dmrs_pdcch_processor → DM-RS (Gold, keyed by cell ID + CORESET index)
Polar encoding covers variable-length DCI payloads (up to 164 bits per TS 38.212 Section 5.1). QPSK is the only modulation for PDCCH. RE mapping follows the aggregation level: 1, 2, 4, 8, or 16 CCEs within the CORESET (TS 38.213 Section 8.1.1).
3.5 SSB Processor
File: lib/phy/upper/channel_processors/ssb/ssb_processor_impl.h/.cpp
ssb_processor_impl
├── pss_processor → Zadoff-Chu sequence (root u = cell_id mod 3, length 127)
├── sss_processor → Gold sequence (cell_id mod 168, frame number, length 127)
├── pbch_encoder → 24-bit MIB + 8-bit control → polar code (N=32)
├── pbch_modulator → QPSK + layer mapping
└── dmrs_pbch_processor → DM-RS (Gold, keyed by cell ID)
The SS/PBCH block occupies 4 OFDM symbols x 20 PRBs (240 REs). The RE pattern for PSS, SSS, PBCH, and DM-RS positions is fixed by numerology and frequency range.
3.6 NZP-CSI-RS Generator
File: lib/phy/upper/signal_processors/nzp_csi_rs/nzp_csi_rs_generator_impl.h/.cpp
Generates non-zero-power CSI-RS according to a configurable density, periodicity, and port count. Sequence is Gold, keyed by cell ID and CSI-RS port index (TS 38.211 Section 7.4.1.5). RE pattern depends on resource_config (density, time/frequency offset).
3.7 PRS Generator
File: lib/phy/upper/signal_processors/prs/prs_generator_impl.h
Positioning Reference Signal. Gold sequence keyed by cell ID and PRS resource ID. RE pattern configurable per SCS, density, and periodicity. Generated as part of the downlink PDU pipeline.
4. Uplink Processing Chain
4.1 Processor Pool and Dispatch
uplink_processor_pool_impl (lib/phy/upper/uplink_processor_pool_impl.h) maintains a circular array of 16 uplink_processor_impl instances. Assignment is round-robin by slot. A default processor handles unassigned PRACH and symbol requests.
4.2 uplink_processor_impl
File: lib/phy/upper/uplink_processor_impl.h/.cpp
uplink_processor_impl
├── prach_detector → frequency-domain preamble detection
├── pusch_processor → DM-RS estimation → equalization → demod → decode
├── pucch_processor → per-format detection or demod + decode
├── srs_estimator → SRS channel estimation
├── ul_grid → local RX resource grid for this UL slot
└── uplink_processor_fsm → state machine (EMPTY → STORING_SYMBOLS → PROCESSING → IDLE)
The FSM accumulates symbols as they arrive from the RU (process_ul_signal()), one OFDM symbol at a time. When the slot boundary is reached, it triggers PUSCH, PUCCH, and SRS processing.
4.3 PUSCH Processor
File: lib/phy/upper/channel_processors/pusch/pusch_processor_impl.h/.cpp
PUSCH processing is event-driven, not slot-synchronous. The DM-RS estimator runs in an executor pool; when it completes, a notifier callback triggers the demodulator and decoder.
sequenceDiagram
participant FSM as uplink_processor_fsm
participant PUSCH as pusch_processor_impl
participant EST as dmrs_pusch_estimator
participant DEMOD as pusch_demodulator
participant DEC as pusch_decoder
participant UCI as uci_decoder
FSM->>PUSCH: process(grid, rx_buffer, pdu)
PUSCH->>EST: estimate(notifier, grid, config) [async in executor]
EST-->>PUSCH: on_estimation_complete(channel_estimates, noise_variance)
PUSCH->>DEMOD: demodulate(grid, channel_estimates, noise_variance)
PUSCH->>DEC: decode_sch(soft_bits, rx_buffer)
PUSCH->>UCI: decode HARQ-ACK / CSI Part 1 / CSI Part 2
PUSCH->>MAC: on_new_pusch_results_data(decoded_bits, crc, csi)Processing steps:
- DM-RS extraction and channel estimation — per RX port, in parallel (executor pool). Computes channel frequency response at pilot subcarriers; interpolates across data subcarriers and OFDM symbols. Estimates noise variance from pilot residuals.
- Equalization — ZF or MMSE per subcarrier, using the estimated channel and noise variance.
- Soft-bit demodulation (LLR computation) — approximate log-likelihood ratio per bit:
LLR(b_i) ≈ -1/σ² × [min_{S_{i,0}} |y-s|² - min_{S_{i,1}} |y-s|²]. - Rate de-matching — maps received LLRs back to encoder output positions; unmatched positions zero-filled.
- LDPC decoding — layered belief propagation with min-sum approximation; up to configured max iterations; early stop on syndrome pass.
- UCI extraction — HARQ-ACK, CSI Part 1, CSI Part 2 extracted from reserved REs or multiplexed in payload; decoded via separate
uci_decoderinstances.
concurrent_dependencies (estimator + demodulator + UCI decoder set) is acquired from concurrent_dependencies_pool_type per PDU. Multiple PUSCH PDUs in the same slot can run concurrently.
unique_rx_buffer holds the soft-bit HARQ buffer from rx_buffer_pool_controller. For a HARQ retransmission, the pool returns the same buffer so that the decoder can combine LLRs across retransmissions. Buffers expire after a configurable number of slots.
4.4 PUCCH Processor
File: lib/phy/upper/channel_processors/pucch/pucch_processor_impl.h
Handles four formats; each is a separate processing path:
| Format | Payload | Method |
|---|---|---|
| Format 0 | 1-2 HARQ-ACK bits | NC-PSK correlation (single RB, 1 symbol) |
| Format 1 | 1-2 HARQ-ACK + SR | Correlation on 2 OFDM symbols with intra-slot hopping |
| Format 2 | Up to 3 bits | Polar code + QPSK on 1 RB x 1 symbol |
| Format 3, 4 | Up to 11 bits | LDPC or polar code on multiple RBs and symbols |
All formats begin with DM-RS-based channel estimation followed by ZF or MMSE equalization.
4.5 PRACH Detector
File: lib/phy/upper/channel_processors/prach/prach_detector_generic_impl.h/.cpp
For each preamble index, the detector:
- Generates the expected Zadoff-Chu sequence in frequency domain.
- Computes cross-correlation with the captured PRACH window (via IDFT).
- Estimates noise power from the correlation output.
- Computes the generalized log-likelihood ratio:
|correlation|² / noise_power. - Thresholds and returns detected preambles with timing advance (sample offset from correlation peak).
Long preambles use a 4096-point IDFT; short preambles use a 2048-point IDFT. Both use the configurable DFT backend (see Section 8).
5. Channel Coding
5.1 LDPC Encoder
File: lib/phy/upper/channel_coding/ldpc/ldpc_encoder_impl.h/.cpp
Template method pattern: ldpc_encoder_impl defines the algorithm structure; concrete subclasses provide SIMD kernels.
SIMD variants:
ldpc_encoder_avx2.cpp— 256-bit operations.ldpc_encoder_neon.cpp— ARM 128-bit.ldpc_encoder_generic.cpp— scalar fallback.
Base graphs (TS 38.212 Section 5.3.2):
- BG1: 22 information columns, 68 full columns, 46 check equations (longer codeblocks).
- BG2: 22 information columns, 52 full columns, 42 check equations (shorter codeblocks).
Lifting sizes: 8 sets (up to 384) per TS 38.212. Actual codeblock size = K x lifting_size.
The encoder writes only the high-rate parity region (first 4 x lifting_size parity bits) by default. Extended parity is computed on demand for rate matching that requires a larger circular buffer.
5.2 LDPC Graph
File: lib/phy/upper/channel_coding/ldpc/ldpc_graph_impl.h/.cpp
Stores the parity-check matrix as static lookup tables for all 16 (base graph x lifting set) combinations. Each entry is a circular shift amount or NO_EDGE (0xffff). The decoder uses ldpc_graph_impl to know which variable nodes are connected to each check node, and what shift to apply.
5.3 LDPC Decoder
File: lib/phy/upper/channel_coding/ldpc/ldpc_decoder_impl.h/.cpp
Algorithm: Layered Belief Propagation with Min-Sum Approximation
SIMD variants:
ldpc_decoder_avx2.cppldpc_decoder_avx512.cppldpc_decoder_neon.cppldpc_decoder_generic.cpp
One iteration per check-node layer in the base graph:
- Compute variable-to-check (V2C) messages from current soft bits.
- Find the two minimum absolute V2C values and the sign product for each lifted group.
- Compute check-to-variable (C2V) messages:
C2V = sign_product × min(|V2C|, second_min) × 0.8. - Update soft bits:
soft_bits += C2V_new - C2V_old.
Scaling factor 0.8 is the standard min-sum correction. Soft bits are clamped to [-64, +64]. Iteration continues until the CRC matches, the syndrome is satisfied (if early_stop_syndrome is set), or max iterations is reached.
5.4 Rate Matcher
File: lib/phy/upper/channel_coding/ldpc/ldpc_rate_matcher_impl.h/.cpp
Implements the circular buffer model from TS 38.212 Section 5.4.2.1. The encoder output is treated as a circular sequence; starting from the extended parity region, exactly E bits are selected by circular traversal — puncturing (skipping) or repeating as needed. SIMD variants (AVX2, AVX512, NEON) vectorize the scatter/gather operations.
The rate de-matcher (RX side) maps received LLRs back to encoder-output positions and fills unmatched positions with 0.
5.5 Segmenter
TX segmenter (ldpc_segmenter_tx_impl): splits a transport block into codeblocks of equal size per TS 38.212 Section 5.2.2. Adds a 24-bit CRC to each codeblock if more than one codeblock is produced.
RX segmenter (ldpc_segmenter_rx_impl): reassembles decoded codeblocks, verifies per-CB CRC, and returns the transport block. If any CB CRC fails, the TB is flagged as NACK.
5.6 Polar Encoder / Decoder
Files: lib/phy/upper/channel_coding/polar/
Used for PDCCH (DCI) and PBCH (MIB). The decoder uses Successive Cancellation (SC) or SC-List (SCL) with CRC-aided early termination.
5.7 CRC Calculator
Four implementations selected at factory time:
| Variant | File suffix | Method |
|---|---|---|
| LUT | _lut_impl | 256-entry lookup table |
| CLMUL | _clmul_impl | x86 SSE4.2 carryless multiply |
| NEON | _neon_impl | ARM NEON |
| Generic | _generic_impl | Scalar bit-by-bit |
Polynomials: CRC-24A (0x864CFB), CRC-24B (0x800063), CRC-8 (0x9B) per TS 38.212 Section 5.1.1.
6. Modulation
6.1 Modulation Mapper
File: lib/phy/upper/channel_modulation/modulation_mapper_lut_impl.h/.cpp
Supports QPSK, 16-QAM, 64-QAM, 256-QAM. Output is unit-average-power complex symbols. LUT variant pre-computes all constellation points; SIMD variants vectorize the lookup.
SIMD variants:
modulation_mapper_avx512_impl— 16 symbols per SIMD operation.modulation_mapper_neon_impl— 4-8 symbols per SIMD operation.
6.2 Demodulation Mapper (Soft-Bit Extraction)
File: lib/phy/upper/channel_modulation/demodulation_mapper_impl.h/.cpp
Computes approximate LLRs using the nearest-neighbour minimum-distance formula:
LLR(b_i) = -1/σ² × [ min_{s in S_{i,0}} |y - s|² - min_{s in S_{i,1}} |y - s|² ]
QAM-specific files (_qpsk, _qam16, _qam64, _qam256) pre-compute I/Q quadrant lookup tables for the minimum-distance search. LLR values are represented as log_likelihood_ratio (int8 or float32 depending on the path).
7. Channel Estimation
7.1 Port Channel Estimator
File: lib/phy/upper/signal_processors/channel_estimator/port_channel_estimator_average_impl.h/.cpp
Per-port, per-OFDM-symbol estimation:
- Extract DM-RS symbols from pilot RE positions.
- Least-squares channel estimate at pilot subcarriers.
- Frequency-domain interpolation across data subcarriers.
- Time-domain interpolation (if multiple DM-RS symbols exist in the slot).
- Noise variance estimated from pilot residuals.
7.2 PUSCH Channel Estimator
File: lib/phy/upper/signal_processors/pusch/dmrs_pusch_estimator_impl.h
Spawns one port_channel_estimator task per RX port in an executor pool. Aggregates results and fires dmrs_pusch_estimator_notifier.on_estimation_complete() when all ports are done.
DM-RS sequences:
- Type 1: 1 DM-RS OFDM symbol per slot.
- Type 2: 2 DM-RS OFDM symbols per slot.
- Pseudo-random (Gold) seeded by cell ID + UE ID.
- Optional low-PAPR sequences for transform-precoded PUSCH.
7.3 PUCCH Channel Estimator
Format-specific estimators:
dmrs_pucch_estimator_format2.cpp— 1 symbol, single RB.dmrs_pucch_estimator_formats3_4.cpp— multiple symbols and RBs.
8. DFT / FFT Backends
Interface: include/ocudu/phy/generic_functions/dft_processor.hdft_processor::run() performs in-place DFT/IDFT on a pre-allocated input buffer.
| Backend | File | Notes |
|---|---|---|
| FFTW | dft_processor_fftw_impl | Uses fftwf_plan; configurable ESTIMATE/MEASURE/EXHAUSTIVE; optional wisdom file |
| AMD AOCL (FFTZ) | dft_processor_fftz_impl | AMD FFTPACK wrapper; similar API |
| AVX2 CI16 | dft_processor_ci16_avx2 | Integer I/Q (int16); Cooley-Tukey radix-4 with AVX2 butterflies; used for small sizes |
| Generic | dft_processor_generic_impl | Scalar radix-2/4 fallback |
The factory in lib/phy/generic_functions/generic_functions_factories.cpp selects the backend. FFTW and FFTZ are compile-time options (ENABLE_FFTW, ENABLE_FFTZ). PRACH detection uses IDFT through this interface.
9. Resource Grid and Buffers
9.1 Resource Grid
File: lib/phy/support/resource_grid_impl.h/.cpp
A 3D tensor [subcarrier x OFDM_symbol x antenna_port] stored as cbf16_t (complex block float-16, reduced memory footprint vs float32). resource_grid_writer and resource_grid_reader provide the DL and UL views.
shared_resource_grid wraps the grid in a shared_ptr + pool notifier for automatic return on scope exit.
Pool (resource_grid_pool_impl): maintains N pre-allocated grids; allocate_resource_grid(slot) returns a round-robin grid. On release, the grid is async-zeroed if an executor is available.
9.2 RX Buffer Pool
File: lib/phy/upper/rx_buffer_pool_impl.h/.cpp
rx_buffer_pool_impl
├── rx_buffer_codeblock_pool shared pool of soft-bit CB buffers
├── rx_buffer_impl[] per (UE, HARQ process) buffers
├── trx_buffer_identifier[] identity: (RNTI, HARQ ID)
└── slot_point expiration[] buffer released after N slots
reserve(slot, id, nof_codeblocks, new_data) returns unique_rx_buffer. If new_data=false (retransmission), the same buffer is returned so LLRs combine across transmissions. Expired buffers are reclaimed automatically.
10. Sequence Generators
10.1 Gold Sequence (Pseudo-Random)
File: lib/phy/upper/sequence_generators/pseudo_random_generator_impl.h
Two LFSR registers x1 and x2 per TS 38.211 Section 5.2.1. Output: c[n] = (x1[n] + x2[n]) mod 2. c_init encodes cell ID, RNTI, or other context. The implementation uses bit-parallel LFSR (32 bits per cycle) and supports fast-advance via state transition matrices.
Used in: PDCCH DM-RS, PDSCH DM-RS, PBCH DM-RS, NZP-CSI-RS, PSS, PRS, scrambling.
10.2 Low-PAPR (Zadoff-Chu / Cyclic-Shifted)
File: lib/phy/upper/sequence_generators/low_papr_sequence_generator_impl.h
Zadoff-Chu: u[k] = exp(-j pi u k(k+1) / N) for root u and length N. Used in PRACH preamble generation and transform-precoded PUSCH (DFT-s-OFDM).
11. Hardware Acceleration Integration
Two *_hw_impl classes exist as drop-in replacements for SW implementations:
pdsch_encoder_hw_impl(lib/phy/upper/channel_processors/pdsch/) — wrapshal_ldpc_encoder.pusch_decoder_hw_impl(lib/phy/upper/channel_processors/pusch/) — wrapshal_ldpc_decoder.
The HAL interface (include/ocudu/hal/hw_accelerator.h) is the abstraction layer for accelerator devices (ACC100/ACC200/VRB1 in the implemented backend). Factory selection in lib/phy/upper/upper_phy_factories.cpp chooses between HW and SW based on build-time and runtime configuration. If hardware_encoder_available && use_hw_encoder, the HW variant is instantiated; otherwise the AVX2 or generic SW path is used.
Modulation and DFT remain on the CPU even when LDPC is offloaded. See the Hardware Acceleration section for HAL and BBDev details.
12. Concurrency Model
Downlink: Multi-Executor Task-Based
Each DL PDU type runs on a dedicated task_executor:
process_pdcch(pdu) → enqueue on pdcch_executor
process_pdsch(pdu) → enqueue on pdsch_executor
process_ssb(pdu) → enqueue on ssb_executor
process_nzp_csi_rs → enqueue on csi_rs_executor
A counter tracks pending tasks. The resource grid is sent to the RU only when pending_pdus == 0 && should_finish. This provides per-channel parallelism within a slot without requiring locks on the resource grid (each channel type writes to non-overlapping RE positions).
Uplink: Event-Driven with FSM
Within PROCESSING, DM-RS estimation tasks run in an executor pool. Each PUSCH PDU acquires a concurrent_dependencies object (estimator + demodulator + UCI decoder). Multiple UEs’ PUSCH can be estimated in parallel; each individual decode sequence (demod → rate dematch → LDPC) is serial per PDU.
13. DU-Low Interface
Downlink Request
unique_downlink_processor dp =
upper_phy.get_downlink_processor_pool()
.get_processor_controller(slot)
.configure_resource_grid(context, grid);
dp.process_pdcch(pdcch_pdu);
dp.process_pdsch(transport_blocks, pdsch_pdu);
dp.process_ssb(ssb_pdu);
// dp destroyed here → finish_processing_pdus() called → grid sent to RU
Uplink Request
upper_phy.get_uplink_request_processor().process_uplink_slot_request(context, grid);
upper_phy.get_uplink_request_processor().process_prach_request(prach_context);
Result Callbacks (Upper PHY → DU-Low)
notifier.on_new_pusch_results_data({ rnti, slot, harq_id, decoder_result, payload, csi });
notifier.on_new_pucch_results({ rnti, slot, format, harq_ack, sr, csi });
notifier.on_new_prach_results({ rnti, slot, time_advance });
All results are delivered via upper_phy_rx_results_notifier_wrapper which forwards to the DU-High MAC.
14. 3GPP References in Code
| Standard | Clause | Coverage |
|---|---|---|
| TS 38.211 | Section 5.2.1 | Gold sequence generation |
| TS 38.211 | Section 7.4.1.1 | PDSCH DM-RS RE patterns |
| TS 38.211 | Section 7.4.1.5 | NZP-CSI-RS patterns |
| TS 38.211 | Section 7.3.1 | PDSCH resource mapping |
| TS 38.211 | Section 7.3.2 | PDCCH resource mapping |
| TS 38.211 | Section 6.3.3.1 | PRACH preamble format |
| TS 38.212 | Section 5.1 | Polar coding |
| TS 38.212 | Section 5.2.2 | LDPC segmentation |
| TS 38.212 | Section 5.3.1 | Polar code construction |
| TS 38.212 | Section 5.3.2 | LDPC base graphs BG1 / BG2 |
| TS 38.212 | Section 5.4.2.1 | LDPC rate matching (circular buffer) |
| TS 38.213 | Section 8.1.1 | PDCCH aggregation levels |
15. File Reference Index
| Component | Header | Implementation |
|---|---|---|
| Upper PHY orchestrator | upper_phy_impl.h | upper_phy_impl.cpp |
| DL processor pool | downlink_processor_pool_impl.h | downlink_processor_pool_impl.cpp |
| DL processor | downlink_processor_multi_executor_impl.h | downlink_processor_multi_executor_impl.cpp |
| PDSCH processor | pdsch_processor_impl.h | pdsch_processor_impl.cpp |
| PDCCH processor | pdcch_processor_impl.h | pdcch_processor_impl.cpp |
| SSB processor | ssb_processor_impl.h | ssb_processor_impl.cpp |
| NZP-CSI-RS generator | nzp_csi_rs_generator_impl.h | nzp_csi_rs_generator_impl.cpp |
| UL processor pool | uplink_processor_pool_impl.h | uplink_processor_pool_impl.cpp |
| UL processor | uplink_processor_impl.h | uplink_processor_impl.cpp |
| PUSCH processor | pusch_processor_impl.h | pusch_processor_impl.cpp |
| PUCCH processor | pucch_processor_impl.h | pucch_processor_impl.cpp |
| PRACH detector | prach_detector_generic_impl.h | prach_detector_generic_impl.cpp |
| LDPC encoder | ldpc_encoder_impl.h | ldpc_encoder_impl.cpp, _avx2.cpp, _neon.cpp |
| LDPC decoder | ldpc_decoder_impl.h | _generic.cpp, _avx2.cpp, _avx512.cpp, _neon.cpp |
| LDPC graph | ldpc_graph_impl.h | ldpc_graph_impl.cpp |
| LDPC rate matcher | ldpc_rate_matcher_impl.h | ldpc_rate_matcher_impl.cpp |
| LDPC segmenter (TX) | ldpc_segmenter_tx_impl.h | ldpc_segmenter_tx_impl.cpp |
| Polar encoder | polar_encoder_impl.h | polar_encoder_impl.cpp |
| Polar decoder | polar_decoder_impl.h | polar_decoder_impl.cpp |
| Modulation mapper (LUT) | modulation_mapper_lut_impl.h | modulation_mapper_lut_impl.cpp |
| Modulation mapper (AVX512) | modulation_mapper_avx512_impl.h | modulation_mapper_avx512_impl.cpp |
| Demodulation mapper | demodulation_mapper_impl.h | demodulation_mapper_impl.cpp |
| Port channel estimator | port_channel_estimator_average_impl.h | port_channel_estimator_average_impl.cpp |
| PUSCH channel estimator | dmrs_pusch_estimator_impl.h | dmrs_pusch_estimator_impl.cpp |
| PDSCH DM-RS | dmrs_pdsch_processor_impl.h | dmrs_pdsch_processor_impl.cpp |
| PDCCH DM-RS | dmrs_pdcch_processor_impl.h | dmrs_pdcch_processor_impl.cpp |
| PBCH DM-RS | dmrs_pbch_processor_impl.h | dmrs_pbch_processor_impl.cpp |
| PSS generator | pss_processor_impl.h | pss_processor_impl.cpp |
| SSS generator | sss_processor_impl.h | sss_processor_impl.cpp |
| Gold sequence generator | pseudo_random_generator_impl.h | pseudo_random_generator_impl.cpp |
| DFT (FFTW) | dft_processor_fftw_impl.h | dft_processor_fftw_impl.cpp |
| DFT (FFTZ) | dft_processor_fftz_impl.h | dft_processor_fftz_impl.cpp |
| DFT (AVX2 CI16) | dft_processor_ci16_avx2.h | dft_processor_ci16_avx2.cpp |
| Resource grid | resource_grid_impl.h | resource_grid_impl.cpp |
| Resource grid pool | resource_grid_pool_impl.h | resource_grid_pool_impl.cpp |
| RX buffer pool | rx_buffer_pool_impl.h | rx_buffer_pool_impl.cpp |
| CRC calculator | crc_calculator_*.h | crc_calculator_lut_impl.cpp, _clmul_impl.cpp, _neon_impl.cpp |
| PDSCH encoder HW | pdsch_encoder_hw_impl.h | pdsch_encoder_hw_impl.cpp |
| PUSCH decoder HW | pusch_decoder_hw_impl.h | pusch_decoder_hw_impl.cpp |