Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
openairinterface-6g
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenXG
openairinterface-6g
Commits
0713b2f6
Commit
0713b2f6
authored
Nov 04, 2025
by
Robert Schmidt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rewrite doc/SW-archi-graph.md
parent
15441c74
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
92 additions
and
69 deletions
+92
-69
doc/SW-archi-graph.md
doc/SW-archi-graph.md
+92
-69
No files found.
doc/SW-archi-graph.md
View file @
0713b2f6
This document is a high-level overview over the L1 threading mechanism.
```
mermaid
```
mermaid
flowchart TB
flowchart TB
A[ru_thread] --> RFin>block rx_rf] --> feprx
ru_thread --> RFin[block rx_rf] --> UL{is UL slot?}
feprx --> half-slot --> end_feprx
UL -- yes --> wait_free_rx_tti --> fep_rx --> rx_nr_prach_ru --> msg:L1_tx_out
feprx --> second-thread -- block_end_feprx --> end_feprx>feprx]
UL -- no --> msg:L1_tx_out
end_feprx --> rx_nr_prach_ru
msg:L1_tx_out -- asnyc launch --> L1_tx_thread
rx_nr_prach_ru -- block_queue_singleton --> resp_L1>resp L1]
msg:L1_tx_out --> RFin
resp_L1 -- async launch --> rx_func
```
resp_L1 -- immediate return --> RFin
The main thread is
`ru_thread()`
. It blocks on reception of radio samples
subgraph rxfunc
(either time domain or frequency domain). In the case of an UL slot, it waits
rx_func_implem[rx_func]
that no more than N UL jobs are scheduled (via
`wait_free_rx_tti()`
, which
subgraph rxfuncbeg
waits on queue
`L1_rx_out`
, cf. the RX L1 processing further below). Then:
handle_nr_slot_ind
--> rnti_to_remove-mgmt
-
if the radio is time domain-based, it performs RX front-end processing (RX
--> L1_nr_prach_procedures
FEP ->
`fep_rx()`
, i.e. DFT) to reach a frequency domain representation of
--> apply_nr_rotation_RX
the RX signal, as well as does DFT for PRACH.
end
-
if the radio is frequency domain-based, nothing is done.
subgraph phy_procedures_gNB_uespec_RX
fill_ul_rb_mask
Afterwards, it triggers TX processing by pushing a message into the FIFO queue
--> pucch(decode each gNB->pucch)
`L1_tx_out`
, which asynchronously starts a TX job in
`L1_tx_thread()`
(see
-->nr_fill_ul_indication
below). After that, it blocks again on reception on the radio.
--> nr_ulsch_procedures
--> nr_ulsch_decoding
--> segInParallel[[all segments decode in parallel]]
```
mermaid
--> barrier_end_of_ulsch_decoding
flowchart TB
end
L1_tx_thread --> TX_in[block L1_tx_out] --> NR_slot_indication
subgraph NR_UL_indication
handle_nr_rach
subgraph tx_func
--> handle_nr_uci
--> handle_nr_ulsch
NR_slot_indication --> msg:resp_L1 --> phy_procedures_gNB_tx --> ru_tx_func
subgraph gNB_dlsch_ulsch_scheduler
NR_slot_indication["run the scheduler:
run_pdcp
- monolithic: run_scheduler_monolithic()
--> schedule_xxxx
- nFAPI: send indication via pnf_send_slot_ind()"]
end
msg:resp_L1 -- async launch --> L1_RX_thread
handle_nr_ulsch --> gNB_dlsch_ulsch_scheduler
subgraph NR_Schedule_response
L1_tx_free3>L1_tx_free]
--> handle_nr_nfapi_xxx_pdu
--> sendTxFilled((L1_tx_filled))
--> nr_fill_ul_xxx
--> nr_schedule_rx_prach()
end
gNB_dlsch_ulsch_scheduler --> NR_Schedule_response
end
rx_func_implem --> rxfuncbeg
rxfuncbeg --> phy_procedures_gNB_uespec_RX
phy_procedures_gNB_uespec_RX --> NR_UL_indication
-- block_queue_block_PNF_monolithic --> L1_tx_free2>L1 tx filled]
-- async launch --> tx_func
L1_tx_free2 -- send_msg --> rsp((resp_L1))
end
rx_func --> rxfunc
subgraph tx_func
direction LR
subgraph phy_procedures_gNB_TX
dcitop[nr_generate dci top]
--> nr_generate_csi_rs
--> apply_nr_rotation_TX
-- send_msg --> end_tx_func((L1_tx_out))
end
subgraph tx_reorder_thread
L1_tx_out>L1_tx_out]
--> reorder{re order} --> reorder
reorder --> ru_tx_func
reorder --> L1_tx_free((L1_tx_free))
ru_tx_func --> feptx_prec
--> feptx_ofdm
end
end
end
ru_tx_func --> TX_in
```
The
`L1_tx_thread()`
processes individual TX jobs sequentially, by waiting for
new messages on queue
`L1_tx_out`
, signalling individual TX jobs. For each
message, it calls
`tx_func()`
which does in order:
-
run the scheduler through
`NR_slot_indication`
, which corresponds to a
"Slot.indication" in FAPI parlance. This runs the scheduler, and schedules a
given slot (either downlink, uplink, or both).
-
trigger RX processing by pushing a message into the FIFO queue
`resp_L1`
,
asynchronously starting an RX job in
`L1_rx_thread()`
(see below).
-
process the current L1 TX job through
`phy_procedures_gNB_tx()`
-
write to the radio board via
`ru_tx_func()`
.
After these steps,
`tx_func()`
return to
`L1_tx_thread()`
, which will wait for
the next TX job.
```
mermaid
flowchart TB
L1_rx_thread --> RX_in[block resp_L1] --> L1_nr_prach_proc
subgraph rx_func
L1_nr_prach_proc --> phase_comp{apply phase comp.?}
phase_comp -- yes --> apply_nr_rotation --> phy_procedures_gNB_uespec_RX
phase_comp -- no --> phy_procedures_gNB_uespec_RX
phy_procedures_gNB_uespec_RX --> NR_ul_indication --> msg:L1_rx_out
NR_ul_indication["run the scheduler: NR_UL_indication()"]
msg:L1_rx_out -- async signal free --> ru_thread
end
msg:L1_rx_out --> RX_in
```
```
The
`L1_rx_thread()`
processes individual RX jobs sequentially. It waits for a
new RX job through the queue
`resp_L1`
, and then calls
`rx_func()`
, which does
in order:
-
run PRACH processing via
`L1_nr_prach_proc()`
-
optionally apply rotation to the RX signal if phase compensation is to be
applied
-
run the current L1 RX job through (
`phy_procedures_gNB_uespec_RX()`
), which
notably includes PUCCH, PUSCH, SRS processing
-
call the scheduler through
`NR_ul_indication()`
, which corresponds to FAPI
uplink messages (e.g.,
`RX_data.indication`
,
`CRC.indication`
,
`UCI.indication`
etc.)
-
signal completion via FIFO queue
`L1_rx_out()`
, which tells
`ru_thread()`
that RX processing finished.
The signalling of scheduler data is done through a variable
`UL_INFO`
, which is
filled by
`L1_nr_prach_proc()`
(for PRACH) and
`phy_procedures_gNB_uespec_RX()`
(for PUCCH, PUSCH, SRS).
After these steps,
`rx_func()`
returns to
`L1_rx_thread()`
, which will wait the
next RX job.
Note that while individual TX (RX) jobs are run sequentially through
`L1_tx_thread()`
(
`L1_rx_thread()`
), both TX and RX processing run in
parallel.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment