mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 13:10:28 +00:00
Compare commits
9 Commits
config_api
...
tutorial-v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6103a6fe5d | ||
|
|
b98b0c4d32 | ||
|
|
1d659aaf9c | ||
|
|
58a26fd8b4 | ||
|
|
15f1b77077 | ||
|
|
54c5590eee | ||
|
|
cf9b1b12dc | ||
|
|
fea52dc3d0 | ||
|
|
48c10bee5c |
@@ -282,7 +282,7 @@ add_boolean_option(TRACY_ENABLE OFF "Enable tracy instrumentation" ON)
|
||||
if (TRACY_ENABLE)
|
||||
# the tracy version here should match the tracy server version
|
||||
# below is latest release as of this commit
|
||||
CPMAddPackage("gh:wolfpld/tracy#0.12.2")
|
||||
CPMAddPackage("gh:wolfpld/tracy#v0.12.2")
|
||||
endif()
|
||||
|
||||
set (OCP_ITTI ${OPENAIR_DIR}/common/utils/ocp_itti)
|
||||
|
||||
100
doc/tutorial_resources/vrtsim/channel_modelling_basics.md
Normal file
100
doc/tutorial_resources/vrtsim/channel_modelling_basics.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# About
|
||||
|
||||
In this step usage of channel modelling with `vrtsim` will be explained
|
||||
|
||||
# Configure
|
||||
|
||||
Modify the gNB config file at `targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf`. Add the following at the end:
|
||||
|
||||
```
|
||||
channelmod = {
|
||||
max_chan=10;
|
||||
modellist="modellist_rfsimu_1";
|
||||
modellist_rfsimu_1 = (
|
||||
{
|
||||
model_name = "server_tx_channel_model"
|
||||
type = "AWGN";
|
||||
ploss_dB = 0;
|
||||
noise_power_dB = 0;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
}
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
# (Optional) Run UE with scope to visualize the impact
|
||||
|
||||
```
|
||||
cmake ../../ -DENABLE_IMSCOPE=ON
|
||||
```
|
||||
|
||||
```
|
||||
cmake --build . --target imscope
|
||||
```
|
||||
|
||||
Add `--imscope` to UE command line
|
||||
|
||||
# Run
|
||||
|
||||
```
|
||||
sudo ./nr-softmodem -O ../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --device.name vrtsim --vrtsim.role server --vrtsim.chanmod 1
|
||||
```
|
||||
|
||||
```
|
||||
sudo ./nr-uesoftmodem -C 3619200000 -r 106 --numerology 1 --ssb 516 --band 78 --device.name vrtsim
|
||||
```
|
||||
|
||||
# Modifying the channel model
|
||||
|
||||
Try the following settings:
|
||||
|
||||
```
|
||||
modellist_rfsimu_1 = (
|
||||
{
|
||||
model_name = "server_tx_channel_model"
|
||||
type = "Rayleigh8";
|
||||
ploss_dB = 0;
|
||||
noise_power_dB = 0;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
}
|
||||
);
|
||||
```
|
||||
```
|
||||
modellist_rfsimu_1 = (
|
||||
{
|
||||
model_name = "server_tx_channel_model"
|
||||
type = "AWGN";
|
||||
ploss_dB = -5;
|
||||
noise_power_dB = 0;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
}
|
||||
);
|
||||
```
|
||||
```
|
||||
modellist_rfsimu_1 = (
|
||||
{
|
||||
model_name = "server_tx_channel_model"
|
||||
type = "AWGN";
|
||||
ploss_dB = -10;
|
||||
noise_power_dB = 0;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
Add noise:
|
||||
|
||||
```
|
||||
channelmod = {
|
||||
max_chan=10;
|
||||
modellist="modellist_rfsimu_1";
|
||||
noise_power_dBFS = -42;
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
# About
|
||||
|
||||
Precomputed 3GPP 38.901 TDL profiles (A to E) with statistical MIMO channels, plus a Python emitter that publishes taps to VRTSIM over a nanomsg PUB socket using FlatBuffers. Supports multiple antenna shapes (up to 64x64), speed presets (walking about 1.5 m/s, car about 30 m/s), spatial correlation, mutual coupling, LOS steering for D and E, and time-varying lognormal shadowing.
|
||||
|
||||
---
|
||||
|
||||
## 1) Setup
|
||||
|
||||
python3 -m pip install --user flatbuffers nanomsg numpy pyyaml
|
||||
cd ~/raytracing-channel-emulator/server/api
|
||||
flatc --python -o . taps.fbs # generates ./Phy/Taps.py
|
||||
export PYTHONPATH="$(pwd):$PYTHONPATH"
|
||||
|
||||
# switch to external_taps for the tools below
|
||||
cd ~/raytracing-channel-emulator/server/external_taps
|
||||
|
||||
---
|
||||
|
||||
## 2) Generate the CIR file
|
||||
|
||||
Default profiles, delay spreads, antenna shapes, and speed presets are embedded.
|
||||
Shadowing is enabled by default, lognormal per link, time varying across snapshots via AR(1).
|
||||
|
||||
This command writes:
|
||||
- binary taps file: ./cir_db.bin
|
||||
- YAML sidecar with per-entry metadata: ./cir_db.yaml (used by the emitter to resolve selections and offsets)
|
||||
|
||||
python3 CIR_generator.py --out ./cir_db.bin
|
||||
|
||||
To change shadowing, pass --shadow-sigma-db and optionally --shadow-tau-c-s for the correlation time. Set sigma to 0 to disable.
|
||||
|
||||
---
|
||||
|
||||
## 3) Run the emitter
|
||||
|
||||
Sequential replay, one snapshot every 0.5 s:
|
||||
|
||||
python3 emit_from_db.py --bind tcp://127.0.0.1:5555 --db ./cir_db.bin --model TDL-A --ds-ns 30 --nrx 1 --ntx 1 --interval 0.5
|
||||
|
||||
List what is in the database:
|
||||
|
||||
python3 emit_from_db.py --db ./cir_db.bin --describe-db
|
||||
|
||||
Optional, print the selected entry before streaming:
|
||||
|
||||
python3 emit_from_db.py --db ./cir_db.bin --print-selected
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 4) Run OAI with VRTSIM
|
||||
|
||||
gNB (server role):
|
||||
|
||||
sudo ./nr-softmodem -O ../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --device.name vrtsim --vrtsim.role server --vrtsim.taps-socket tcp://127.0.0.1:5555 --gNBs.[0].min_rxtxtime 3
|
||||
|
||||
UE (client role):
|
||||
|
||||
sudo ./nr-uesoftmodem -C 3619200000 -r 106 --numerology 1 --ssb 516 --band 78 --device.name vrtsim --vrtsim.role client
|
||||
145
doc/tutorial_resources/vrtsim/first_steps.md
Normal file
145
doc/tutorial_resources/vrtsim/first_steps.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# About
|
||||
|
||||
In this step the basics of compiling and running `vrtsim` will be explained.
|
||||
|
||||
# About vrtsim
|
||||
|
||||
vrtsim is a realtime/fixed timescale split8 device emulator. The main difference between
|
||||
rfsim and vrtsim is the timing constraints vrtsim forces on the applications that use it.
|
||||
|
||||
# Compiling
|
||||
|
||||
Start by making a new directory under `cmake_targets`
|
||||
|
||||
```bash
|
||||
mkdir -p cmake_targets/build/
|
||||
```
|
||||
|
||||
Compile vrtsim + RAN elements
|
||||
|
||||
```bash
|
||||
cd /cmake_targets/build
|
||||
cmake ../../ -GNinja
|
||||
cmake --build . --target vrtsim nr-softmodem nr-uesoftmodem ldpc params_libconfig params_yaml
|
||||
```
|
||||
|
||||
# Running
|
||||
|
||||
Run a basic testcase to verify connectivity, no core network present
|
||||
|
||||
```bash
|
||||
sudo ./nr-softmodem -O ../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --device.name vrtsim --vrtsim.role server
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo ./nr-uesoftmodem -C 3619200000 -r 106 --numerology 1 --ssb 516 --band 78 --device.name vrtsim
|
||||
```
|
||||
|
||||
# Verification
|
||||
|
||||
Goal is to have the UE connect for now (i.e. enter RRC Connected mode). The success depends on your
|
||||
CPU speed.
|
||||
|
||||
## Example NR UE output when UE is connected
|
||||
|
||||
```
|
||||
[PHY] Initial sync: pbch decoded sucessfully, ssb index 0
|
||||
[PHY] pbch rx ok. rsrp:51 dB/RE, adjust_rxgain:-1 dB
|
||||
[NR_PHY] Cell Detected with GSCN: 0, SSB SC offset: 516, SSB Ref: 0.000000, PSS Corr peak: 99 dB, PSS Corr Average: 61
|
||||
[PHY] [UE0] In synch, rx_offset 444704 samples
|
||||
[PHY] [UE 0] Measured Carrier Frequency offset 6 Hz
|
||||
[PHY] Initial sync successful, PCI: 0
|
||||
[PHY] HW: Configuring channel 0 (rf_chain 0): setting tx_freq 3619200006 Hz, rx_freq 3619200006 Hz, tune_offset 0
|
||||
[PHY] Got synch: hw_slot_offset 29, carrier off 6 Hz, rxgain 110.000000 (DL 3619200006.000000 Hz, UL 3619200006.000000 Hz)
|
||||
[PHY] UE synchronized! decoded_frame_rx=404 UE->init_sync_frame=0 trashed_frames=14
|
||||
[PHY] Resynchronizing RX by 444704 samples
|
||||
[HW] received write reorder clear context
|
||||
[NR_RRC] SIB1 decoded
|
||||
[NR_MAC] TDD period index = 6, based on the sum of dl_UL_TransmissionPeriodicity from Pattern1 (5.000000 ms) and Pattern2 (0.000000 ms): Total = 5.000000 ms
|
||||
[NR_MAC] Set TDD configuration period to: 8 DL slots, 3 UL slots, 10 slots per period (NR_TDD_UL_DL_Pattern is 7 DL slots, 2 UL slots, 6 DL symbols, 4 UL symbols)
|
||||
[NR_MAC] Configured 1 TDD patterns (total slots: pattern1 = 10, pattern2 = 0)
|
||||
[PHY] N_TA_offset changed from 0 to 800
|
||||
[MAC] Initialization of 4-Step CBRA procedure
|
||||
[NR_MAC] PRACH scheduler: Selected RO Frame 421, Slot 19, Symbol 0, Fdm 0
|
||||
[PHY] PRACH [UE 0] in frame.slot 421.19, placing PRACH in position 2828, Msg1/MsgA-Preamble frequency start 0 (k1 0), preamble_offset 6, first_nonzero_root_idx 0, preambleIndex = 27
|
||||
[PHY] [UE 0] RAR-Msg2 decoded
|
||||
[NR_MAC] [UE 0][RAPROC][RA-RNTI 010b] Got BI RAR subPDU 5 ms
|
||||
[NR_MAC] [UE 0][RAPROC][RA-RNTI 010b] Got RAPID RAR subPDU
|
||||
[NR_MAC] [UE 0][RAPROC][422.10] Found RAR with the intended RAPID 27
|
||||
[MAC] received TA command 31
|
||||
[NR_MAC] [RAPROC][422.19] RA-Msg3 transmitted
|
||||
[MAC] [UE 0][423.10][RAPROC] 4-Step RA procedure succeeded. CBRA: Contention Resolution is successful.
|
||||
[NR_RRC] [UE0][RAPROC] Logical Channel DL-CCCH (SRB0), Received NR_RRCSetup
|
||||
[RLC] Added srb 1 to UE 0
|
||||
[NR_RRC] State = NR_RRC_CONNECTED
|
||||
```
|
||||
|
||||
## Example gNB output when connected
|
||||
|
||||
```
|
||||
[NR_PHY] [RAPROC] 421.19 Initiating RA procedure with preamble 27, energy 31.7 dB (I0 0, thres 120), delay 0 start symbol 0 freq index 0
|
||||
[NR_MAC] 421.19 UE RA-RNTI 010b TC-RNTI 2c32: initiating RA procedure
|
||||
[NR_MAC] UE 2c32: Msg3 scheduled at 422.19 (422.10 TDA 0) start 0 RBs 8
|
||||
[NR_MAC] UE 2c32: 422.10 Generating RA-Msg2 DCI, RA RNTI 0x10b, state 1, preamble_index(RAPID) 27, timing_offset = 0 (estimated distance 0.0 [m])
|
||||
[NR_MAC] 422.10 Send RAR to RA-RNTI 010b
|
||||
[NR_MAC] 422.19 PUSCH with TC_RNTI 0x2c32 received correctly
|
||||
[MAC] [RAPROC] Received SDU for CCCH length 6 for UE 2c32
|
||||
[RLC] Activated srb0 for UE 11314
|
||||
[RLC] Added srb 1 to UE 11314
|
||||
[NR_MAC] Activating scheduling Msg4 for TC_RNTI 0x2c32 (state WAIT_Msg3)
|
||||
[NR_RRC] Decoding CCCH: RNTI 2c32, payload_size 6
|
||||
[NR_RRC] [--] (cellID 0, UE ID 1 RNTI 2c32) Create UE context: CU UE ID 1 DU UE ID 11314 (rnti: 2c32, random ue id 1c14de2d3f000000)
|
||||
[RRC] activate SRB 1 of UE 1
|
||||
[NR_RRC] [DL] (cellID bc614e, UE ID 1 RNTI 2c32) Send RRC Setup
|
||||
[NR_MAC] UE 2c32 Generate Msg4: feedback at 423.17, payload 225 bytes, next state nrRA_WAIT_Msg4_MsgB_ACK
|
||||
[NR_MAC] 423.17 UE 2c32: Received Ack of Msg4. CBRA procedure succeeded (UE Connected)
|
||||
[NR_MAC] Adding new UE context with RNTI 0x2c32
|
||||
[NR_RRC] [UL] (cellID bc614e, UE ID 1 RNTI 2c32) Received RRCSetupComplete (RRC_CONNECTED reached)
|
||||
```
|
||||
|
||||
## Troubleshooting:
|
||||
In case the UE does not connect:
|
||||
|
||||
Interrupt the process using `CTRL + C` and analyze `vrtsim` stdout at the end. You should see the histogram
|
||||
print from `vrtsim`
|
||||
|
||||
Example from a working configuration:
|
||||
```
|
||||
[HW] VRTSIM: Realtime issues: TX 0.00%, RX 0.00%
|
||||
[HW] VRTSIM: Read/write too early (suspected radio implementaton error) TX: 0, RX: 0
|
||||
[HW] VRTSIM: Average TX budget 913.111 uS (more is better)
|
||||
[HW] VRTSIM: TX budget histogram: 6468 samples
|
||||
[HW] Bin 0 [0.0 - 100.0uS]: 0
|
||||
[HW] Bin 1 [100.0 - 200.0uS]: 0
|
||||
[HW] Bin 2 [200.0 - 300.0uS]: 0
|
||||
[HW] Bin 3 [300.0 - 400.0uS]: 0
|
||||
[HW] Bin 4 [400.0 - 500.0uS]: 1
|
||||
[HW] Bin 5 [500.0 - 600.0uS]: 0
|
||||
[HW] Bin 6 [600.0 - 700.0uS]: 0
|
||||
[HW] Bin 7 [700.0 - 800.0uS]: 1
|
||||
[HW] Bin 8 [800.0 - 900.0uS]: 125
|
||||
[HW] Bin 9 [900.0 - 1000.0uS]: 6242
|
||||
[HW] Bin 10 [1000.0 - 1100.0uS]: 0
|
||||
[HW] Bin 11 [1100.0 - 1200.0uS]: 0
|
||||
```
|
||||
|
||||
The histogram above indicates if the application encountered any timing related issues. If the average TX budget
|
||||
is low (near ~0) or bin 0 is being filled that could mean that your CPU is too slow.
|
||||
|
||||
Possible fixes:
|
||||
- Try disabling idle states
|
||||
```bash
|
||||
sudo cpupower idle-set -D 0
|
||||
```
|
||||
- Change cpu frequency scaling governor to performance
|
||||
```bash
|
||||
sudo cpupower frequency-set --governor performance
|
||||
```
|
||||
- Modify this line in the code of the UE and rebuild:
|
||||
```diff
|
||||
-#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (3)
|
||||
+#define NR_UE_CAPABILITY_SLOT_RX_TO_TX (6)
|
||||
```
|
||||
|
||||
If that doesnt work, adjust `--vrtsim.timescale <timescale>` argument on `nr-softmodem`.
|
||||
Start lowering the timescale (e.g. to 0.2) to slow down time until the UE connects.
|
||||
95
doc/tutorial_resources/vrtsim/ip_traffic.md
Normal file
95
doc/tutorial_resources/vrtsim/ip_traffic.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# About
|
||||
|
||||
In this step using `iperf` to test the modems performance is explained.
|
||||
|
||||
# Running
|
||||
|
||||
## Option 1: --noS1 mode
|
||||
|
||||
Select this option on slower machines. This doesn't require core network.
|
||||
|
||||
1. Run gNB
|
||||
|
||||
```bash
|
||||
sudo ./nr-softmodem -O ../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --device.name vrtsim --vrtsim.role server --noS1 --do-ra
|
||||
```
|
||||
|
||||
2. Create UE namespace
|
||||
|
||||
```bash
|
||||
sudo ip netns add ue_ns
|
||||
```
|
||||
|
||||
2. Run UE in the new namespace
|
||||
|
||||
```bash
|
||||
sudo ip netns exec ue_ns bash
|
||||
sudo ./nr-uesoftmodem -C 3619200000 -r 106 --numerology 1 --ssb 516 --band 78 --device.name vrtsim --noS1 --do-ra
|
||||
```
|
||||
|
||||
3. Run iperf server in the UE namespace
|
||||
|
||||
```bash
|
||||
sudo ip netns exec ue_ns bash
|
||||
iperf -s -B 10.0.1.2
|
||||
```
|
||||
|
||||
4. Run iperf client in host namespace
|
||||
|
||||
```bash
|
||||
iperf -c 10.0.1.2 -B 10.0.1.1
|
||||
```
|
||||
|
||||
## Option 2: with core network
|
||||
|
||||
1. Start `cn` in `doc/tutorial_resources/oai-cn5g` with `docker compose up`
|
||||
|
||||
2. Run gNB
|
||||
|
||||
```bash
|
||||
sudo ./nr-softmodem -O ../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --device.name vrtsim --vrtsim.role server
|
||||
```
|
||||
|
||||
3. Verify connection to core network in gNB stdout
|
||||
|
||||
```
|
||||
[NGAP] Send NGSetupRequest to AMF
|
||||
[NGAP] 3584 -> 0000e000
|
||||
[NGAP] Served GUAMIs for AMF OAI-AMF (assoc_id=3):
|
||||
[NGAP] GUAMI:
|
||||
[NGAP] PLMN: MCC=001, MNC=01
|
||||
[NGAP] AMF Region ID: 1
|
||||
[NGAP] AMF Set ID: 1
|
||||
[NGAP] AMF Pointer: 1
|
||||
[NGAP] Supported PLMN 0: MCC=001 MNC=01
|
||||
[NGAP] Supported slice (PLMN 0): SST=0x01 SD=000
|
||||
[NGAP] Received NGSetupResponse from AMF
|
||||
```
|
||||
|
||||
4. Connect the UE.
|
||||
|
||||
```bash
|
||||
sudo ./nr-uesoftmodem -C 3619200000 -r 106 --numerology 1 --ssb 516 --band 78 --device.name vrtsim --uicc0.imsi 001010000000001
|
||||
```
|
||||
|
||||
5. Verify interface is created
|
||||
|
||||
```
|
||||
[OIP] Interface oaitun_ue1 successfully configured, IPv4 10.0.0.2, IPv6 (null)
|
||||
```
|
||||
|
||||
```bash
|
||||
ifconfig | grep tun
|
||||
```
|
||||
|
||||
6. Run iperf in oai-ext-dn container
|
||||
|
||||
```bash
|
||||
docker exec -it oai-ext-dn bash
|
||||
iperf -c 10.0.0.2 -B 192.168.70.135
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Use the same steps as from `first_steps.md`. This test adds additional requirements
|
||||
on the CPU which might cause the UE to fail.
|
||||
17
doc/tutorial_resources/vrtsim/oru-demo.md
Normal file
17
doc/tutorial_resources/vrtsim/oru-demo.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# About
|
||||
|
||||
Just a demonstration of what we need vrtsim for
|
||||
|
||||
# Running
|
||||
|
||||
```
|
||||
sudo -E LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu/:. -E ASAN_OPTIONS=detect_odr_violation=0 ./oainr_ru -O ~/ru.band77.106prb.fhi72.2x2.conf --vrtsim.role server
|
||||
```
|
||||
|
||||
```
|
||||
sudo -E LD_LIBRARY_PATH=/usr/local/lib/x86_64-linux-gnu/:. -E ASAN_OPTIONS=detect_odr_violation=0 ./nr-softmodem -O ~/gnb.2x2.conf --gNBs.[0].min_rxtxtime 6
|
||||
```
|
||||
|
||||
```
|
||||
sudo -E LD_LIBRARY_PATH=. ./nr-uesoftmodem -C 4049760000 -r 106 --numerology 1 --ssb 516 --band 77 --device.name vrtsim
|
||||
```
|
||||
6
doc/tutorial_resources/vrtsim/prep.md
Normal file
6
doc/tutorial_resources/vrtsim/prep.md
Normal file
@@ -0,0 +1,6 @@
|
||||
1. Clone https://gitlab.eurecom.fr/oai/raytracing-channel-emulator
|
||||
2. Run: sudo apt install git-lfs
|
||||
3. In the cloned repository, run: git lfs fetch and git lfs checkout
|
||||
4. Install the required Python packages listed here
|
||||
5. sudo apt install -y llvm-dev libnanomsg-dev flatbuffers-compiler
|
||||
6. Godot 4.4 for the test platform (optional) https://godotengine.org/download/archive/4.4-stable/
|
||||
30
doc/tutorial_resources/vrtsim/raytracing-ce.md
Normal file
30
doc/tutorial_resources/vrtsim/raytracing-ce.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# About
|
||||
|
||||
This tutorial will showcase the usage fo channel emulation server to provide realistic ray-traced channel to the softmodems
|
||||
|
||||
# Compiling
|
||||
|
||||
Reuse the previous step binaries
|
||||
|
||||
```
|
||||
cmake ../../ -DOAI_VRTSIM_TAPS_CLIENT=ON
|
||||
```
|
||||
|
||||
# Running
|
||||
|
||||
```
|
||||
sudo ./nr-softmodem -O ../../targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf --gNBs.[0].min_rxtxtime 6 --device.name vrtsim --vrtsim.role server --vrtsim.taps-socket ipc:///tmp/ru_socket_0
|
||||
```
|
||||
|
||||
```
|
||||
source .venv/bin/activate
|
||||
python main.py example_config.yaml
|
||||
```
|
||||
|
||||
```
|
||||
sudo ./nr-uesoftmodem -C 3619200000 -r 106 --numerology 1 --ssb 516 --device.name vrtsim
|
||||
```
|
||||
|
||||
```
|
||||
./move_ue.sh
|
||||
```
|
||||
@@ -219,7 +219,7 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
int SNRtimes10 = dB_fixed_x10(signal_pwr) - dB_fixed_x10(ue->measurements.n0_power_avg);
|
||||
ue->measurements.ssb_sinr_dB[ssb_index] = SNRtimes10 / 10.0;
|
||||
|
||||
LOG_D(PHY,
|
||||
LOG_I(PHY,
|
||||
"[UE %d] ssb %d SS-RSRP: %d dBm/RE (%f dB/RE), SS-SINR: %f dB\n",
|
||||
ue->Mod_id,
|
||||
ssb_index,
|
||||
|
||||
@@ -8,6 +8,7 @@ target_link_libraries(vrtsim PRIVATE SIMU shm_td_iq_channel actor noise_device l
|
||||
add_boolean_option(OAI_VRTSIM_TAPS_CLIENT OFF "Enable taps client" ON)
|
||||
if (OAI_VRTSIM_TAPS_CLIENT)
|
||||
target_link_libraries(vrtsim PRIVATE taps_client)
|
||||
target_compile_definitions(vrtsim PRIVATE ENABLE_TAPS_CLIENT=ON)
|
||||
file(DOWNLOAD
|
||||
"https://gitlab.eurecom.fr/oai/raytracing-channel-emulator/-/raw/59589ad2a534881810b2aa7dd81e63066245bb8d/server/api/taps.fbs?inline=false"
|
||||
${CMAKE_SOURCE_DIR}/taps.fbs
|
||||
@@ -26,6 +27,14 @@ if (OAI_VRTSIM_TAPS_CLIENT)
|
||||
|
||||
add_library(taps_client taps_client.cpp ${TAPS_API_HEADER})
|
||||
target_include_directories(taps_client PUBLIC .)
|
||||
find_package(Flatbuffers REQUIRED)
|
||||
#find_package(Flatbuffers REQUIRED)
|
||||
find_package(FlatBuffers QUIET)
|
||||
if(NOT FlatBuffers_FOUND)
|
||||
# Fall back to lowercase (Ubuntu 22.04)
|
||||
find_package(Flatbuffers REQUIRED)
|
||||
set(FLATBUFFERS_TARGET flatbuffers)
|
||||
else()
|
||||
set(FLATBUFFERS_TARGET flatbuffers::flatbuffers)
|
||||
endif()
|
||||
target_link_libraries(taps_client PUBLIC flatbuffers taps_api SIMU nanomsg)
|
||||
endif()
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "PHY/TOOLS/tools_defs.h"
|
||||
#include "notified_fifo.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -54,7 +55,10 @@
|
||||
typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role;
|
||||
|
||||
#define MAX_NUM_ANTENNAS_TX 4
|
||||
#define MAX_CHANNEL_LENGTH (1 << 20)
|
||||
#define MAX_CHANNEL_LENGTH 200
|
||||
#define SAVED_SAMPLES_LEN (MAX_CHANNEL_LENGTH - 1)
|
||||
#define BATCH_SIZE 4096
|
||||
#define FIRST_BATCH_SIZE (BATCH_SIZE / 2)
|
||||
|
||||
#define ROLE_CLIENT_STRING "client"
|
||||
#define ROLE_SERVER_STRING "server"
|
||||
@@ -112,6 +116,7 @@ typedef struct {
|
||||
uint64_t rx_samples_late;
|
||||
uint64_t rx_early;
|
||||
uint64_t rx_samples_total;
|
||||
int num_tx_timing;
|
||||
tx_timing_t *tx_timing;
|
||||
peer_info_t peer_info;
|
||||
int chanmod;
|
||||
@@ -120,14 +125,12 @@ typedef struct {
|
||||
int tx_num_channels;
|
||||
int rx_num_channels;
|
||||
channel_desc_t *channel_desc;
|
||||
int num_chanmod_actors;
|
||||
Actor_t *channel_modelling_actors;
|
||||
char *taps_socket;
|
||||
int client_num_rx_antennas;
|
||||
} vrtsim_state_t;
|
||||
|
||||
// Sample history for channel impulse response
|
||||
static c16_t saved_samples[MAX_NUM_ANTENNAS_TX][MAX_CHANNEL_LENGTH] __attribute__((aligned(32))) = {0};
|
||||
|
||||
static void histogram_add(histogram_t *histogram, double diff)
|
||||
{
|
||||
histogram->num_samples++;
|
||||
@@ -312,10 +315,11 @@ static int vrtsim_connect(openair0_device *device)
|
||||
}
|
||||
|
||||
// Handle channel modelling after number of RX antennas are known
|
||||
int num_tx_stats = 1;
|
||||
vrtsim_state->num_tx_timing = 1;
|
||||
if (vrtsim_state->chanmod || vrtsim_state->taps_socket) {
|
||||
vrtsim_state->channel_modelling_actors = calloc_or_fail(vrtsim_state->peer_info.num_rx_antennas, sizeof(Actor_t));
|
||||
for (int i = 0; i < vrtsim_state->peer_info.num_rx_antennas; i++) {
|
||||
vrtsim_state->num_chanmod_actors = vrtsim_state->peer_info.num_rx_antennas * vrtsim_state->tx_num_channels;
|
||||
vrtsim_state->channel_modelling_actors = calloc_or_fail(vrtsim_state->num_chanmod_actors, sizeof(Actor_t));
|
||||
for (int i = 0; i < vrtsim_state->num_chanmod_actors; i++) {
|
||||
init_actor(&vrtsim_state->channel_modelling_actors[i], "chanmod", -1);
|
||||
}
|
||||
if (vrtsim_state->taps_socket) {
|
||||
@@ -327,10 +331,10 @@ static int vrtsim_connect(openair0_device *device)
|
||||
} else {
|
||||
load_channel_model(vrtsim_state);
|
||||
}
|
||||
num_tx_stats = vrtsim_state->peer_info.num_rx_antennas;
|
||||
vrtsim_state->num_tx_timing = vrtsim_state->num_chanmod_actors;
|
||||
}
|
||||
vrtsim_state->tx_timing = calloc_or_fail(num_tx_stats, sizeof(tx_timing_t));
|
||||
for (int i = 0; i < num_tx_stats; i++) {
|
||||
vrtsim_state->tx_timing = calloc_or_fail(vrtsim_state->num_tx_timing, sizeof(tx_timing_t));
|
||||
for (int i = 0; i < vrtsim_state->num_tx_timing; i++) {
|
||||
vrtsim_state->tx_timing[i].tx_histogram.min_samples = 100;
|
||||
// Set the histogram range to 3000uS. Anything above that is not interesting
|
||||
vrtsim_state->tx_timing[i].tx_histogram.range = 3000.0;
|
||||
@@ -371,25 +375,24 @@ typedef struct {
|
||||
vrtsim_state_t *vrtsim_state;
|
||||
openair0_timestamp timestamp;
|
||||
c16_t *samples[MAX_NUM_ANTENNAS_TX];
|
||||
c16_t *first_samples[MAX_NUM_ANTENNAS_TX];
|
||||
int nsamps;
|
||||
int nbAnt;
|
||||
int flags;
|
||||
int aarx;
|
||||
int task_index;
|
||||
int num_tasks;
|
||||
int tx_timing_index;
|
||||
c16_t samples_copy[1];
|
||||
} channel_modelling_args_t;
|
||||
|
||||
static void perform_channel_modelling(void *arg)
|
||||
{
|
||||
channel_modelling_args_t *channel_modelling_args = arg;
|
||||
vrtsim_state_t *vrtsim_state = channel_modelling_args->vrtsim_state;
|
||||
int nsamps = channel_modelling_args->nsamps;
|
||||
int aarx = channel_modelling_args->aarx;
|
||||
int nb_tx_ant = channel_modelling_args->nbAnt;
|
||||
c16_t **input_samples = (c16_t **)channel_modelling_args->samples;
|
||||
|
||||
int aligned_nsamps = ceil_mod(nsamps, (512 / 8) / sizeof(cf_t));
|
||||
cf_t samples[aligned_nsamps] __attribute__((aligned(64)));
|
||||
// Apply noise from global settings
|
||||
get_noise_vector((float *)samples, nsamps * 2);
|
||||
channel_modelling_args_t *args = arg;
|
||||
vrtsim_state_t *vrtsim_state = args->vrtsim_state;
|
||||
int nsamps = args->nsamps;
|
||||
int aarx = args->aarx;
|
||||
int nb_tx_ant = args->nbAnt;
|
||||
|
||||
channel_desc_t *channel_desc = vrtsim_state->channel_desc;
|
||||
|
||||
@@ -417,90 +420,149 @@ static void perform_channel_modelling(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
for (int aatx = 0; aatx < nb_tx_ant; aatx++) {
|
||||
c16_t *previous_samples = saved_samples[aatx];
|
||||
for (int i = 0; i < nsamps; i++) {
|
||||
cf_t *impulse_response = channel_impulse_response_p[aatx];
|
||||
for (int l = 0; l < channel_desc->channel_length; l++) {
|
||||
int idx = i - l;
|
||||
// TODO: Use AVX2 for this
|
||||
c16_t tx_input = idx >= 0 ? input_samples[aatx][idx]
|
||||
: previous_samples[(channel_modelling_args->timestamp + i + idx) % MAX_CHANNEL_LENGTH];
|
||||
samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i;
|
||||
samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i;
|
||||
// Calculate number of batches to process per thread.
|
||||
int num_batches_to_process = 0;
|
||||
if (nsamps > args->task_index * FIRST_BATCH_SIZE) {
|
||||
num_batches_to_process = 1;
|
||||
int nsamps_after_first_batch = max(0, nsamps - args->num_tasks * FIRST_BATCH_SIZE);
|
||||
int num_full_size_batches = nsamps_after_first_batch / (args->num_tasks * BATCH_SIZE);
|
||||
|
||||
int nsamps_left = nsamps_after_first_batch - (num_full_size_batches * BATCH_SIZE);
|
||||
if (nsamps_left > args->task_index * BATCH_SIZE)
|
||||
num_batches_to_process++;
|
||||
num_batches_to_process += num_full_size_batches;
|
||||
}
|
||||
|
||||
for (int batch_index = 0; batch_index < num_batches_to_process; batch_index++) {
|
||||
int batch_start_offset;
|
||||
int batch_size;
|
||||
if (batch_index == 0) {
|
||||
batch_start_offset = args->task_index * FIRST_BATCH_SIZE;
|
||||
batch_size = FIRST_BATCH_SIZE;
|
||||
} else {
|
||||
batch_start_offset = args->num_tasks * (FIRST_BATCH_SIZE + (batch_index - 1) * BATCH_SIZE) + args->task_index * BATCH_SIZE;
|
||||
batch_size = BATCH_SIZE;
|
||||
}
|
||||
int batch_nsamps = min(batch_size, nsamps - (batch_start_offset - args->timestamp));
|
||||
int aligned_nsamps = ceil_mod(batch_nsamps, (512 / 8) / sizeof(cf_t));
|
||||
cf_t samples[aligned_nsamps] __attribute__((aligned(64)));
|
||||
get_noise_vector((float *)samples, batch_nsamps * 2);
|
||||
|
||||
c16_t **input_samples = batch_start_offset == 0 ? args->first_samples : (c16_t **)args->samples;
|
||||
for (int aatx = 0; aatx < nb_tx_ant; aatx++) {
|
||||
for (int i = 0; i < batch_nsamps; i++) {
|
||||
cf_t *impulse_response = channel_impulse_response_p[aatx];
|
||||
cf_t sample = {0, 0};
|
||||
for (int l = 0; l < channel_desc->channel_length; l++) {
|
||||
int idx = i - l;
|
||||
// TODO: Use AVX2 for this
|
||||
c16_t tx_input = input_samples[aatx][batch_start_offset + idx];
|
||||
sample.r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i;
|
||||
sample.i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i;
|
||||
}
|
||||
samples[i].r += sample.r;
|
||||
samples[i].i += sample.i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to c16_t
|
||||
c16_t samples_out[aligned_nsamps] __attribute__((aligned(64)));
|
||||
// Convert to c16_t
|
||||
c16_t samples_out[aligned_nsamps] __attribute__((aligned(64)));
|
||||
#if defined(__AVX512F__)
|
||||
for (int i = 0; i < aligned_nsamps / 8; i++) {
|
||||
simde__m512 *in = (simde__m512 *)&samples[i * 8];
|
||||
simde__m256i *out = (simde__m256i *)&samples_out[i * 8];
|
||||
*out = simde_mm512_cvtsepi32_epi16(simde_mm512_cvtps_epi32(*in));
|
||||
}
|
||||
for (int i = 0; i < aligned_nsamps / 8; i++) {
|
||||
simde__m512 *in = (simde__m512 *)&samples[i * 8];
|
||||
simde__m256i *out = (simde__m256i *)&samples_out[i * 8];
|
||||
*out = simde_mm512_cvtsepi32_epi16(simde_mm512_cvtps_epi32(*in));
|
||||
}
|
||||
#elif defined(__AVX2__)
|
||||
for (int i = 0; i < aligned_nsamps / 4; i++) {
|
||||
simde__m256 *in = (simde__m256 *)&samples[i * 4];
|
||||
simde__m128i *out = (simde__m128i *)&samples_out[i * 4];
|
||||
*out = simde_mm256_cvtsepi32_epi16(simde_mm256_cvtps_epi32(*in));
|
||||
}
|
||||
for (int i = 0; i < aligned_nsamps / 4; i++) {
|
||||
simde__m256 *in = (simde__m256 *)&samples[i * 4];
|
||||
simde__m128i *out = (simde__m128i *)&samples_out[i * 4];
|
||||
*out = simde_mm256_cvtsepi32_epi16(simde_mm256_cvtps_epi32(*in));
|
||||
}
|
||||
#else
|
||||
for (int i = 0; i < nsamps; i++) {
|
||||
samples_out[i].r = lroundf(samples[i].r);
|
||||
samples_out[i].i = lroundf(samples[i].i);
|
||||
}
|
||||
for (int i = 0; i < nsamps; i++) {
|
||||
samples_out[i].r = lroundf(samples[i].r);
|
||||
samples_out[i].i = lroundf(samples[i].i);
|
||||
}
|
||||
#endif
|
||||
|
||||
vrtsim_write_internal(channel_modelling_args->vrtsim_state,
|
||||
channel_modelling_args->timestamp,
|
||||
samples_out,
|
||||
channel_modelling_args->nsamps,
|
||||
aarx,
|
||||
channel_modelling_args->flags,
|
||||
aarx);
|
||||
vrtsim_write_internal(args->vrtsim_state,
|
||||
args->timestamp + batch_start_offset,
|
||||
samples_out,
|
||||
batch_nsamps,
|
||||
aarx,
|
||||
args->flags,
|
||||
args->tx_timing_index);
|
||||
}
|
||||
}
|
||||
|
||||
static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state,
|
||||
openair0_timestamp timestamp,
|
||||
void **samplesVoid,
|
||||
c16_t **samplesVoid,
|
||||
int nsamps,
|
||||
int nbAnt,
|
||||
int flags)
|
||||
{
|
||||
AssertFatal(nbAnt < MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX);
|
||||
AssertFatal(nbAnt <= MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX);
|
||||
|
||||
static int actor = 0;
|
||||
// Sample history for channel impulse response
|
||||
static c16_t saved_samples[MAX_NUM_ANTENNAS_TX][SAVED_SAMPLES_LEN] __attribute__((aligned(32))) = {0};
|
||||
static openair0_timestamp last_timestamp = 0;
|
||||
|
||||
for (int aarx = 0; aarx < vrtsim_state->peer_info.num_rx_antennas; aarx++) {
|
||||
notifiedFIFO_elt_t *task = newNotifiedFIFO_elt(sizeof(channel_modelling_args_t), 0, NULL, perform_channel_modelling);
|
||||
channel_modelling_args_t *args = (channel_modelling_args_t *)NotifiedFifoData(task);
|
||||
args->vrtsim_state = vrtsim_state;
|
||||
args->timestamp = timestamp;
|
||||
args->nsamps = nsamps;
|
||||
args->nbAnt = nbAnt;
|
||||
args->flags = flags;
|
||||
args->aarx = aarx;
|
||||
for (int i = 0; i < nbAnt; i++) {
|
||||
args->samples[i] = samplesVoid[i];
|
||||
for (int task_index = 0; task_index < vrtsim_state->tx_num_channels; task_index++) {
|
||||
// Allocate extra space at the end of the message to copy historical samples
|
||||
size_t extra_size = sizeof(c16_t) * (BATCH_SIZE + SAVED_SAMPLES_LEN) * nbAnt;
|
||||
notifiedFIFO_elt_t *task = newNotifiedFIFO_elt(sizeof(channel_modelling_args_t) + extra_size, 0, NULL, perform_channel_modelling);
|
||||
channel_modelling_args_t *args = NotifiedFifoData(task);
|
||||
if (task_index == 0) {
|
||||
for (int aatx = 0; aatx < nbAnt; aatx++) {
|
||||
c16_t *buffer = (c16_t *)(args + 1) + aatx * (FIRST_BATCH_SIZE + SAVED_SAMPLES_LEN);
|
||||
size_t gap_samples = timestamp - last_timestamp;
|
||||
if (gap_samples > 0) {
|
||||
size_t gap_samples_needed = min(SAVED_SAMPLES_LEN, gap_samples);
|
||||
memset(&buffer[SAVED_SAMPLES_LEN - gap_samples_needed], 0, sizeof(c16_t) * gap_samples_needed);
|
||||
if (gap_samples < SAVED_SAMPLES_LEN) {
|
||||
size_t samples_from_saved = SAVED_SAMPLES_LEN - gap_samples_needed;
|
||||
memcpy(&buffer[0], &saved_samples[aatx][SAVED_SAMPLES_LEN - samples_from_saved], sizeof(c16_t) * samples_from_saved);
|
||||
}
|
||||
} else {
|
||||
memcpy(buffer, saved_samples[aatx], sizeof(c16_t) * SAVED_SAMPLES_LEN);
|
||||
}
|
||||
memcpy(&buffer[SAVED_SAMPLES_LEN], &samplesVoid[aatx][0], sizeof(c16_t) * FIRST_BATCH_SIZE);
|
||||
args->first_samples[aatx] = buffer + SAVED_SAMPLES_LEN;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nbAnt; i++) {
|
||||
args->samples[i] = samplesVoid[i];
|
||||
}
|
||||
args->vrtsim_state = vrtsim_state;
|
||||
args->timestamp = timestamp;
|
||||
args->nsamps = nsamps;
|
||||
args->nbAnt = nbAnt;
|
||||
args->flags = flags;
|
||||
args->aarx = aarx;
|
||||
args->task_index = task_index;
|
||||
args->num_tasks = vrtsim_state->tx_num_channels;
|
||||
actor = (actor + 1) % vrtsim_state->num_chanmod_actors;
|
||||
args->tx_timing_index = actor;
|
||||
pushNotifiedFIFO(&vrtsim_state->channel_modelling_actors[actor].fifo, task);
|
||||
}
|
||||
pushNotifiedFIFO(&vrtsim_state->channel_modelling_actors[aarx].fifo, task);
|
||||
}
|
||||
int start_index = timestamp % MAX_CHANNEL_LENGTH;
|
||||
int end_index = min(start_index + nsamps, MAX_CHANNEL_LENGTH);
|
||||
int cp_nsamps = end_index - start_index;
|
||||
for (int aatx = 0; aatx < nbAnt; aatx++) {
|
||||
c16_t *samples = (c16_t *)samplesVoid[aatx];
|
||||
memcpy(&saved_samples[aatx][start_index], &samples[0], sizeof(c16_t) * cp_nsamps);
|
||||
}
|
||||
|
||||
if (end_index < start_index + nsamps) {
|
||||
// wrap around condition, write at beginning of buffer
|
||||
cp_nsamps = nsamps - cp_nsamps; // remaining samples
|
||||
start_index = 0;
|
||||
// Save samples for next round
|
||||
if (nsamps < MAX_CHANNEL_LENGTH) {
|
||||
for (int aatx = 0; aatx < nbAnt; aatx++) {
|
||||
c16_t *samples = (c16_t *)samplesVoid[aatx];
|
||||
memcpy(&saved_samples[aatx][start_index], &samples[0], sizeof(c16_t) * cp_nsamps);
|
||||
memmove(&saved_samples[aatx][0], &saved_samples[aatx][nsamps], sizeof(c16_t) * (SAVED_SAMPLES_LEN - nsamps));
|
||||
memcpy(&saved_samples[aatx][SAVED_SAMPLES_LEN - nsamps], &samplesVoid[aatx][0], sizeof(c16_t) * nsamps);
|
||||
}
|
||||
} else {
|
||||
for (int aatx = 0; aatx < nbAnt; aatx++) {
|
||||
memcpy(saved_samples[aatx], &samplesVoid[aatx][nsamps - SAVED_SAMPLES_LEN], sizeof(c16_t) * (SAVED_SAMPLES_LEN));
|
||||
}
|
||||
}
|
||||
last_timestamp = timestamp + nsamps;
|
||||
return nsamps;
|
||||
}
|
||||
|
||||
@@ -515,7 +577,7 @@ static int vrtsim_write(openair0_device *device, openair0_timestamp timestamp, v
|
||||
timestamp -= device->openair0_cfg->command_line_sample_advance;
|
||||
vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
|
||||
bool channel_modelling = vrtsim_state->chanmod || vrtsim_state->taps_socket;
|
||||
return channel_modelling ? vrtsim_write_with_chanmod(vrtsim_state, timestamp, samplesVoid, nsamps, nbAnt, flags)
|
||||
return channel_modelling ? vrtsim_write_with_chanmod(vrtsim_state, timestamp, (c16_t **)samplesVoid, nsamps, nbAnt, flags)
|
||||
: vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, 0, flags, 0);
|
||||
}
|
||||
|
||||
@@ -569,18 +631,18 @@ static void vrtsim_end(openair0_device *device)
|
||||
|
||||
tx_timing_t *tx_timing = vrtsim_state->tx_timing;
|
||||
if (vrtsim_state->chanmod || vrtsim_state->taps_socket) {
|
||||
for (int i = 0; i < vrtsim_state->peer_info.num_rx_antennas; i++) {
|
||||
for (int i = 0; i < vrtsim_state->num_chanmod_actors; i++) {
|
||||
shutdown_actor(&vrtsim_state->channel_modelling_actors[i]);
|
||||
}
|
||||
free(vrtsim_state->channel_modelling_actors);
|
||||
for (int i = 1; i < vrtsim_state->peer_info.num_rx_antennas; i++) {
|
||||
for (int i = 1; i < vrtsim_state->num_tx_timing; i++) {
|
||||
histogram_merge(&tx_timing->tx_histogram, &tx_timing[i].tx_histogram);
|
||||
tx_timing->tx_early += tx_timing[i].tx_early;
|
||||
tx_timing->tx_samples_late += tx_timing[i].tx_samples_late;
|
||||
tx_timing->average_tx_budget += tx_timing[i].average_tx_budget;
|
||||
tx_timing->tx_samples_total += tx_timing[i].tx_samples_total;
|
||||
}
|
||||
tx_timing->average_tx_budget /= vrtsim_state->peer_info.num_rx_antennas;
|
||||
tx_timing->average_tx_budget /= vrtsim_state->num_tx_timing;
|
||||
free_noise_device();
|
||||
if (vrtsim_state->taps_socket) {
|
||||
taps_client_stop();
|
||||
|
||||
@@ -248,3 +248,21 @@ e2_agent = {
|
||||
#sm_dir = "/path/where/the/SMs/are/located/"
|
||||
sm_dir = "/usr/local/lib/flexric/"
|
||||
};
|
||||
|
||||
|
||||
channelmod = {
|
||||
max_chan=10;
|
||||
modellist="modellist_rfsimu_1";
|
||||
modellist_rfsimu_1 = (
|
||||
{
|
||||
model_name = "server_tx_channel_model"
|
||||
type = "AWGN";
|
||||
ploss_dB = 0;
|
||||
noise_power_dB = 0;
|
||||
forgetfact = 0;
|
||||
offset = 0;
|
||||
ds_tdl = 0;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user