Commit c1f9764d authored by root's avatar root

UE add RF drivers

parent 9a04aea8
# Creates shared library
CC= gcc
CFLAGS+= -DADRV9371_ZC706 -DHWLAT -O0 -g3 -Wall -fmessage-length=0 -fPIC
DROOT= ./USERSPACE
DIR= $(DROOT)/LIB
IFLAGS+= -I$(DIR)/ \
-I$(DROOT)/libini/ \
-I../COMMON/ \
-I/usr/include/
LDFLAGS+= -L/usr/lib/x86/64-linux-gnu/ \
-lm -liio -ldl -lriffa
OUTDIR= ./slib
TARGET= libadrv9371_zc706.so
SRC= $(DIR)/adrv9371_dump.c \
$(DIR)/adrv9371_helper.c \
$(DIR)/adrv9371_self_test.c \
$(DIR)/adrv9371_zc706_lib.c \
$(DIR)/adrv9371_zc706_riffa_lib.c \
$(DIR)/adrv9371_zc706_stats.c \
$(DIR)/hw_init.c \
$(DROOT)/libini/libini.c
OBJ= $(OUTDIR)/adrv9371_dump.o \
$(OUTDIR)/adrv9371_helper.o \
$(OUTDIR)/adrv9371_self_test.o \
$(OUTDIR)/adrv9371_zc706_lib.o \
$(OUTDIR)/adrv9371_zc706_riffa_lib.o \
$(OUTDIR)/adrv9371_zc706_stats.o \
$(OUTDIR)/hw_init.o \
$(OUTDIR)/libini.o
all: lib
dir:
mkdir -p $(OUTDIR)
env:
set PATH=/usr/lib/:${PATH}
obj: dir env
$(CC) -c $(CFLAGS) $(IFLAGS) $(SRC)
mv *.o $(OUTDIR)
lib: dir obj
$(CC) -shared $(OBJ) -o $(OUTDIR)/$(TARGET) $(LDFLAGS)
# exec: env
# $(CC) $(CFLAGS) $(IFLAGS) main.c $(SRC) -o lib.exe $(LDFLAGS) -lpthread
.PHONY: clean
clean:
rm -f $(OUTDIR)/*.o $(OUTDIR)/*~
rm: clean
rm -f $(OUTDIR)/$(TARGET)
rmdir $(OUTDIR)
\ No newline at end of file
[IIO Oscilloscope]
plugin.DMM.detached=0
plugin.Debug.detached=0
plugin.AD9371 Advanced.detached=0
plugin.AD9371.detached=0
startup_version_check=0
test=1
[IIO Oscilloscope - Capture Window1]
fru_connect = 1
test.message = Please ensure:\n • 30.72 MHz -> REF_CLK_IN (0dBm)\n • Rx1 <-> Tx1\n • Rx2 <-> Tx2
domain=fft
sample_count=400
fft_size=16384
fft_avg=8
fft_pwr_offset=0.000000
graph_type=Lines
show_grid=1
enable_auto_scale=1
x_axis_min=-67.583626
x_axis_max=67.576126
y_axis_min=-130
y_axis_max=3
show_capture_options = 1
axi-ad9371-rx-obs-hpc.expanded=1
axi-ad9371-rx-obs-hpc.active=0
axi-ad9371-rx-obs-hpc.trigger_enabled=0
axi-ad9371-rx-obs-hpc.voltage0_i.enabled=0
axi-ad9371-rx-obs-hpc.voltage0_q.enabled=0
axi-ad9371-rx-hpc.expanded=1
axi-ad9371-rx-hpc.active=1
axi-ad9371-rx-hpc.voltage0_i.enabled=1
axi-ad9371-rx-hpc.voltage0_q.enabled=1
axi-ad9371-rx-hpc.voltage1_i.enabled=0
axi-ad9371-rx-hpc.voltage1_q.enabled=0
marker_type = Single Tone Markers
marker.0 = 9525
marker.1 = 8192
marker.2 = 10859
marker.3 = 12193
marker.4 = 13526
marker.5 = 14859
capture_started=0
[DMM]
device_list = ad7291 0
device_list = ad9371-phy 0
device_list = xadc 0
running = No
# temp between 20C and 55C (in 0.25C units)
test.ad7291.in_temp0_raw.int = 80 220
# See the production testing wiki docs [1] for how these values are calculated.
# [1]: (https://wiki.analog.com/resources/eval/user-guides/ad-fmcomms2-ebz/testing#voltage)
# scale = 0.610351562
# All nominal voltages +/- 2.5%
# 0 INPUT_VOLTAGE 12V - V(Drop Diode) 56/10
test.ad7291.in_voltage0_raw.int = 2710 2850
# 1 VOUT2_1V3_DIG 1
test.ad7291.in_voltage1_raw.int = 2077 2183
# 2 VDD_IF 10/10
test.ad7291.in_voltage2_raw.int = 1997 2099
# 3 VOUT3_3V3 10/10
test.ad7291.in_voltage3_raw.int = 2636 2770
# 5 VOUT4_1V8 1
test.ad7291.in_voltage5_raw.int = 2875 3023
# 7 VOUT1_1V3_ANLG 1
test.ad7291.in_voltage7_raw.int = 2077 2183
# Test AD9528 lock status - Requires 30.720 MHz reference clock!
test.ad9528-1.pll1_reference_clk_a_present.int = 1 1
test.ad9528-1.pll1_locked.int = 1 1
test.ad9528-1.pll2_locked.int = 1 1
[AD9371]
ad9371-phy.in_voltage2_rf_port_select = INTERNALCALS
ad9371-phy.in_voltage2_temp_comp_gain = 0.00 dB
ad9371-phy.out_altvoltage1_TX_LO_frequency = 2500000000
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = 2600000000
ad9371-phy.out_voltage1_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage1_lo_leakage_tracking_en = 1
ad9371-phy.out_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage0_gain_control_mode = automatic
ad9371-phy.in_voltage0_quadrature_tracking_en = 1
ad9371-phy.in_voltage0_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage1_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage1_gain_control_mode = automatic
ad9371-phy.out_altvoltage0_RX_LO_frequency = 2600000000
ad9371-phy.out_voltage0_lo_leakage_tracking_en = 1
ad9371-phy.out_voltage0_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage0_quadrature_tracking_en = 1
ad9371-phy.ensm_mode = radio_on
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_frequency = 10001402
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_frequency = 1001265
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_frequency = 10001402
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_frequency = 10001402
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_frequency = 40001860
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_frequency = 1001265
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_frequency = 10001402
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_frequency = 40001860
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_scale = 0.000000
dds_mode_tx1 = 0
dds_mode_tx2 = 0
SYNC_RELOAD = 1
# test receiver at 1GHz to 5 GHz
# SEQ FIRST INCREMENT LAST
<SEQ> i 1000000000 5000000000 5000000000
[IIO Oscilloscope - Capture Window1]
# wait for device to settle
marker_type = Peak Markers
capture_started = 0
cycle = 1000
axi-ad9371-rx-hpc.voltage0_i.enabled=1
axi-ad9371-rx-hpc.voltage0_q.enabled=1
axi-ad9371-rx-hpc.voltage1_i.enabled=0
axi-ad9371-rx-hpc.voltage1_q.enabled=0
cycle = 1000
[AD9371]
ad9371-phy.out_altvoltage1_TX_LO_frequency = <i>
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = {{<i>} + {100000000}}
ad9371-phy.out_altvoltage0_RX_LO_frequency = {{<i>} + {100000000}}
dds_mode_tx1 = 0
dds_mode_tx2 = 0
SYNC_RELOAD = 1
[IIO Oscilloscope - Capture Window1]
# wait for device to settle
capture_started = 1
cycle = 3000
[AD9371]
# channels should be off, so RSSI should be low
test.ad9371-phy.in_voltage0_rssi.int = 44 45
test.ad9371-phy.in_voltage1_rssi.int = 44 45
# and gain is high
test.ad9371-phy.in_voltage0_hardwaregain.double = 30.0 31.0
test.ad9371-phy.in_voltage0_hardwaregain.double = 30.0 31.0
# set Tx and Rx to be the same
ad9371-phy.out_altvoltage0_RX_LO_frequency = <i>
dds_mode_tx1 = 1
dds_mode_tx2 = 1
SYNC_RELOAD = 1
[IIO Oscilloscope - Capture Window1]
# wait for device to settle
marker_type = Single Tone Markers
cycle = 3000
[AD9371]
ad9371-phy.out_voltage0_hardwaregain = 0.000000 dB
ad9371-phy.out_voltage1_hardwaregain = 0.000000 dB
# channels should be on, so RSSI should be high
test.ad9371-phy.in_voltage0_rssi.int = 3 12
test.ad9371-phy.in_voltage1_rssi.int = 3 12
# and gain is low
test.ad9371-phy.in_voltage0_hardwaregain.double = 15.0 29.0
test.ad9371-phy.in_voltage0_hardwaregain.double = 15.0 29.0
[IIO Oscilloscope - Capture Window1]
cycle = 1000
capture_started = 1
cycle = 3000
save_png = ADRV9371_rx1_<i>.png
save_markers = markers.log
#look at the markers - Fundamental
test.marker.0 = -12.0 -4.0
# DC
test.marker.1 = -100.0 -60.0
# 2st Harmonic
test.marker.2 = -110.0 -75.0
# 3nd Harmonic
test.marker.3 = -110.0 -75.0
# 4th Harmonic
test.marker.4 = -110.0 -75.0
# 4th Harmonic
test.marker.5 = -110.0 -65.0
capture_started = 0
cycle = 1000
axi-ad9371-rx-hpc.voltage0_i.enabled=0
axi-ad9371-rx-hpc.voltage0_q.enabled=0
axi-ad9371-rx-hpc.voltage1_i.enabled=1
axi-ad9371-rx-hpc.voltage1_q.enabled=1
cycle = 1000
capture_started = 1
cycle = 3000
save_png = ADRV9371_rx2_<i>.png
save_markers = markers.log
#look at the markers - Fundamental
test.marker.0 = -12.0 -4.0
# DC
test.marker.1 = -100.0 -60.0
# 2st Harmonic
test.marker.2 = -110.0 -75.0
# 3nd Harmonic
test.marker.3 = -110.0 -75.0
# 4th Harmonic
test.marker.4 = -110.0 -75.0
# 4th Harmonic
test.marker.5 = -110.0 -65.0
</SEQ>
[IIO Oscilloscope - Capture Window1]
capture_started = 0
test.message = Please ensure:\n • ORX1 <-> Tx1\n • ORX22 <-> Tx2
axi-ad9371-rx-hpc.expanded=1
axi-ad9371-rx-hpc.active=0
axi-ad9371-rx-hpc.voltage0_i.enabled=0
axi-ad9371-rx-hpc.voltage0_q.enabled=0
axi-ad9371-rx-hpc.voltage1_i.enabled=0
axi-ad9371-rx-hpc.voltage1_q.enabled=0
axi-ad9371-rx-obs-hpc.expanded=1
axi-ad9371-rx-obs-hpc.active=1
axi-ad9371-rx-obs-hpc.voltage0_i.enabled=1
axi-ad9371-rx-obs-hpc.voltage0_q.enabled=1
cycle = 1000
# test observer path at 1GHz to 5 GHz
# SEQ FIRST INCREMENT LAST
<SEQ> i 1000000000 1000000000 5000000000
[AD9371]
# set Tx and Rx to be the same
ad9371-phy.out_altvoltage1_TX_LO_frequency = <i>
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = {{<i>} + {1000000}}
ad9371-phy.out_altvoltage0_RX_LO_frequency = <i>
dds_mode_tx1 = 1
dds_mode_tx2 = 1
ad9371-phy.out_voltage0_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage1_hardwaregain = -10.000000 dB
ad9371-phy.in_voltage2_rf_port_select = ORX1_TX_LO
ad9371-phy.in_voltage2_gain_control_mode = manual
ad9371-phy.in_voltage2_hardwaregain = 18.000000 dB
[IIO Oscilloscope - Capture Window1]
capture_started = 1
cycle = 3000
save_png = ADRV9371_ob1_<i>.png
save_markers = markers.log
#look at the markers - Fundamental
test.marker.0 = -15.0 -5.0
# DC
test.marker.1 = -100.0 -75.0
# 2st Harmonic
test.marker.2 = -110.0 -75.0
# 3nd Harmonic
test.marker.3 = -110.0 -75.0
# 4th Harmonic
test.marker.4 = -110.0 -75.0
# 4th Harmonic
test.marker.5 = -110.0 -65.0
[AD9371]
ad9371-phy.in_voltage2_rf_port_select = ORX2_TX_LO
[IIO Oscilloscope - Capture Window1]
cycle = 1000
capture_started = 1
cycle = 3000
save_png = ADRV9371_ob2_<i>.png
save_markers = markers.log
#look at the markers - Fundamental
test.marker.0 = -15.0 -4.0
# DC
test.marker.1 = -100.0 -75.0
# 2st Harmonic
test.marker.2 = -110.0 -75.0
# 3nd Harmonic
test.marker.3 = -110.0 -75.0
# 4th Harmonic
test.marker.4 = -110.0 -75.0
# 4th Harmonic
test.marker.5 = -110.0 -65.0
</SEQ>
[IIO Oscilloscope - Capture Window1]
test.message = All tests passed - Ship it
quit = 1
[AD9371]
ad9371-phy.in_voltage2_rf_port_select = OFF
ad9371-phy.in_voltage2_hardwaregain = -156.000000 dB
ad9371-phy.in_voltage2_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_voltage0_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage0_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage0_quadrature_tracking_en = 1
ad9371-phy.out_voltage1_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage1_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage1_TX_LO_frequency = 2685000000
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = 2565000000
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage0_gain_control_mode = automatic
ad9371-phy.in_voltage0_quadrature_tracking_en = 1
ad9371-phy.in_voltage0_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage0_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage1_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage1_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage1_gain_control_mode = automatic
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage0_RX_LO_frequency = 2565000000
ad9371-phy.calibrate_rx_qec_en = 0
ad9371-phy.calibrate_tx_lol_en = 0
ad9371-phy.calibrate_vswr_en = 0
ad9371-phy.calibrate_tx_qec_en = 0
ad9371-phy.calibrate_clgc_en = 0
ad9371-phy.ensm_mode = radio_on
ad9371-phy.calibrate_tx_lol_ext_en = 0
ad9371-phy.calibrate_dpd_en = 0
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_scale = 0.000000
load_myk_profile_file = /targets/ARCH/ADRV9371_ZC706/USERSPACE/PROFILES/profile_rx30_Tx60_syr.txt
dds_mode_tx1 = 1
dds_mode_tx2 = 1
dac_buf_filename = /usr/local/lib/osc/waveforms/LTE20.mat
tx_channel_0 = 1
tx_channel_1 = 1
tx_channel_2 = 0
tx_channel_3 = 0
global_settings_show = 1
tx_show = 1
rx_show = 1
obs_show = 1
fpga_show = 1
[ADRV9371_ZC706]
debug_mode = 0
interpolation_decimation_factor = 2
<profile AD9371 version=0 name=Rx 20, IQrate 30.720>
<clocks>
<deviceClock_kHz=122880>
<clkPllVcoFreq_kHz=9830400>
<clkPllVcoDiv=2>
<clkPllHsDiv=4>
</clocks>
<rx>
<adcDiv=1>
<rxFirDecimation=4>
<rxDec5Decimation=5>
<enHighRejDec5=1>
<rhb1Decimation=2>
<iqRate_kHz=30720>
<rfBandwidth_Hz=20000000>
<rxBbf3dBCorner_kHz=20000>
<filter FIR gain=-6 num=72>
0
2
4
3
-4
-14
-21
-12
17
56
73
39
-53
-159
-198
-101
129
377
457
229
-274
-793
-951
-482
527
1564
1899
1011
-978
-3154
-4109
-2611
1669
7795
13807
17524
17524
13807
7795
1669
-2611
-4109
-3154
-978
1011
1899
1564
527
-482
-951
-793
-274
229
457
377
129
-101
-198
-159
-53
39
73
56
17
-12
-21
-14
-4
3
4
2
0
</filter>
<adc-profile num=16>
599
357
201
98
1280
112
1505
53
1331
21
820
40
48
40
23
191
</adc-profile>
</rx>
<obs>
<adcDiv=1>
<rxFirDecimation=2>
<rxDec5Decimation=5>
<enHighRejDec5=1>
<rhb1Decimation=2>
<iqRate_kHz=61440>
<rfBandwidth_Hz=50000000>
<rxBbf3dBCorner_kHz=25000>
<filter FIR gain=0 num=72>
0
-1
1
2
-2
-6
6
12
-13
-24
25
43
-45
-73
77
118
-124
-183
193
274
-289
-402
423
579
-607
-826
866
1187
-1244
-1759
1842
2818
-2970
-5815
4337
18436
18436
4337
-5815
-2970
2818
1842
-1759
-1244
1187
866
-826
-607
579
423
-402
-289
274
193
-183
-124
118
77
-73
-45
43
25
-24
-13
12
6
-6
-2
2
1
-1
0
</filter>
<adc-profile num=16>
596
358
201
98
1280
134
1509
64
1329
25
818
39
48
40
23
190
</adc-profile>
<lpbk-adc-profile num=16>
599
357
201
98
1280
112
1505
53
1331
21
820
40
48
40
23
191
</lpbk-adc-profile>
</obs>
<tx>
<dacDiv=2.5>
<txFirInterpolation=2>
<thb1Interpolation=2>
<thb2Interpolation=2>
<txInputHbInterpolation=1>
<iqRate_kHz=61440>
<primarySigBandwidth_Hz=20000000>
<rfBandwidth_Hz=50000000>
<txDac3dBCorner_kHz=92000>
<txBbf3dBCorner_kHz=25000>
<filter FIR gain=0 num=32>
-118
-122
242
240
-429
-499
730
900
-1154
-1615
1742
2957
-2322
-5354
3885
17211
17211
3885
-5354
-2322
2957
1742
-1615
-1154
900
730
-499
-429
240
242
-122
-118
</filter>
</tx>
</profile>
[AD9371]
ad9371-phy.in_voltage2_rf_port_select = OFF
ad9371-phy.in_voltage2_hardwaregain = -156.000000 dB
ad9371-phy.in_voltage2_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_voltage0_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage0_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage0_quadrature_tracking_en = 1
ad9371-phy.out_voltage1_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage1_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage1_TX_LO_frequency = 2535000000
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = 2655000000
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage0_gain_control_mode = automatic
ad9371-phy.in_voltage0_quadrature_tracking_en = 1
ad9371-phy.in_voltage0_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage0_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage1_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage1_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage1_gain_control_mode = automatic
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage0_RX_LO_frequency = 2655000000
ad9371-phy.calibrate_rx_qec_en = 0
ad9371-phy.calibrate_tx_lol_en = 0
ad9371-phy.calibrate_vswr_en = 0
ad9371-phy.calibrate_tx_qec_en = 0
ad9371-phy.calibrate_clgc_en = 0
ad9371-phy.ensm_mode = radio_on
ad9371-phy.calibrate_tx_lol_ext_en = 0
ad9371-phy.calibrate_dpd_en = 0
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_scale = 0.000000
load_myk_profile_file = /targets/ARCH/ADRV9371_ZC706/USERSPACE/PROFILES/profile_rx30_Tx60_syr.txt
dds_mode_tx1 = 1
dds_mode_tx2 = 1
dac_buf_filename = /usr/local/lib/osc/waveforms/LTE20.mat
tx_channel_0 = 1
tx_channel_1 = 1
tx_channel_2 = 0
tx_channel_3 = 0
global_settings_show = 1
tx_show = 1
rx_show = 1
obs_show = 1
fpga_show = 1
[ADRV9371_ZC706]
debug_mode = 0
interpolation_decimation_factor = 1
[AD9371]
ad9371-phy.in_voltage2_rf_port_select = OFF
ad9371-phy.in_voltage2_hardwaregain = -156.000000 dB
ad9371-phy.in_voltage2_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_voltage0_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage0_hardwaregain = -20.000000 dB
ad9371-phy.out_voltage0_quadrature_tracking_en = 1
ad9371-phy.out_voltage1_hardwaregain = -20.000000 dB
ad9371-phy.out_voltage1_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage1_TX_LO_frequency = 2560000000
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = 2680000000
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage0_gain_control_mode = manual
ad9371-phy.in_voltage0_quadrature_tracking_en = 1
ad9371-phy.in_voltage0_hardwaregain = 15.000000 dB
ad9371-phy.in_voltage0_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage1_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage1_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage1_gain_control_mode = manual
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage0_RX_LO_frequency = 2680000000
ad9371-phy.calibrate_rx_qec_en = 0
ad9371-phy.calibrate_tx_lol_en = 0
ad9371-phy.calibrate_vswr_en = 0
ad9371-phy.calibrate_tx_qec_en = 0
ad9371-phy.calibrate_clgc_en = 0
ad9371-phy.ensm_mode = radio_on
ad9371-phy.calibrate_tx_lol_ext_en = 0
ad9371-phy.calibrate_dpd_en = 0
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_scale = 0.000000
load_myk_profile_file = /targets/ARCH/ADRV9371_ZC706/USERSPACE/PROFILES/profile_rx30_Tx60_syr.txt
dds_mode_tx1 = 1
dds_mode_tx2 = 1
dac_buf_filename = /usr/local/lib/osc/waveforms/LTE20.mat
tx_channel_0 = 1
tx_channel_1 = 1
tx_channel_2 = 0
tx_channel_3 = 0
global_settings_show = 1
tx_show = 1
rx_show = 1
obs_show = 1
fpga_show = 1
[ADRV9371_ZC706]
# NO_DEBUG=0; DEBUG=1
debug_mode = 0
# 20MHz 40MHz 80MHz=1; 10MHz=2; 5MHz=4
interpolation_decimation_factor = 1
# is taken into account only if "ad9371-phy.in_voltage0_gain_control_mode = manual"
rx_gain_offset = 46
[AD9371]
ad9371-phy.in_voltage2_rf_port_select = OFF
ad9371-phy.in_voltage2_hardwaregain = -156.000000 dB
ad9371-phy.in_voltage2_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_voltage0_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage0_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage0_quadrature_tracking_en = 1
ad9371-phy.out_voltage1_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage1_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage1_TX_LO_frequency = 2535000000
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = 2655000000
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage0_gain_control_mode = automatic
ad9371-phy.in_voltage0_quadrature_tracking_en = 1
ad9371-phy.in_voltage0_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage0_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage1_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage1_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage1_gain_control_mode = automatic
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage0_RX_LO_frequency = 2655000000
ad9371-phy.calibrate_rx_qec_en = 0
ad9371-phy.calibrate_tx_lol_en = 0
ad9371-phy.calibrate_vswr_en = 0
ad9371-phy.calibrate_tx_qec_en = 0
ad9371-phy.calibrate_clgc_en = 0
ad9371-phy.ensm_mode = radio_on
ad9371-phy.calibrate_tx_lol_ext_en = 0
ad9371-phy.calibrate_dpd_en = 0
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_scale = 0.000000
load_myk_profile_file = /targets/ARCH/ADRV9371_ZC706/USERSPACE/PROFILES/profile_rx30_Tx60_syr.txt
dds_mode_tx1 = 1
dds_mode_tx2 = 1
dac_buf_filename = /usr/local/lib/osc/waveforms/LTE20.mat
tx_channel_0 = 1
tx_channel_1 = 1
tx_channel_2 = 0
tx_channel_3 = 0
global_settings_show = 1
tx_show = 1
rx_show = 1
obs_show = 1
fpga_show = 1
[ADRV9371_ZC706]
debug_mode = 0
interpolation_decimation_factor = 4
[AD9371]
ad9371-phy.in_voltage2_rf_port_select = OFF
ad9371-phy.in_voltage2_hardwaregain = -156.000000 dB
ad9371-phy.in_voltage2_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_voltage0_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage0_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage0_quadrature_tracking_en = 1
ad9371-phy.out_voltage1_hardwaregain = -10.000000 dB
ad9371-phy.out_voltage1_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage1_TX_LO_frequency = 2535000000
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = 2655000000
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage0_gain_control_mode = automatic
ad9371-phy.in_voltage0_quadrature_tracking_en = 1
ad9371-phy.in_voltage0_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage0_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage1_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage1_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage1_gain_control_mode = automatic
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage0_RX_LO_frequency = 2655000000
ad9371-phy.calibrate_rx_qec_en = 0
ad9371-phy.calibrate_tx_lol_en = 0
ad9371-phy.calibrate_vswr_en = 0
ad9371-phy.calibrate_tx_qec_en = 0
ad9371-phy.calibrate_clgc_en = 0
ad9371-phy.ensm_mode = radio_on
ad9371-phy.calibrate_tx_lol_ext_en = 0
ad9371-phy.calibrate_dpd_en = 0
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_scale = 0.000000
load_myk_profile_file = /targets/ARCH/ADRV9371_ZC706/USERSPACE/PROFILES/profile_rx30_Tx60_syr.txt
dds_mode_tx1 = 1
dds_mode_tx2 = 1
dac_buf_filename = /usr/local/lib/osc/waveforms/LTE20.mat
tx_channel_0 = 1
tx_channel_1 = 1
tx_channel_2 = 0
tx_channel_3 = 0
global_settings_show = 1
tx_show = 1
rx_show = 1
obs_show = 1
fpga_show = 1
[ADRV9371_ZC706]
debug_mode = 0
interpolation_decimation_factor = 2
Common command line:
--------------------
cd /openairinterface5g/
source oaienv
HWLAT application:
------------------
./cmake_targets/build_oai -c -C -w ADRV9371_ZC706 --HWLAT
./cmake_targets/lte-hwlat/build/lte-hwlat
LTE-SOFTMODEM application:
--------------------------
./cmake_targets/build_oai -c --eNB --UE --noS1 -w ADRV9371_ZC706
sudo su
source oaienv
source ./targets/bin/init_nas_nos1 UE
./cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 -U -C 2680000000 -r100 --ue-scan-carrier --ue-txgain 0 --ue-rxgain 5 -S -A 6 --ue-max-power -25 --phy-test -g 7 --rf-config-file ./targets/ARCH/ADRV9371_ZC706/USERSPACE/PROFILES/ue.band7.tm1.PRB100.adrv9371-zc706_HWgain15dB.ini
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <linux/sched.h>
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
#include <syscall.h>
#include <sys/sysinfo.h>
#include "assertions.h"
#include "PHY/types.h"
#include "PHY/defs.h"
#include <sys/time.h>
#define GET_TIME_INIT(num) struct timeval _timers[num]
#define GET_TIME_VAL(num) gettimeofday(&_timers[num], NULL)
#define TIME_VAL_TO_MS(num) (((double)_timers[num].tv_sec*1000.0) + ((double)_timers[num].tv_usec/1000.0))
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "../../ARCH/COMMON/common_lib.h"
#include "PHY/extern.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h"
#define RIFFA_CHANNEL_TESTER 0
#define RIFFA_CHANNEL_TESTER2 0
#define RIFFA_CHANNEL_DATA1 1
volatile int oai_exit = 0;
openair0_config_t openair0_cfg[MAX_CARDS];
#if 0
#define NB_ANTENNAS_RX 4
#define DevAssert(cOND) _Assert_(cOND, _Assert_Exit_, "")
#define malloc16(x) memalign(16,x)
#ifdef 0
static inline void* malloc16_clear( size_t size )
{
#ifdef __AVX2__
void* ptr = memalign(32, size);
#else
void* ptr = memalign(16, size);
#endif
if(ptr)
memset( ptr, 0, size );
return ptr;
}
#endif
#endif
typedef struct latency_stat {
uint64_t counter;
uint64_t stat250;
uint64_t stat500;
uint64_t stat600;
uint64_t stat700;
uint64_t stat800;
uint64_t stat1300;
uint64_t stat1500;
uint64_t stat2000;
uint64_t stat2500;
uint64_t stat3000;
uint64_t stat880;
uint64_t stat960;
uint64_t stat1040;
uint64_t stat1120;
uint64_t stat1200;
} latency_stat_t;
typedef struct timing_stats {
char *name;
double min;
double max;
double total;
unsigned int count;
} timing_stats_t;
//static struct timespec get_timespec_diff(
// struct timespec *start,
// struct timespec *stop )
//{
// struct timespec result;
//
// if ( ( stop->tv_nsec - start->tv_nsec ) < 0 ) {
// result.tv_sec = stop->tv_sec - start->tv_sec - 1;
// result.tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
// }
// else {
// result.tv_sec = stop->tv_sec - start->tv_sec;
// result.tv_nsec = stop->tv_nsec - start->tv_nsec;
// }
//
// return result;
//}
//static void measure_time (
// openair0_device *rf_device,
// struct timespec *start,
// struct timespec *stop,
// timing_stats_t *stats,
// boolean_t START,
// uint8_t PRINT_INTERVAL )
//{
// if ( START ) {
// clock_gettime( CLOCK_MONOTONIC, start );
// }
// else {
// clock_gettime( CLOCK_MONOTONIC, stop );
//
// struct timespec diff;
// double current = 0;
//// boolean_t show_stats = false;
//
// diff = get_timespec_diff( start, stop );
// current = (double)diff.tv_sec * 1000000 + (double)diff.tv_nsec / 1000;
//
// if ( current > stats->max ) {
// stats->max = current;
//// show_stats = true;
// }
// if ( stats->min == 0 || current < stats->min ) {
// stats->min = current;
//// show_stats = true;
// }
// stats->total += current;
//
//// if ( show_stats ) {
//// rf_device.trx_get_stats_func( &rf_device );
//// }
//
//// if ( stats->count % PRINT_INTERVAL == 0 ) {
//// double avg = stats->total / ( stats->count + 1 );
//// printf( "[%s][%d] Current : %.2lf µs, Min : %.2lf µs, Max : %.2lf µs, Avg : %.2lf µs\n",
//// stats->count, stats->name, current, stats->min, stats->max, avg );
//// }
//
// stats->count++;
// }
//}
int32_t **rxdata;
int32_t **txdata;
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
static inline void saif_meas(int frame_rx, int subframe_rx) {
static latency_stat_t __thread latency_stat;
static struct timespec __thread last= {0};
struct timespec now;
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
if ( last.tv_sec ) {
uint64_t diffTime = ((uint64_t)now.tv_sec *1000 *1000 *1000 + now.tv_nsec) -
((uint64_t)last.tv_sec *1000 *1000 *1000 + last.tv_nsec);
diffTime/=1000;
latency_stat.counter++;
if ( diffTime <= 800 ) {
if (diffTime < 250 )
latency_stat.stat250++;
else if (diffTime < 500 )
latency_stat.stat500++;
else if (diffTime < 600 )
latency_stat.stat600++;
else if (diffTime < 700 )
latency_stat.stat700++;
else
latency_stat.stat800++;
}
else if ( diffTime > 1200 ) {
if (diffTime < 1500 )
latency_stat.stat1300++;
else if ( diffTime < 2000 )
latency_stat.stat1500++;
else if ( diffTime < 2500 )
latency_stat.stat2000++;
else if ( diffTime < 3000 )
latency_stat.stat2500++;
else
latency_stat.stat3000++;
}
else
if (diffTime <= 880 )
latency_stat.stat880++;
else if (diffTime <= 960 )
latency_stat.stat960++;
else if (diffTime <= 1040 )
latency_stat.stat1040++;
else if (diffTime < 1120 )
latency_stat.stat1120++;
else
latency_stat.stat1200++;
if ( (diffTime>=1500) || ( !(frame_rx%1024) && subframe_rx == 0 ) ) {
time_t current=time(NULL);
printf("\n");
printf("%.2f Period stats cnt=%7.7ld 0.. 250=%7.7ld 250.. 500=%7.7ld 500.. 600=%7.7ld 600.. 700=%7.7ld 700.. 800=%7.7ld - (frame_rx=%d) - %s",
now.tv_sec+(double)now.tv_nsec/1e9,
latency_stat.counter,
latency_stat.stat250, latency_stat.stat500,
latency_stat.stat600, latency_stat.stat700,
latency_stat.stat800,
frame_rx,
ctime(&current));
printf("%.2f Period stats cnt=%7.7ld 800.. 880=%7.7ld 880.. 960=%7.7ld 960..1040=%7.7ld 1040..1120=%7.7ld 1120..1200=%7.7ld - (frame_rx=%d) - %s",
now.tv_sec+(double)now.tv_nsec/1e9,
latency_stat.counter,
latency_stat.stat880, latency_stat.stat960,
latency_stat.stat1040, latency_stat.stat1120,
latency_stat.stat1200,
frame_rx,
ctime(&current));
printf("%.2f Period stats cnt=%7.7ld 1200..1300=%7.7ld 1300..1500=%7.7ld 1500..2000=%7.7ld 2000..2500=%7.7ld >3000=%7.7ld - (frame_rx=%d) - %s",
now.tv_sec+(double)now.tv_nsec/1e9,
latency_stat.counter,
latency_stat.stat1300, latency_stat.stat1500,
latency_stat.stat2000, latency_stat.stat2500,
latency_stat.stat3000,
frame_rx,
ctime(&current));
fflush(stdout);
}
}
last=now;
}
/* End of Changed by SYRTEM */
void exit_fun(const char* s)
{
if (s != NULL) {
printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
}
oai_exit = 1;
}
void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, char * name) {
#ifdef DEADLINE_SCHEDULER
if (sched_runtime!=0) {
struct sched_attr attr= {0};
attr.size = sizeof(attr);
// This creates a .5 ms fpga_recv_cnt reservation
attr.sched_policy = SCHED_DEADLINE;
attr.sched_runtime = sched_runtime;
attr.sched_deadline = sched_deadline;
attr.sched_period = 0;
AssertFatal(sched_setattr(0, &attr, 0) == 0,
"[SCHED] main eNB thread: sched_setattr failed %s \n",perror(errno));
LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %lu started on CPU %d\n",
(unsigned long)gettid(), sched_getcpu());
}
#else
#ifdef CPU_AFFINITY
if (get_nprocs() >2) {
for (j = 1; j < get_nprocs(); j++)
CPU_SET(j, &cpuset);
}
AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)==0,"");
#endif
struct sched_param sp;
sp.sched_priority = sched_fifo;
AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
"Can't set thread priority, Are you root?\n");
#endif
// Lock memory from swapping. This is a process wide call (not constraint to this thread).
mlockall(MCL_CURRENT | MCL_FUTURE);
pthread_setname_np( pthread_self(), name );
}
int main(void)
{
int ret;
uint64_t i;
openair0_device rf_device;
openair0_timestamp timestamp = 0;
int sub_frame = 0;
unsigned int frame_rx = 0;
unsigned int nb_antennas_tx = 1;
unsigned int nb_antennas_rx = 1;
openair0_cfg[0].mmapped_dma = 0;
openair0_cfg[0].configFilename = NULL;
openair0_cfg[0].duplex_mode = duplex_mode_FDD;
uint32_t **sendbuff = NULL;
uint32_t **recvbuff = NULL;
uint32_t expected_value = 0;
uint32_t received_value = 0;
int nsamp = 0; // 1 ms
int antenna_id = 1;
int c = 0;
int numIter = 0;
int fpga_loop = 0;
#if RIFFA_CHANNEL_DATA1
uint64_t first_ts = 0;
uint8_t is_first_ts = 0;
uint64_t trx_read_cnt = 0;
uint32_t j = 0;
uint32_t err_cnt = 0;
#else
int failure = 0;
#endif
#if 0 // 5MHz BW
unsigned int nb_sample_per_tti = 7680;
openair0_cfg[0].sample_rate = 7.68e6;
openair0_cfg[0].samples_per_frame = nb_sample_per_tti*10;
openair0_cfg[0].rx_bw = 2.5e6;
openair0_cfg[0].tx_bw = 2.5e6;
openair0_cfg[0].num_rb_dl = 25;
#endif
#if 0 // 10MHz BW
unsigned int nb_sample_per_tti = 15360;
openair0_cfg[0].sample_rate = 15.36e6;
openair0_cfg[0].samples_per_frame = nb_sample_per_tti*10;
openair0_cfg[0].rx_bw = 5.0e6;
openair0_cfg[0].tx_bw = 5.0e6;
openair0_cfg[0].num_rb_dl = 50;
#endif
#if 1 // 20MHz BW
unsigned int nb_sample_per_tti = 30720;
openair0_cfg[0].sample_rate = 30.72e6;
openair0_cfg[0].samples_per_frame = nb_sample_per_tti*10;
openair0_cfg[0].rx_bw = 10.0e6;
openair0_cfg[0].tx_bw = 10.0e6;
openair0_cfg[0].num_rb_dl = 100;
#endif
const char *openair_dir = getenv("OPENAIR_DIR");
const char *ini_file = "/targets/ARCH/ADRV9371_ZC706/USERSPACE/PROFILES/ue.band7.tm1.PRB100.adrv9371-zc706_HWgain15dB.ini";
int readBlockSize;
void* rxp[nb_antennas_rx];
void* txp[nb_antennas_tx];
// int32_t rxdata[1][nb_sample_per_tti*10+2048];
#if 0
int32_t **rxdata;
#endif
// init_thread(100000, 500000, sched_get_priority_max(SCHED_FIFO),"main UE");
printf("LTE HARDWARE Latency debug utility \n");
printf("INIT data buffers \n");
#if 0
rxdata = (int32_t**)memalign(32, nb_antennas_rx*sizeof(int32_t*) );
rxdata[0] = (int32_t*)memalign(32,(nb_sample_per_tti*10+2048)*sizeof(int32_t));
#else
rxdata = (int32_t**)malloc16( nb_antennas_rx*sizeof(int32_t*) );
txdata = (int32_t**)malloc16( nb_antennas_tx*sizeof(int32_t*) );
rxdata[0] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
txdata[0] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
#endif
printf("INIT done\n");
memset(&rf_device, 0, sizeof(openair0_device));
rf_device.host_type = BBU_HOST;
openair0_cfg[0].duplex_mode = duplex_mode_FDD;
openair0_cfg[0].rx_num_channels = 1;
openair0_cfg[0].tx_num_channels = 1;
// configure channel 0
for (i=0; i<openair0_cfg[0].rx_num_channels; i++)
{
printf("configure channel %d \n",i);
openair0_cfg[0].autocal[i] = 1;
openair0_cfg[0].rx_freq[i] = 2680000000;
openair0_cfg[0].tx_freq[i] = 2560000000;
openair0_cfg[0].rx_gain[i] = 61;
openair0_cfg[0].tx_gain[i] = 90;
}
if (openair_dir)
{
openair0_cfg[0].configFilename = malloc(strlen(openair_dir) + strlen(ini_file) + 2);
sprintf(openair0_cfg[0].configFilename, "%s/%s", openair_dir, ini_file);
}
// printf("openair0_cfg[0].configFilename:%s\n", openair0_cfg[0].configFilename);
ret = openair0_device_load( &rf_device, &openair0_cfg[0] );
if (ret != 0){
exit_fun("Error loading device library");
exit(-1);
}
/* Runtime test
* 30 720 000 samples (4 bytes) for 1 sec (30 720 for 1 ms)
*/
puts( "* Starting the device" );
// TIMING
// struct timespec start, stop; // tx_start, tx_stop;
// timing_stats_t rx_stats, tx_stats;
// rx_stats.name = strdup( "RX" );
// tx_stats.name = strdup( "TX" );
// TIMING
nsamp = 307200; // 1 ms
sendbuff = memalign( 128, nb_antennas_rx * sizeof( uint32_t * ) );
sendbuff[0] = memalign( 128, nsamp * sizeof( uint32_t ) );
recvbuff = memalign( 128, nb_antennas_rx * sizeof( uint32_t * ) );
recvbuff[0] = memalign( 128, nsamp * sizeof( uint32_t ) );
// Create dummy buffer
for ( c = 0; c < nsamp; c++ ) {
// sendbuff[0][c] = (c+1);
sendbuff[0][c] = (c+1)*16;
// sendbuff[0][c] = (nsamp-c);
recvbuff[0][c] = 0;
}
GET_TIME_INIT(3);
if ( rf_device.trx_start_func( &rf_device ) < 0 ) {
printf( " device could not be started !\n" );
return -1;
}
// read 30720
// write 30720 ts+2*30720
// if tsread >= 2-307200 -> check expected value + status (RxoVer TxUnder)
rxp[0] = (void*)&rxdata[0][0];
txp[0] = (void*)&txdata[0][0];
timestamp = 0;
nsamp = 30720; // 30720 => 1ms buffer
trx_read_cnt = 100000; // 1 loop => 1ms (10sec=10000; 15min = 900000)
antenna_id = 1;
int diff = 0;
int compare_start = 0;
uint32_t looploop=0;
uint64_t error_cnt = 0;
uint64_t error_ts_start;
for (i = 0; i < trx_read_cnt; i++)
{
// printf("\n\n");
// ret = rf_device.trx_read_func( &rf_device, &timestamp, &(rxp[0][(i*30720)%307200]), nsamp, antenna_id );
// ret = rf_device.trx_read_func( &rf_device, &timestamp, recvbuff[0][(i*30720)%307200], nsamp, antenna_id );
rxp[0] = (void*)&rxdata[0][(i*30720)%307200];
GET_TIME_VAL(0);
ret = rf_device.trx_read_func( &rf_device, &timestamp, rxp, nsamp, antenna_id );
GET_TIME_VAL(1);
if (ret != nsamp)
{
printf("Error: nsamp received (%d) != nsamp required (%d)\n", ret, nsamp);
fflush(stdout);
return (-1);
}
if (!is_first_ts)
{
first_ts = timestamp;
is_first_ts = 1;
}
// printf("%d - trx_read_func ret=%d - ts = %d - @=0x%08lx\n", i, ret, timestamp, rxp[0] );
txp[0] = (void*)&(txdata[0][ ((i*30720)%307200+2*30720)%307200 ]);
// printf(" i=%d @txp[0][0] = 0x%016lx\n", i, &(((uint32_t *)txp[0])[0]) );
// printf(" i=%d @txp[0][1] = 0x%016lx\n", i, &(((uint32_t *)txp[0])[1]) );
for ( c = 0; c < nsamp; c++ )
{
(((uint32_t *)txp[0])[c]) = ( (((timestamp+c+2*30720)<<4)&0x0000FFF0) + (((timestamp+c+2*30720)<<8)&0xFFF00000) );
}
// printf(" txp[0][%d] = 0x%x\n",0,((uint32_t *)(txp[0]))[0]);
// printf(" txp[0][%d] = 0x%x\n",1,((uint32_t *)(txp[0]))[1]);
// printf(" ...\n");
// printf(" txp[0][%d] = 0x%x\n",nsamp-2,((uint32_t *)(txp[0]))[nsamp-2]);
// printf(" txp[0][%d] = 0x%x\n",nsamp-1,((uint32_t *)(txp[0]))[nsamp-1]);
ret = rf_device.trx_write_func( &rf_device, (timestamp+2*30720), txp, nsamp, antenna_id, false );
if (ret != nsamp)
{
printf("Error: nsamp sent (%d) != nsamp required (%d)\n", ret, nsamp);
fflush(stdout);
return (-1);
}
// printf("%d - trx_write_func ret=%d - ts = %d - @=0x%08lx\n", i, ret, (timestamp+2*30720), txp[0] );
if (timestamp >= (first_ts + 2 * 307200))
{
// check Rx Overflow
// check Tx Underflow
// check Expected Value
for ( c = 0; c < nsamp; c++ )
{
// LOOPBACK
#if 1
expected_value = ((timestamp + c)&0xFFFFFF);
received_value = ((uint32_t *)(rxp[0]))[c];
received_value = ((received_value)&0xFFF) + ((received_value>>4)&0xFFF000);
if (compare_start == 0)
{
compare_start = 1;
diff = expected_value - received_value;
}
received_value = (received_value + diff)&0xFFFFFF;
#if 1
if (expected_value != received_value)
{
if(!error_cnt)
error_ts_start = (timestamp + c);
else
{
if (looploop < 32)
printf("%d - %d != %d - ts %d - raw 0x%x - diff %d\n",
looploop,
expected_value, received_value,
(timestamp + c), ((uint32_t *)(rxp[0]))[c],
diff);
looploop++;
}
error_cnt++;
if(!(error_cnt%102400))
printf(" -> error detected : cnt=%d - start=%ld - stop=... diff=%d\n",
error_cnt,
error_ts_start,
diff);
}
else
{
if(error_cnt)
{
printf(" -> error detected : cnt=%d - start=%ld - stop=%ld\n\n",
error_cnt,
error_ts_start,
(timestamp + c) );
looploop=0;
}
error_cnt=0;
}
#endif
#endif
// DEBUG mode 0
#if 0
received_value = ((uint32_t *)(rxp[0]))[c];
received_value = ((received_value)&0xFFF) + ((received_value>>4)&0xFFF000);
received_value = (received_value&0xFFFFFF);
if (compare_start == 0)
{
compare_start = 1;
expected_value = received_value;
}
else
{
expected_value++;
expected_value = (expected_value&0xFFFFFF);
}
if (expected_value != received_value)
{
if(!error_cnt)
error_ts_start = (timestamp + c);
error_cnt++;
}
else
{
if(error_cnt)
{
printf(" -> error detected : cnt=%d - start=%ld - stop=%ld\n\n",
error_cnt,
error_ts_start,
(timestamp + c) );
}
error_cnt=0;
}
// if (expected_value != received_value)
// {
// printf("%d -> %d != %d (ts+c=%ld)(raw=0x%08x)\n",
// looploop,
// expected_value, received_value,
// (timestamp + c),
// ((uint32_t *)(rxp[0]))[c] );
//
// if (received_value)
// expected_value = received_value;
// }
#endif
}
}
}
printf("HwLat Application returns !!!\n");
fflush(stdout);
sleep(1);
printf("\n");
rf_device.trx_end_func( &rf_device );
sleep(1);
free(sendbuff[0]);
free(sendbuff);
free(recvbuff[0]);
free(recvbuff);
exit(0);
return(0);
// puts( "* Frequency modification test" );
// rf_device.trx_set_freq_func( &rf_device, &openair0_cfg[0], 0 );
// puts( "* Gain modification test" );
// rf_device.trx_set_gains_func( &rf_device, &openair0_cfg[0] ); // NOT working (cf. initialization)
//#if LTE_UE
// sleep(1);
GET_TIME_VAL(0);
for (i = 0; i < trx_read_cnt; i++)
{
printf("\n");
ret = rf_device.trx_read_func( &rf_device, &timestamp, rxp, nsamp, antenna_id );
printf("* timestamp=%ld\n", timestamp);
#if 1
for (j = 0; j < nsamp; j++)
{
if ( ((uint32_t *)rxp[0])[j] != ((expected_value + j + timestamp)%307200) )
{
err_cnt++;
printf("rxp[%06d]=0x%08x (expected 0x%08lx)\n", j, ((uint32_t *)rxp[0])[j], ((expected_value + j + timestamp)%307200) );
}
if (err_cnt >= 128)
{
printf("Error: more than 128 expected value failed !\n");
i = (trx_read_cnt - 1);
j = nsamp;
break;
}
}
//expected_value = (expected_value + nsamp)%307200;
expected_value = (expected_value)%307200;
#endif
}
GET_TIME_VAL(1);
//#endif
/* ********** ********** */
/* RIFFA_CHANNEL_DATA1 */
/* ********** ********** */
#if RIFFA_CHANNEL_DATA1
// rf_device.trx_get_stats_func( &rf_device );
rf_device.trx_end_func( &rf_device );
printf("\n* rf_device.trx_read_func(%d) x %d: %.6lf s\n\n", nsamp, i, ((TIME_VAL_TO_MS(1) - TIME_VAL_TO_MS(0)))/1000.0 );
// rf_device.trx_get_stats_func( &rf_device );
#if 0
for (i = 0; i < nsamp; i++)
{
// if ( ((uint32_t *)rxp[0])[i] != i)
// {
err_cnt++;
printf("rxp[%06d]=0x%08x (expected 0x%08x)\n", i, ((uint32_t *)rxp[0])[i], i);
// }
// if (err_cnt > 256)
// {
// i = 307200;
// break;
// }
}
#endif
// for (i = 1024-32; i < 1024+32; i++)
// {
//// if ( ((uint32_t *)rxp[0])[i] != i)
//// {
// err_cnt++;
// printf("rxp[%06d]=0x%08x (expected 0x%08x)\n", i, ((uint32_t *)rxp[0])[i], i);
//// }
// if (err_cnt > 256)
// {
// i = 307200;
// break;
// }
// }
printf("RIFFA CHANNEL DATA1 done !!!\n");
sleep(1);
return(0);
#endif
/* ********** ********** */
/* RIFFA_CHANNEL_DATA1 */
/* ********** ********** */
timestamp = 0;
ret = rf_device.trx_write_func( &rf_device, timestamp, (void**)sendbuff, nsamp, antenna_id, false );
printf("* rf_device.trx_write_func returns %d\n", ret);
sleep(1);
nsamp = 30720;
numIter = 100000;
for ( c = 0; c < numIter; c++ )
{
fpga_loop ++;
if ( !(fpga_loop % 1000) )
{
printf("\rtest loop %d / %d", fpga_loop, numIter);
fflush(stdout);
}
// printf("* TEST : %08d\n", (c+1));
// measure_time( &rf_device, &start, &stop, &tx_stats, true, 10 );
// ret = rf_device.trx_write_func( &rf_device, timestamp, (void**)sendbuff, nsamp, antenna_id, false );
// printf("* rf_device.trx_write_func returns %d\n", ret);
// measure_time( &rf_device, &start, &stop, &tx_stats, false, 10 );
// sleep(1);
// measure_time( &rf_device, &start, &stop, &tx_stats, true, 10 );
ret = rf_device.trx_read_func( &rf_device, &timestamp, (void**)recvbuff, nsamp, antenna_id );
// measure_time( &rf_device, &start, &stop, &tx_stats, false, 10 );
// Check the data
if (ret > 0)
{
/* ********** ********** */
/* RIFFA_CHANNEL_TESTER */
/* ********** ********** */
#if RIFFA_CHANNEL_TESTER
failure = 0;
for (i = 0; i < ret; i++)
{
if ( ((i%1024) == 0) || ((i%1024) == 1) || ((i%1024) == 2) || ((i%1024) == 3) )
{
if ( (recvbuff[0])[i] != (1020 + ((i%1024)+1)) )
{
printf("* ERROR (buff[0])[%d]: %d, expected %d\n", i, (uint32_t)(recvbuff[0])[i], ((i%1024)+1) );
failure = 1;
}
}
else if ( (recvbuff[0])[i] != ((i%1024)+1) )
{
printf("* ERROR (buff[0])[%d]: %d, expected %d\n", i, (uint32_t)(recvbuff[0])[i], ((i%1024)+1) );
failure = 1;
}
else
{
printf("* DONE (buff[0])[%d]: %d, expected %d\n", i, (uint32_t)(recvbuff[0])[i], ((i%1024)+1) );
}
if(failure)
break;
}
if (failure)
printf("* ERROR recv %08d checked FAILURE ret=%d\n", (c+1), ret);
else
{
// printf("* DONE recv %08d checked SUCCESSFULLY ret=%d\n", (c+1), ret);
}
#endif
/* ********** ********** */
/* RIFFA_CHANNEL_TESTER2*/
/* ********** ********** */
#if RIFFA_CHANNEL_TESTER2
// printf("* ret=%d timestamp=%ld (%ld)\n", ret, timestamp, (timestamp%307200));
failure = 0;
for (i = 0; i < ret; i++)
{
// printf("* (recvbuff[0])[%d]: %d\n", i, (uint32_t)(recvbuff[0])[i]);
// printf("* timestamp+(i/1024+1)*1024 - 3 + i%1024: %d\n", (timestamp-nsamp+(i/1024+1)*1024 - 3 + i%1024)%307200 );
expected_value = ((((i%1024)+1)/*>>4*/)&0x00000FFF);
if ( ((i%1024) == 0) || ((i%1024) == 1) || ((i%1024) == 2) || ((i%1024) == 3) )
{
expected_value = ((((timestamp-nsamp+(i/1024+1)*1024 - 3 + i%1024))%307200));
if ( (recvbuff[0])[i] != expected_value)
{
if ( (expected_value == 0) && ((recvbuff[0])[i] != 4915200) )
{
printf("* ERROR (buff[0])[%d]: %d, expected %d\n", i, (uint32_t)(recvbuff[0])[i], expected_value );
failure = 1;
}
if ( (expected_value == 0) && ((recvbuff[0])[i] == 4915200) )
{
// printf("* DONE loop in circular buffer\n");
}
}
}
else if ( (recvbuff[0])[i] != expected_value )
{
printf("* ERROR (buff[0])[%d]: %d, expected %d\n", i, (uint32_t)(recvbuff[0])[i], ((i%1024)+1) );
failure = 1;
}
else
{
// printf("* DONE (buff[0])[%d]: %d, expected %d\n", i, (uint32_t)(recvbuff[0])[i], ((i%1024)+1) );
}
// if(failure)
// break;
}
if (failure)
printf("* ERROR recv %08d checked FAILURE ret=%d\n", (c+1), ret);
else
{
// printf("* DONE recv %08d checked SUCCESSFULLY ret=%d\n", (c+1), ret);
}
#endif
#if LOOPBACK
#endif
}
else
{
printf("* ERROR rf_device.trx_read_func returns %d\n", ret);
}
}
printf("\n");
rf_device.trx_end_func( &rf_device );
sleep(1);
free(sendbuff[0]);
free(sendbuff);
free(recvbuff[0]);
free(recvbuff);
exit(0);
// END IS HERE !
rf_device.trx_set_freq_func(&rf_device,&openair0_cfg[0],0);
if (rf_device.trx_start_func(&rf_device) != 0 ) {
printf("Could not start the device\n");
oai_exit=1;
}
while(!oai_exit){
rxp[0] = (void*)&rxdata[0][sub_frame*nb_sample_per_tti];
readBlockSize = rf_device.trx_read_func( &rf_device,
&timestamp,
rxp,
nb_sample_per_tti,
0);
if ( readBlockSize != nb_sample_per_tti )
oai_exit = 1;
sub_frame++;
sub_frame%=10;
if( sub_frame == 0)
frame_rx++;
saif_meas(frame_rx, sub_frame);
}
return(0);
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/* *************************************************************************************************
USER GUIDE
1 - CONFIGURE TEST SESSION
see TESTS PARAMETERS section below
2 - COMPILATION CMD LINE (same as openair compilation)
- NO AVX SUPPORT
/usr/bin/cc -msse4.1 -mssse3 -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -g -DMALLOC_CHECK_=3 -O2 -o lte-hwlat-test lte-hwlat2.c -lrt -lpthread -lm -ldl
- AVX2 Support
/usr/bin/cc -mavx2 -msse4.1 -mssse3 -std=gnu99 -Wall -Wstrict-prototypes -fno-strict-aliasing -rdynamic -funroll-loops -Wno-packed-bitfield-compat -fPIC -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP -g -DMALLOC_CHECK_=3 -O2 -o lte-hwlat-test lte-hwlat2.c -lrt -lpthread -lm -ldl
3 - RUN
sudo cset shield --force --kthread on -c 1-3 // for 4 cores
sudo cset shield --force --kthread on -c 1-7 // for 8 cores
sudo cset shield ./lte-hwlat-test
4 - remove cset shield
sudo cset shield --reset
***************************************************************************************************/
/* *************************************************************************************************
* TESTS PARAMETERS
*/
#define HWLAT_LOOP_CNT 1000000 /* measurment loop count for each thread*/
#define HWLAT_TTI_SLEEP_US 250 /* usleep duration -> IQ capture simulation (in µ seconds) */
#define RX_NB_TH 6
#define CALIB_RT_INTRUMENTATION 0
/* Laurent Thpmas instrumentation -> see openair2/UTIL/LOG/log.h for full implementation
-> This is a copy and paste implementation in this file for a self contained source */
#define INSTRUMENTATION_LT_RDTSC 1
/* SYRTEM rdtsc instrumentation implementation (see below for more infaormation) */
#define INSTRUMENTATION_SYR_RDTSC 2
/* SYRTEM instrumentation using clock_gettime MONOTONIC */
#define INSTRUMENTATION_SYR_CLOCK_MONO 3
/* SYRTEM instrumentation using clock_gettime REALTIME */
#define INSTRUMENTATION_SYR_CLOCK_REALTIME 4
#define HWLAT_INSTRUMENTATION INSTRUMENTATION_LT_RDTSC
/* Statistics histogram output */
#define HISTOGRAM_MIN_VALUE 0
#define HISTOGRAM_MAX_VALUE 2000
#define HISTOGRAM_STEP 1
#define HISTOGRAM_SIZE ( ( ( HISTOGRAM_MAX_VALUE - HISTOGRAM_MIN_VALUE ) / HISTOGRAM_STEP ) + 1 )
/* *************************************************************************************************/
/*
* INCLUDES
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <syscall.h>
#include <math.h>
#include <sched.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sched.h>
#include <linux/sched.h>
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <sys/syscall.h> /* For SYS_xxx definitions */
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
/* From rt_wrapper.h
****************************************************************************************/
#define gettid() syscall(__NR_gettid) // for gettid
/* From common/utils/itti/assertions.h
****************************************************************************************/
# define display_backtrace()
#define _Assert_Exit_ \
{ \
fprintf(stderr, "\nExiting execution\n"); \
display_backtrace(); \
fflush(stdout); \
fflush(stderr); \
exit(EXIT_FAILURE); \
}
#define _Assert_(cOND, aCTION, fORMAT, aRGS...) \
do { \
if (!(cOND)) { \
fprintf(stderr, "\nAssertion ("#cOND") failed!\n" \
"In %s() %s:%d\n" fORMAT, \
__FUNCTION__, __FILE__, __LINE__, ##aRGS); \
aCTION; \
} \
} while(0)
#define AssertFatal(cOND, fORMAT, aRGS...) _Assert_(cOND, _Assert_Exit_, fORMAT, ##aRGS)
/* From "openair1/PHY/TOOLS/time_meas.h"
****************************************************************************************/
double cpu_freq_GHz;
typedef struct {
long long in;
long long diff;
long long diff_now;
long long p_time; /*!< \brief absolute process duration */
long long diff_square; /*!< \brief process duration square */
long long max;
int trials;
int meas_flag;
} time_stats_t;
static inline unsigned long long rdtsc_oai(void) __attribute__((always_inline));
static inline unsigned long long rdtsc_oai(void)
{
unsigned long long a, d;
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
return (d<<32) | a;
}
double get_cpu_freq_GHz(void);
static inline void reset_meas(time_stats_t *ts) {
ts->trials=0;
ts->diff=0;
ts->diff_now=0;
ts->p_time=0;
ts->diff_square=0;
ts->max=0;
ts->meas_flag=0;
}
double estimate_MHz_syr(void);
static __inline__ uint64_t pickCyclesStart(void);
static __inline__ uint64_t pickCyclesStop(void);
/* From "openair2/UTIL/LOG/log.h"
****************************************************************************************/
extern double cpuf;
extern double cpu_mhz_syr;
static __inline__ uint64_t rdtsc(void) {
uint64_t a, d;
__asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
return (d<<32) | a;
}
typedef struct m {
uint64_t iterations;
uint64_t sum;
uint64_t maxArray[11];
} Meas;
static inline void printMeas(char * txt, Meas *M, int period) {
if (M->iterations%period == 0 ) {
char txt2[512];
sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " max=%"
PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 "\n",
txt,
M->sum/M->iterations,
M->iterations,
M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5],
M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]);
// SYRTEM : just use printf do not include all LOG_X for this test
//#if DISABLE_LOG_X
printf("%s",txt2);
//#else
// LOG_W(PHY, "%s",txt2);
//#endif
}
}
static inline int cmpint(const void* a, const void* b) {
uint64_t* aa=(uint64_t*)a;
uint64_t* bb=(uint64_t*)b;
return (int)(*aa-*bb);
}
static inline uint64_t updateTimes(uint64_t start, Meas *M, int period, char * txt) {
if (start!=0) {
uint64_t end=rdtsc();
long long diff=(end-start)/(cpuf*1000);
M->maxArray[0]=diff;
M->sum+=diff;
M->iterations++;
qsort(M->maxArray, 11, sizeof(uint64_t), cmpint);
// printMeas(txt,M,period); // SYRTEM : Printed only a the end of the measurment loop
return diff;
}
return 0;
}
static inline uint64_t updateTimes_syr(uint64_t start, Meas *M, int period, char * txt) {
if (start!=0) {
// uint64_t end=rdtsc();
uint64_t end=pickCyclesStop();
long long diff=(long long)((double)(end-start)/(cpu_mhz_syr));
// long long diff=(end-start)/(cpuf*1000);
M->maxArray[0]=diff;
M->sum+=diff;
M->iterations++;
qsort(M->maxArray, 11, sizeof(uint64_t), cmpint);
// printMeas(txt,M,period); // SYRTEM : Printed only a the end of the measurment loop
return diff;
}
return 0;
}
#define initRefTimes(a) static __thread Meas a= {0}
#define pickTime(a) uint64_t a=rdtsc()
#define pickTime_syr(a) uint64_t a=pickCyclesStart()
#define readTime(a) a
/*
* DEFINES
*/
#define TIMESPEC_TO_DOUBLE_US( t ) ( ( (double)t.tv_sec * 1000000 ) + ( (double)t.tv_nsec / 1000 ) )
typedef struct histo_time {
double max;
unsigned int count;
} histo_time_t;
static void measure_time ( struct timespec *start, struct timespec *stop, uint8_t START, uint16_t PRINT_INTERVAL );
static struct timespec get_timespec_diff( struct timespec *start, struct timespec *stop );
void histogram_save_in_csv( histo_time_t *histo , char *file_prefix);
histo_time_t *histogram_init( histo_time_t *histo );
void histogram_store_value( histo_time_t *histo, double value );
#define FIFO_PRIORITY 40
#define true 1
#define false 0
/*
* STRUCTURES
*/
/* stub of UE_rxtx_proc full structure in openair1/PHY/defs.h
*/
typedef struct UE_rxtx_proc {
int instance_cnt_rxtx;
pthread_t pthread_rxtx;
pthread_cond_t cond_rxtx;
pthread_mutex_t mutex_rxtx;
int sub_frame_start;
int sub_frame_step;
unsigned long long gotIQs;
unsigned long syr_rdtsc_rxtx_th_unlock_iteration;
uint64_t syr_rdtsc_ue_th_got_iq;
double syr_rdtsc_rxtx_th_unlock;
double syr_rdtsc_rxtx_th_unlock_max;
double syr_rdtsc_rxtx_th_unlock_mean;
double syr_rdtsc_rxtx_th_unlock_min;
histo_time_t *syr_rdtsc_rxtx_th_unlock_histogram;
} UE_rxtx_proc_t;
/* this structure is used to pass both UE phy vars and
* proc to the function UE_thread_rxn_txnp4
*/
struct rx_tx_thread_data {
/* PHY_VARS_UE *UE; */ // UE phy vars not used for this test
UE_rxtx_proc_t *proc; // We use a stub of rxtx_proc see definition above
};
// ODD / EVEN Scheduling
#if 0
typedef struct threads_s {
int iq;
int odd;
int even;
} threads_t;
threads_t threads = { -1, -1, -1 }; // Core number for each thread (iq=3, even=2, odd=1)
#endif
// SLOT 0 / SLOT 1 parallelization
typedef struct threads_s {
int iq;
int one;
int two;
int three;
int four;
int five;
int six;
int slot1_proc_one;
int slot1_proc_two;
int slot1_proc_three;
} threads_t;
threads_t threads= {7,6,5,4,3,2,1,-1,-1,-1};
/*
* FUNCTIONS DEFINITION
*/
void *UE_thread(void *arg);
void init_UE(int nb_inst);
/*
* GLOBALS VARIABLES
*/
volatile int oai_exit = 0;
int th_count = 0;
double cpuf;
double cpu_mhz_syr;
pthread_t pthread_ue;
pthread_attr_t attr_ue;
UE_rxtx_proc_t **rxtx_proc;
struct timespec even_start, even_stop;
struct timespec odd_start, odd_stop;
histo_time_t *th_wake_histogram;
/*
* FUNCTIONS
*/
void exit_fun(const char* s) {
if ( s != NULL ) {
printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
}
oai_exit = 1;
}
void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name) {
#ifdef DEADLINE_SCHEDULER
if (sched_runtime!=0) {
struct sched_attr attr= {0};
attr.size = sizeof(attr);
attr.sched_policy = SCHED_DEADLINE;
attr.sched_runtime = sched_runtime;
attr.sched_deadline = sched_deadline;
attr.sched_period = 0;
AssertFatal(sched_setattr(0, &attr, 0) == 0,
"[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n",
name, (unsigned long)gettid(), sched_getcpu());
}
#else
if (CPU_COUNT(cpuset) > 0)
AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");
struct sched_param sp;
sp.sched_priority = sched_fifo;
AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
"Can't set thread priority, Are you root?\n");
/* Check the actual affinity mask assigned to the thread */
cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE);
if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) {
char txt[512]={0};
for (int j = 0; j < CPU_SETSIZE; j++)
if (CPU_ISSET(j, cset))
sprintf(txt+strlen(txt), " %d ", j);
printf("CPU Affinity of thread %s is %s\n", name, txt);
}
CPU_FREE(cset);
#endif
// Lock memory from swapping. This is a process wide call (not constraint to this thread).
mlockall(MCL_CURRENT | MCL_FUTURE);
pthread_setname_np( pthread_self(), name );
// SYRTEM : Synchronization thread is not simulated -> just ignore this part of code
// // LTS: this sync stuff should be wrong
// printf("waiting for sync (%s)\n",name);
// pthread_mutex_lock(&sync_mutex);
// printf("Locked sync_mutex, waiting (%s)\n",name);
// while (sync_var<0)
// pthread_cond_wait(&sync_cond, &sync_mutex);
// pthread_mutex_unlock(&sync_mutex);
printf("started %s as PID: %ld\n",name, gettid());
}
void init_UE(int nb_inst)
{
int inst;
for (inst=0; inst < nb_inst; inst++) {
// UE->rfdevice.type = NONE_DEV;
// SYRTEM : we use a stub of phy_var_ue
// PHY_VARS_UE *UE = PHY_vars_UE_g[inst][0];
// AssertFatal(0 == pthread_create(&UE->proc.pthread_ue, &UE->proc.attr_ue, UE_thread, (void*)UE), "");
AssertFatal( 0 == pthread_create( &pthread_ue, &attr_ue, UE_thread, NULL ), "" );
}
printf("UE threads created by %ld\n", gettid());
}
// SYRTEM - UE synchronization thread is not used in this latency test program
//static void *UE_thread_synch(void *arg) {
// ...
//}
// SYRTEM - Stub of UE_thread_rxn_txnp4
// -> No DSP scheduled
// -> Only thread initialization and thread wake up are kept
static void *UE_thread_rxn_txnp4(void *arg){
static __thread int UE_thread_rxtx_retval;
struct rx_tx_thread_data *rtd = arg;
UE_rxtx_proc_t *proc = rtd->proc;
proc->instance_cnt_rxtx=-1;
char threadname[256];
sprintf(threadname,"UE_%d_proc_%d", 0, proc->sub_frame_start);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
if ( (proc->sub_frame_start)%RX_NB_TH == 0 && threads.one != -1 )
CPU_SET(threads.one, &cpuset);
if ( (proc->sub_frame_start)%RX_NB_TH == 1 && threads.two != -1 )
CPU_SET(threads.two, &cpuset);
if ( (proc->sub_frame_start)%RX_NB_TH == 2 && threads.three != -1 )
CPU_SET(threads.three, &cpuset);
if ( (proc->sub_frame_start)%RX_NB_TH == 3 && threads.four != -1 )
CPU_SET(threads.four, &cpuset);
if ( (proc->sub_frame_start)%RX_NB_TH == 4 && threads.five != -1 )
CPU_SET(threads.five, &cpuset);
if ( (proc->sub_frame_start)%RX_NB_TH == 5 && threads.six != -1 )
CPU_SET(threads.six, &cpuset);
//CPU_SET(threads.three, &cpuset);
init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
threadname);
proc->syr_rdtsc_rxtx_th_unlock_iteration=0;
proc->syr_rdtsc_rxtx_th_unlock_max=0;
proc->syr_rdtsc_rxtx_th_unlock_mean=0;
proc->syr_rdtsc_rxtx_th_unlock_min=1000;
proc->syr_rdtsc_rxtx_th_unlock_histogram = NULL;
proc->syr_rdtsc_rxtx_th_unlock_histogram = histogram_init (proc->syr_rdtsc_rxtx_th_unlock_histogram);
while (!oai_exit) {
if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
printf("[SCHED][UE] error locking mutex for UE RXTX\n" );
exit_fun("nothing to add");
}
while (proc->instance_cnt_rxtx < 0) {
// most of the time, the thread is waiting here
pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
}
if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
printf("[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
exit_fun("nothing to add");
}
proc->syr_rdtsc_rxtx_th_unlock = (double)(pickCyclesStop()-proc->syr_rdtsc_ue_th_got_iq )/cpu_mhz_syr;
proc->syr_rdtsc_rxtx_th_unlock_iteration++;
proc->syr_rdtsc_rxtx_th_unlock_mean += proc->syr_rdtsc_rxtx_th_unlock;
if ( proc->syr_rdtsc_rxtx_th_unlock_max < proc->syr_rdtsc_rxtx_th_unlock )
proc->syr_rdtsc_rxtx_th_unlock_max = proc->syr_rdtsc_rxtx_th_unlock;
if ( proc->syr_rdtsc_rxtx_th_unlock_min > proc->syr_rdtsc_rxtx_th_unlock )
proc->syr_rdtsc_rxtx_th_unlock_min = proc->syr_rdtsc_rxtx_th_unlock;
histogram_store_value( proc->syr_rdtsc_rxtx_th_unlock_histogram, proc->syr_rdtsc_rxtx_th_unlock );
if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
printf("[SCHED][UE] error locking mutex for UE RXTX\n" );
exit_fun("noting to add");
}
proc->instance_cnt_rxtx--;
if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
printf("[SCHED][UE] error unlocking mutex for UE RXTX\n" );
exit_fun("noting to add");
}
}
// thread finished
free(arg);
return &UE_thread_rxtx_retval;
}
void *UE_thread(void *arg) {
int i = 0;
int hw_loop_cnt = 0;
int nb_threads = RX_NB_TH;
char threadname[128];
cpu_set_t cpuset;
struct rx_tx_thread_data *rtd;
UE_rxtx_proc_t *proc;
CPU_ZERO( &cpuset );
if ( threads.iq != -1 )
CPU_SET( threads.iq, &cpuset );
init_thread( 100000, 500000, FIFO_PRIORITY, &cpuset, "HDW Threads" );
sprintf( threadname, "Main UE %d", 0 );
pthread_setname_np( pthread_self(), threadname );
// init_UE_threads(UE)
pthread_attr_init( &attr_ue );
pthread_attr_setstacksize( &attr_ue, 8192 );//5*PTHREAD_STACK_MIN);
for ( i = 0; i < nb_threads; i++ ) {
printf("\n");
rtd = calloc( 1, sizeof( struct rx_tx_thread_data ) );
if ( rtd == NULL )
abort();
rtd->proc = rxtx_proc[i]; // &UE->proc.proc_rxtx[i];
pthread_mutex_init( &rxtx_proc[i]->mutex_rxtx ,NULL ); // pthread_mutex_init( &UE->proc.proc_rxtx[i].mutex_rxtx,NULL );
pthread_cond_init( &rxtx_proc[i]->cond_rxtx, NULL ); // pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
rtd->proc->sub_frame_start=i;
rtd->proc->sub_frame_step=nb_threads;
printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, rxtx_proc[i]->sub_frame_start,nb_threads, i);
pthread_create( &rxtx_proc[i]->pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd ); // pthread_create( &UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd);
usleep(1000);
}
// init_UE_threads(UE)
int sub_frame=-1;
while ( !oai_exit ) {
sub_frame++;
sub_frame %= 10;
proc = rxtx_proc[hw_loop_cnt%RX_NB_TH];
// Simulate IQ reception
usleep( HWLAT_TTI_SLEEP_US );
proc->syr_rdtsc_ue_th_got_iq = pickCyclesStart();
AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,"");
proc->instance_cnt_rxtx++;
if ( proc->instance_cnt_rxtx == 0 ) {
if ( pthread_cond_signal( &proc->cond_rxtx) != 0 ) {
exit_fun( "nothing to add" );
}
} else {
if ( proc->instance_cnt_rxtx > 2 )
exit_fun( "instance_cnt_rxtx > 2" );
}
AssertFatal( pthread_cond_signal( &proc->cond_rxtx ) == 0 ,"" );
AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,"");
/* Do not go indefinitely */
hw_loop_cnt++;
if ( hw_loop_cnt%1000 == 0 )
{
printf("\r%d/%d",hw_loop_cnt,HWLAT_LOOP_CNT*RX_NB_TH);
fflush(stdout);
}
if (hw_loop_cnt >= HWLAT_LOOP_CNT*RX_NB_TH)
{
printf("\n\n");
for (i=0 ; i<RX_NB_TH ; i++)
{
proc = rxtx_proc[i];
pthread_getname_np(proc->pthread_rxtx,threadname,128 );
printf("RxTX Thread unlock latency on thread %s (it. %ld) (us) : max=%8.3f - mean=%8.3f - min=%8.3f\n",
threadname,
proc->syr_rdtsc_rxtx_th_unlock_iteration,
proc->syr_rdtsc_rxtx_th_unlock_max,
proc->syr_rdtsc_rxtx_th_unlock_mean/proc->syr_rdtsc_rxtx_th_unlock_iteration,
proc->syr_rdtsc_rxtx_th_unlock_min);
histogram_save_in_csv(proc->syr_rdtsc_rxtx_th_unlock_histogram, threadname );
}
printf("\n\n");
oai_exit = 1;
}
} // while !oai_exit
oai_exit = 1;
return NULL;
}
#define CALIB_LOOP_CNT 1000000 //2000000000
#define CALIB_LOOP_REPORT_PERIOD 1000
#define CALIB_LOOP_UP_THRESHOLD 20 // 20 -> for NG Intel flat model
#define CALIB_USLEEP 250
int main( void )
{
int i;
#if CALIB_RT_INTRUMENTATION
uint32_t calib_loop_count;
uint64_t lt_overhead_cur;
uint64_t lt_overhead_min;
uint64_t lt_overhead_max;
uint64_t lt_overhead_mean;
histo_time_t *lt_overhead_histogram = NULL;
uint64_t lt_syr_overhead_cur;
uint64_t lt_syr_overhead_min;
uint64_t lt_syr_overhead_max;
uint64_t lt_syr_overhead_mean;
histo_time_t *lt_syr_overhead_histogram = NULL;
double syr_rdtsc_overhead_cur;
double syr_rdtsc_overhead_min;
double syr_rdtsc_overhead_max;
double syr_rdtsc_overhead_mean;
histo_time_t *syr_rdtsc_overhead_histogram = NULL;
double syr_clock_gettime_overhead_cur;
double syr_clock_gettime_overhead_min;
double syr_clock_gettime_overhead_max;
double syr_clock_gettime_overhead_mean;
histo_time_t *syr_clock_gettime_overhead_histogram = NULL;
uint64_t cycles_start;
uint64_t cycles_stop;
uint64_t cycles_diff;
uint64_t cycles_diff_max = 0;
struct timespec start;
struct timespec stop;
#endif
cpuf = get_cpu_freq_GHz();
cpu_mhz_syr = estimate_MHz_syr();
printf("\n\ncpuf %f - cpu_mhz_syr %f\n\n", cpuf, cpu_mhz_syr);
#if CALIB_RT_INTRUMENTATION
/* ********************************************************************************************** */
/* CALIBRATION */
/* ********************************************************************************************** */
/* *************************************************************
Laurent Thomas instrumentation overhead
*/
printf("\nCalibrating OAI Realtime Instrumentation (Laurent Thomas imp.)\n");
calib_loop_count = CALIB_LOOP_CNT;
initRefTimes(lt_instru_calib); // Laurent Thomas realtime instrumentation calibration measurments
lt_overhead_min = 1000;
lt_overhead_max = 0;
lt_overhead_mean = 0;
lt_overhead_histogram = histogram_init( lt_overhead_histogram );
while(calib_loop_count)
{
pickTime(lt_start);
// asm volatile(""); // Nop instruction
usleep(CALIB_USLEEP);
lt_overhead_cur = updateTimes( readTime(lt_start),
&lt_instru_calib,
CALIB_LOOP_CNT,
"Laurent Thomas realtime instrumentation calibration measurments");
lt_overhead_mean += lt_overhead_cur;
if ( lt_overhead_max < lt_overhead_cur )
lt_overhead_max = lt_overhead_cur;
if ( lt_overhead_min > lt_overhead_cur )
lt_overhead_min = lt_overhead_cur;
histogram_store_value( lt_overhead_histogram, (double)lt_overhead_cur );
if ( calib_loop_count%CALIB_LOOP_REPORT_PERIOD == 0 )
{
printf("\r%d/%d",calib_loop_count,CALIB_LOOP_CNT);
fflush(stdout);
}
calib_loop_count--;
}
lt_overhead_mean = lt_overhead_mean/CALIB_LOOP_CNT;
// printMeas("\nLaurent Thomas realtime instrumentation calibration measurments",&lt_instru_calib,CALIB_LOOP_CNT);
/* *************************************************************
Laurent Thomas instrumentation overhead
*/
printf("\nCalibrating OAI Realtime Instrumentation - SYRTEM revisited\n");
calib_loop_count = CALIB_LOOP_CNT;
initRefTimes(lt_instru_calib_syr); // Laurent Thomas realtime instrumentation calibration measurments
lt_syr_overhead_min = 1000;
lt_syr_overhead_max = 0;
lt_syr_overhead_mean = 0;
lt_syr_overhead_histogram = histogram_init( lt_syr_overhead_histogram );
while(calib_loop_count)
{
pickTime_syr(lt_start_syr);
// asm volatile(""); // Nop instruction
usleep(CALIB_USLEEP);
lt_syr_overhead_cur = updateTimes_syr(readTime(lt_start_syr), &lt_instru_calib_syr, CALIB_LOOP_CNT, "Laurent Thomas realtime instrumentation calibration measurments (SYRTEM Update)");
lt_syr_overhead_mean += lt_syr_overhead_cur;
if ( lt_syr_overhead_max < lt_syr_overhead_cur )
lt_syr_overhead_max = lt_syr_overhead_cur;
if ( lt_syr_overhead_min > lt_syr_overhead_cur )
lt_syr_overhead_min = lt_syr_overhead_cur;
histogram_store_value( lt_syr_overhead_histogram, (double)lt_syr_overhead_cur );
if ( calib_loop_count%CALIB_LOOP_REPORT_PERIOD == 0 )
{
printf("\r%d/%d",calib_loop_count,CALIB_LOOP_CNT);
fflush(stdout);
}
calib_loop_count--;
}
lt_syr_overhead_mean = lt_syr_overhead_mean / CALIB_LOOP_CNT;
// printMeas("\nLaurent Thomas realtime instrumentation calibration measurments (SYRTEM Update)",&lt_instru_calib_syr,CALIB_LOOP_CNT);
/* *************************************************************
SYRTEM RDTSC instrumentation overhead
*/
printf("\nCalibrating SYRTEM RDTSC Realtime Instrumentation\n");
calib_loop_count = CALIB_LOOP_CNT;
syr_rdtsc_overhead_min = 1000;
syr_rdtsc_overhead_max = 0;
syr_rdtsc_overhead_mean = 0;
syr_rdtsc_overhead_histogram = histogram_init( syr_rdtsc_overhead_histogram );
while(calib_loop_count)
{
cycles_start = pickCyclesStart();
// asm volatile(""); // Nop instruction
usleep(CALIB_USLEEP);
cycles_stop = pickCyclesStop();
cycles_diff = cycles_stop - cycles_start;
if(cycles_diff_max < cycles_diff)
cycles_diff_max = cycles_diff;
syr_rdtsc_overhead_cur = (double)cycles_diff/cpu_mhz_syr;
syr_rdtsc_overhead_mean += syr_rdtsc_overhead_cur;
if ( syr_rdtsc_overhead_max < syr_rdtsc_overhead_cur )
syr_rdtsc_overhead_max = syr_rdtsc_overhead_cur;
if ( syr_rdtsc_overhead_min > syr_rdtsc_overhead_cur )
syr_rdtsc_overhead_min = syr_rdtsc_overhead_cur;
histogram_store_value( syr_rdtsc_overhead_histogram, (double)syr_rdtsc_overhead_cur );
if ( calib_loop_count%CALIB_LOOP_REPORT_PERIOD == 0 )
{
printf("\r%d/%d",calib_loop_count,CALIB_LOOP_CNT);
fflush(stdout);
}
calib_loop_count--;
}
syr_rdtsc_overhead_mean = syr_rdtsc_overhead_mean / CALIB_LOOP_CNT;
// printf("\nSYRTEM RDTSV realtime instrumentation calibration : cycles_diff_max %ld - tsc_duration_max %f us\n ", cycles_diff_max, tsc_duration_max);
/* *************************************************************
SYRTEM Clock_gettime MONOTONIC instrumentation overhead
*/
printf("\nCalibrating SYRTEM clock_gettime Realtime Instrumentation\n");
calib_loop_count = CALIB_LOOP_CNT;
syr_clock_gettime_overhead_min = 1000;
syr_clock_gettime_overhead_max = 0;
syr_clock_gettime_overhead_mean = 0;
syr_clock_gettime_overhead_histogram = histogram_init( syr_clock_gettime_overhead_histogram );
while(calib_loop_count)
{
clock_gettime( CLOCK_MONOTONIC, &start );
// asm volatile(""); // Nop instruction
usleep(CALIB_USLEEP);
clock_gettime( CLOCK_MONOTONIC, &stop );
syr_clock_gettime_overhead_cur = TIMESPEC_TO_DOUBLE_US( get_timespec_diff( &start, &stop ) );
syr_clock_gettime_overhead_mean += syr_clock_gettime_overhead_cur;
if ( syr_clock_gettime_overhead_max < syr_clock_gettime_overhead_cur )
syr_clock_gettime_overhead_max = syr_clock_gettime_overhead_cur;
if ( syr_clock_gettime_overhead_min > syr_clock_gettime_overhead_cur )
syr_clock_gettime_overhead_min = syr_clock_gettime_overhead_cur;
histogram_store_value( syr_clock_gettime_overhead_histogram, (double)syr_clock_gettime_overhead_cur );
if ( calib_loop_count%CALIB_LOOP_REPORT_PERIOD == 0 )
{
printf("\r%d/%d",calib_loop_count,CALIB_LOOP_CNT);
fflush(stdout);
}
calib_loop_count--;
}
syr_clock_gettime_overhead_mean = syr_clock_gettime_overhead_mean / CALIB_LOOP_CNT;
// printf("\nSYRTEM clock_gettime MONOTONIC calibration : clock_gettime duration_max %f us\n ", max);
printf("\n");
printf("OAI LT RT profiling overhead (it. %d) (us) : max=%8ld - mean=%8ld - min=%8ld\n",
CALIB_LOOP_CNT,
lt_overhead_max, lt_overhead_mean, lt_overhead_min);
printf("OAI SYR RT profiling overhead (it. %d) (us) : max=%8ld - mean=%8ld - min=%8ld\n",
CALIB_LOOP_CNT,
lt_syr_overhead_max, lt_syr_overhead_mean, lt_syr_overhead_min);
printf("SYR RDTSC profiling overhead (it. %d) (us) : max=%8.3f - mean=%8.3f - min=%8.3f\n",
CALIB_LOOP_CNT,
syr_rdtsc_overhead_max, syr_rdtsc_overhead_mean, syr_rdtsc_overhead_min);
printf("SYR clock_gettime profiling overhead (it. %d) (us): max=%8.3f - mean=%8.3f - min=%8.3f\n",
CALIB_LOOP_CNT,
syr_clock_gettime_overhead_max, syr_clock_gettime_overhead_mean, syr_clock_gettime_overhead_min);
return 0;
#endif
rxtx_proc = calloc( RX_NB_TH, sizeof( UE_rxtx_proc_t* ) );
for (i=0 ; i<RX_NB_TH; i++)
rxtx_proc[i] = calloc( 1, sizeof( UE_rxtx_proc_t ) );
th_wake_histogram = histogram_init( th_wake_histogram );
init_UE( 1 );
while ( !oai_exit )
sleep( 1 );
return 0;
}
double estimate_MHz_syr(void)
{
//copied blantantly from http://www.cs.helsinki.fi/linux/linux-kernel/2001-37/0256.html
/*
* $Id: MHz.c,v 1.4 2001/05/21 18:58:01 davej Exp $
* This file is part of x86info.
* (C) 2001 Dave Jones.
*
* Licensed under the terms of the GNU GPL License version 2.
*
* Estimate CPU MHz routine by Andrea Arcangeli <andrea@suse.de>
* Small changes by David Sterba <sterd9am@ss1000.ms.mff.cuni.cz>
*
*/
struct timespec start;
struct timespec stop;
unsigned long long int cycles[2]; /* must be 64 bit */
double microseconds; /* total time taken */
/* get this function in cached memory */
cycles[0] = rdtsc ();
clock_gettime( CLOCK_REALTIME, &start );
/* we don't trust that this is any specific length of time */
usleep (100000);
cycles[1] = rdtsc ();
clock_gettime( CLOCK_REALTIME, &stop );
microseconds = TIMESPEC_TO_DOUBLE_US( get_timespec_diff( &start, &stop ) );
unsigned long long int elapsed = 0;
if (cycles[1] < cycles[0])
{
//printf("c0 = %llu c1 = %llu",cycles[0],cycles[1]);
elapsed = UINT32_MAX - cycles[0];
elapsed = elapsed + cycles[1];
//printf("c0 = %llu c1 = %llu max = %llu elapsed=%llu\n",cycles[0], cycles[1], UINT32_MAX,elapsed);
}
else
{
elapsed = cycles[1] - cycles[0];
// printf("\nc0 = %llu c1 = %llu elapsed=%llu\n",cycles[0], cycles[1],elapsed);
}
double mhz = elapsed / microseconds;
//printf("%llg MHz processor (estimate). diff cycles=%llu microseconds=%llu \n", mhz, elapsed, microseconds);
//printf("%g elapsed %llu microseconds %llu\n",mhz, elapsed, microseconds);
return (mhz);
}
/** TSC Timestamp references
- http://oliveryang.net/2015/09/pitfalls-of-TSC-usage/#312-tsc-sync-behaviors-on-smp-system
- https://www.intel.com/content/www/us/en/embedded/training/ia-32-ia-64-benchmark-code-execution-paper.html
- https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3b-part-2-manual.pdf
- http://blog.tinola.com/?e=54
- https://stackoverflow.com/questions/24392392/getting-tsc-frequency-from-proc-cpuinfo !! warning on turbo
- https://gist.github.com/nfarring/1624742
- https://www.lmax.com/blog/staff-blogs/2015/10/25/time-stamp-counters/
- https://github.com/cyring/CoreFreq
- https://patchwork.kernel.org/patch/9438133/ --> TSC_ADJUST - to be checked
-> https://software.intel.com/en-us/forums/software-tuning-performance-optimization-platform-monitoring/topic/388964
- https://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=11&ved=0ahUKEwjwpJbem5DVAhWBDpoKHXv0Dt04ChAWCCIwAA&url=https%3A%2F%2Fsigarra.up.pt%2Ffeup%2Fpt%2Fpub_geral.show_file%3Fpi_gdoc_id%3D809041&usg=AFQjCNFHTMjmjWMG6QSVnLDflEoU0RavKw&cad=rja
- https://unix4lyfe.org/benchmarking/
- https://stackoverflow.com/questions/27693145/rdtscp-versus-rdtsc-cpuid
- https://github.com/dterei/tsc/blob/master/tsc.h
- https://software.intel.com/en-us/forums/intel-isa-extensions/topic/280440
- https://stackoverflow.com/questions/19941588/wrong-clock-cycle-measurements-with-rdtsc
*/
static __inline__ uint64_t pickCyclesStart(void) {
unsigned cycles_low, cycles_high;
asm volatile( "CPUID\n\t" // serialize
"RDTSC\n\t" // read clock
"MOV %%edx, %0\n\t"
"MOV %%eax, %1\n\t"
: "=r" (cycles_high), "=r" (cycles_low)
:: "%rax", "%rbx", "%rcx", "%rdx" );
return ((uint64_t) cycles_high << 32) | cycles_low;
}
static __inline__ uint64_t pickCyclesStop(void) {
uint32_t eax, edx;
__asm__ __volatile__("rdtscp"
: "=a" (eax), "=d" (edx)
:
: "%ecx", "memory");
return (((uint64_t)edx << 32) | eax);
}
/**************************************************************************************
EXTRACT from openair1/PHY/TOOLS/time_meas.c
***************************************************************************************/
double get_cpu_freq_GHz(void) {
time_stats_t ts = {0};
reset_meas(&ts);
ts.trials++;
ts.in = rdtsc_oai();
sleep(1);
ts.diff = (rdtsc_oai()-ts.in);
cpu_freq_GHz = (double)ts.diff/1000000000;
printf("CPU Freq is %f \n", cpu_freq_GHz);
return cpu_freq_GHz;
}
/**************************************************************************************
SYRTEM STATISTICS HELPER
***************************************************************************************/
histo_time_t *histogram_init(histo_time_t *histo )
{
int i = 0;
double max_val = HISTOGRAM_MIN_VALUE + HISTOGRAM_STEP;
histo = calloc( HISTOGRAM_SIZE, sizeof( histo_time_t ) );
if ( histo == NULL ) {
printf( "ERROR allocating histogram structure !\n" );
return NULL;
}
for ( i = 0; i < HISTOGRAM_SIZE; i++ ) {
histo[i].max = max_val;
max_val += HISTOGRAM_STEP;
}
return histo;
}
void histogram_store_value( histo_time_t *histo, double value )
{
int i = 0;
for ( i = 0; i < HISTOGRAM_SIZE; i++ ) {
if ( histo[i].max >= value || ( i + 1 ) == HISTOGRAM_SIZE ) {
histo[i].count++;
break;
}
}
}
void histogram_save_in_csv( histo_time_t *histo , char *file_sufix)
{
char *csv_filename;
char month[3], day[3], hour[3], min[3], sec[3];
time_t curr_time;
struct tm *datetime;
curr_time = time( NULL );
datetime = localtime( &curr_time );
csv_filename = calloc( sizeof( char ), 64 );
if ( csv_filename == NULL ) {
return;
}
memset( csv_filename, 0x00, 64 );
memset( month, 0x00, 3 );
memset( day, 0x00, 3 );
memset( hour, 0x00, 3 );
memset( min, 0x00, 3 );
memset( sec, 0x00, 3 );
/* Month. */
if ( datetime->tm_mon < 9 )
snprintf( month, 3, "0%d", datetime->tm_mon + 1 );
else
snprintf( month, 3, "%d", datetime->tm_mon + 1 );
/* Day. */
if ( datetime->tm_mday < 10 )
snprintf( day, 3, "0%d", datetime->tm_mday );
else
snprintf( day, 3, "%d", datetime->tm_mday );
/* Hour. */
if ( datetime->tm_hour < 10 )
snprintf( hour, 3, "0%d", datetime->tm_hour );
else
snprintf( hour, 3, "%d", datetime->tm_hour );
/* Minute. */
if ( datetime->tm_min < 10 )
snprintf( min, 3, "0%d", datetime->tm_min );
else
snprintf( min, 3, "%d", datetime->tm_min );
/* Second. */
if ( datetime->tm_sec < 10 )
snprintf( sec, 3, "0%d", datetime->tm_sec );
else
snprintf( sec, 3, "%d", datetime->tm_sec );
snprintf( csv_filename, 63, "ADRV9371_ZC706_HISTO_UEtoRXTX_%d%s%s%s%s%s_%s.csv",
datetime->tm_year + 1900, month, day, hour, min, sec, file_sufix );
FILE *fp;
int i = 0;
int min_val = 0;
fp = fopen( csv_filename, "w+" );
fprintf( fp, "range;count\n" );
for ( i = 0; i < HISTOGRAM_SIZE; i++ ) {
if ( i + 1 == HISTOGRAM_SIZE )
fprintf( fp, "%u+;%u\n", min_val, histo[i].count );
else
fprintf( fp, "%u-%.0f;%u\n", min_val, histo[i].max, histo[i].count );
min_val = histo[i].max;
}
fclose( fp );
}
static struct timespec get_timespec_diff(
struct timespec *start,
struct timespec *stop )
{
struct timespec result;
if ( ( stop->tv_nsec - start->tv_nsec ) < 0 ) {
result.tv_sec = stop->tv_sec - start->tv_sec - 1;
result.tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
}
else {
result.tv_sec = stop->tv_sec - start->tv_sec;
result.tv_nsec = stop->tv_nsec - start->tv_nsec;
}
return result;
}
static void measure_time (
struct timespec *start,
struct timespec *stop,
uint8_t START,
uint16_t PRINT_INTERVAL )
{
static double max = 0;
static double min = 0;
static double total = 0;
static int count = 0;
if ( START ) {
clock_gettime( CLOCK_REALTIME, start );
}
else {
clock_gettime( CLOCK_REALTIME, stop );
struct timespec diff;
double current = 0;
diff = get_timespec_diff( start, stop );
// current = ( (double)diff.tv_sec * 1000000 ) + ( (double)diff.tv_nsec / 1000 );
current = TIMESPEC_TO_DOUBLE_US( diff );
if ( current > max ) {
max = current;
}
if ( min == 0 || current < min ) {
min = current;
}
total += current;
histogram_store_value( th_wake_histogram, current );
if ( count % PRINT_INTERVAL == 0 && count != 0 ) {
double avg = total / ( count + 1 );
printf( "[%d] Current : %.2lf µs, Min : %.2lf µs, Max : %.2lf µs, Moy : %.2lf µs\n",
count, current, min, max, avg );
}
count++;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment