diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container
index a2bb8112fc..e395973b25 100644
--- a/ci-scripts/Jenkinsfile-GitLab-Container
+++ b/ci-scripts/Jenkinsfile-GitLab-Container
@@ -380,6 +380,29 @@ pipeline {
}
}
}
+ stage ("VRT-Sim-Test-5G") {
+ when { expression {do5Gtest || do5GUeTest} }
+ steps {
+ script {
+ triggerSlaveJob ('RAN-VRT-Sim-Test-5G', 'VRT-Sim-Test-5G')
+ }
+ }
+ post {
+ always {
+ script {
+ // Using a unique variable name for each test stage to avoid overwriting on a global variable
+ // due to parallel-time concurrency
+ vrtSim5GStatus = finalizeSlaveJob('RAN-VRT-Sim-Test-5G')
+ }
+ }
+ failure {
+ script {
+ currentBuild.result = 'FAILURE'
+ failingStages += vrtSim5GStatus
+ }
+ }
+ }
+ }
stage ("RF-Sim-Test-5G") {
when { expression {do5Gtest || do5GUeTest} }
steps {
diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml b/ci-scripts/conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml
new file mode 100644
index 0000000000..5cca2b0718
--- /dev/null
+++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml
@@ -0,0 +1,209 @@
+Active_gNBs:
+ - gnb-rfsim
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity: none
+gNBs:
+ ##### Identification parameters:
+ - gNB_ID: 0xe00
+ gNB_name: gnb-rfsim
+ tracking_area_code: 1
+ plmn_list:
+ - mcc: 208
+ mnc: 99
+ mnc_length: 2
+ snssaiList:
+ - sst: 1
+ sd: 0xffffff
+ nr_cellid: 12345678
+ ##### Physical parameters:
+ min_rxtxtime: 6
+ pusch_AntennaPorts: 2
+ pdsch_AntennaPorts_XP: 2
+
+ servingCellConfigCommon:
+ #spCellConfigCommon
+ - physCellId: 0
+ # downlinkConfigCommon
+ #frequencyInfoDL
+ # this is 3300.60 MHz + 53*12*30e-3 MHz = 3319.68
+ absoluteFrequencySSB: 621312
+ # this is 3300.60 MHz
+ dl_absoluteFrequencyPointA: 620040
+ #scs-SpecificCarrierList
+ dl_offstToCarrier: 0
+ # subcarrierSpacing
+ # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ dl_subcarrierSpacing: 1
+ dl_carrierBandwidth: 106
+ #initialDownlinkBWP
+ #genericParameters
+ # this is RBstart=0,L=106 (275*(L-1))+RBstart
+ initialDLBWPlocationAndBandwidth: 28875
+ # subcarrierSpacing
+ # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ initialDLBWPsubcarrierSpacing: 1
+ #pdcch-ConfigCommon
+ initialDLBWPcontrolResourceSetZero: 11
+ initialDLBWPsearchSpaceZero: 0
+ #uplinkConfigCommon
+ #frequencyInfoUL
+ ul_frequencyBand: 78
+ #scs-SpecificCarrierList
+ ul_offstToCarrier: 0
+ # subcarrierSpacing
+ # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ ul_subcarrierSpacing: 1
+ ul_carrierBandwidth: 106
+ pMax: 20
+ #initialUplinkBWP
+ #genericParameters
+ initialULBWPlocationAndBandwidth: 28875
+ # subcarrierSpacing
+ # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ initialULBWPsubcarrierSpacing: 1
+ #rach-ConfigCommon
+ #rach-ConfigGeneric
+ prach_ConfigurationIndex: 98
+ #prach_msg1_FDM
+ #0 = one, 1=two, 2=four, 3=eight
+ prach_msg1_FDM: 0
+ prach_msg1_FrequencyStart: 0
+ zeroCorrelationZoneConfig: 12
+ preambleReceivedTargetPower: -104
+ #preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
+ preambleTransMax: 6
+ #powerRampingStep
+ # 0=dB0,1=dB2,2=dB4,3=dB6
+ powerRampingStep: 1
+ #ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
+ #1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
+ ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR: 4
+ #one (0..15) 4,8,12,16,...60,64
+ ssb_perRACH_OccasionAndCB_PreamblesPerSSB: 15
+ #ra_ContentionResolutionTimer
+ #(0..7) 8,16,24,32,40,48,56,64
+ ra_ContentionResolutionTimer: 7
+ rsrp_ThresholdSSB: 19
+ #prach-RootSequenceIndex_PR
+ #1 = 839, 2 = 139
+ prach_RootSequenceIndex_PR: 2
+ prach_RootSequenceIndex: 1
+ # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
+ msg1_SubcarrierSpacing: 1
+ # restrictedSetConfig
+ # 0=unrestricted, 1=restricted type A, 2=restricted type B
+ restrictedSetConfig: 0
+ msg3_DeltaPreamble: 1
+ p0_NominalWithGrant: -90
+
+ # pucch-ConfigCommon setup :
+ # pucchGroupHopping
+ # 0 = neither, 1= group hopping, 2=sequence hopping
+ pucchGroupHopping: 0
+ hoppingId: 40
+ p0_nominal: -90
+ ssb_PositionsInBurst_Bitmap: 1
+ # ssb_periodicityServingCell
+ # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
+ ssb_periodicityServingCell: 2
+
+ # dmrs_TypeA_position
+ # 0 = pos2, 1 = pos3
+ dmrs_TypeA_Position: 0
+
+ # subcarrierSpacing
+ # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ subcarrierSpacing: 1
+
+ #tdd-UL-DL-ConfigurationCommon
+ # subcarrierSpacing
+ # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
+ referenceSubcarrierSpacing: 1
+
+ # pattern1
+ # dl_UL_TransmissionPeriodicity
+ # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
+ dl_UL_TransmissionPeriodicity: 6
+ nrofDownlinkSlots: 7
+ nrofDownlinkSymbols: 6
+ nrofUplinkSlots: 2
+ nrofUplinkSymbols: 4
+ ssPBCH_BlockPower: -25
+ SCTP:
+ SCTP_INSTREAMS: 2
+ SCTP_OUTSTREAMS: 2
+
+ ##### AMF parameters:
+ amf_ip_address:
+ - ipv4: 192.168.71.132
+
+ NETWORK_INTERFACES:
+ GNB_IPV4_ADDRESS_FOR_NG_AMF: 192.168.71.140
+ GNB_IPV4_ADDRESS_FOR_NGU: 192.168.71.140
+ GNB_PORT_FOR_S1U: 2152 # Spec 2152
+
+
+MACRLCs:
+ - num_cc: 1
+ tr_s_preference: local_L1
+ tr_n_preference: local_RRC
+ pusch_TargetSNRx10: 200
+ pucch_TargetSNRx10: 200
+
+L1s:
+ - num_cc: 1
+ tr_n_preference: local_mac
+ prach_dtx_threshold: 200
+ # pucch0_dtx_threshold = 150;
+
+RUs:
+ - local_rf: yes
+ nb_tx: 2
+ nb_rx: 2
+ att_tx: 0
+ att_rx: 0
+ bands: [78]
+ max_pdschReferenceSignalPower: -27
+ max_rxgain: 75
+ eNB_instances: [0]
+ sf_extension: 0
+
+security:
+ # preferred ciphering algorithms
+ # the first one of the list that an UE supports in chosen
+ # valid values: nea0, nea1, nea2, nea3
+ ciphering_algorithms: [nea0]
+
+ # preferred integrity algorithms
+ # the first one of the list that an UE supports in chosen
+ # valid values: nia0, nia1, nia2, nia3
+ integrity_algorithms: [nia2, nia0]
+
+ # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter
+ # what 'ciphering_algorithms' configures; same thing for 'drb_integrity'
+ drb_ciphering: yes
+ drb_integrity: no
+
+log_config:
+ global_log_level: info
+ hw_log_level: info
+ phy_log_level: info
+ mac_log_level: info
+ rlc_log_level: info
+ pdcp_log_level: info
+ rrc_log_level: info
+ ngap_log_level: debug
+ f1ap_log_level: debug
+
+
+channelmod:
+ max_chan: 10
+ modellist: DefaultChannelList
+ DefaultChannelList:
+ - model_name: server_tx_channel_model
+ type: AWGN
+ ploss_dB: 0
+ noise_power_dB: -100
+ forgetfact: 0
+ offset: 0
+ ds_tdl: 0
diff --git a/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml b/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml
new file mode 100644
index 0000000000..a9488007d7
--- /dev/null
+++ b/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml
@@ -0,0 +1,20 @@
+uicc0:
+ imsi: 208990100001100
+ key: fec86ba6eb707ed08905757b1bb44b8f
+ opc: C42449363BBAD02B66D16BC975D77CC1
+ dnn: oai
+ nssai_sst: 1
+
+thread-pool: "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"
+
+channelmod:
+ max_chan: 10;
+ modellist: DefaultChannelList
+ DefaultChannelList:
+ - model_name: client_tx_channel_model
+ type: AWGN
+ ploss_dB: 0
+ noise_power_dB: -100
+ forgetfact: 0
+ offset: 0
+ ds_tdl: 0
diff --git a/ci-scripts/xml_files/container_5g_vrtsim_chanmod.xml b/ci-scripts/xml_files/container_5g_vrtsim_chanmod.xml
new file mode 100644
index 0000000000..6bd16eff1f
--- /dev/null
+++ b/ci-scripts/xml_files/container_5g_vrtsim_chanmod.xml
@@ -0,0 +1,140 @@
+
+
+ vrtsim-5gnr-chanmod
+ Monolithic gNB vrtsim + chanmod
+ wrench
+
+ 111111
+ 800813
+ 000011
+ 000012
+ 000013
+ 020011
+ 020012
+ 030011
+ 030012
+ 100011
+ 222222
+
+
+
+
+ Pull_Local_Registry
+ Pull Images from Local Registry
+ localhost
+ oai-gnb oai-nr-ue
+
+
+ Create_Workspace
+ Create new Workspace
+ localhost
+
+
+ Deploy_Object
+ Deploy OAI 5G CoreNetwork
+ localhost
+ ci-scripts/yaml_files/5g_vrtsim_chanmod
+ mysql oai-amf oai-smf oai-upf oai-ext-dn
+
+
+
+ Deploy_Object
+ Deploy OAI 5G gNB+UE RF sim SA
+ localhost
+ ci-scripts/yaml_files/5g_vrtsim_chanmod
+ oai-gnb oai-nr-ue
+
+
+
+ Attach_UE
+ Attach OAI UE (Wait for IP)
+ rfsim5g_ue
+ localhost
+
+
+
+ Ping
+ Ping ext-dn from NR-UE
+ rfsim5g_ue
+ localhost
+ rfsim5g_ext_dn
+ localhost
+ -c 20 -i 0.25
+ 5
+
+
+
+ Ping
+ Ping NR-UE from ext-dn
+ rfsim5g_ext_dn
+ localhost
+ rfsim5g_ue
+ localhost
+ -c 20 -i 0.25
+ 5
+
+
+
+ Iperf
+ Iperf (DL/3Mbps/UDP)(20 sec)
+ -u -b 3M -t 20 -R
+ rfsim5g_ue
+ localhost
+ rfsim5g_ext_dn
+ localhost
+ 5
+ 90
+
+
+
+ Iperf
+ Iperf (UL/1Mbps/UDP)(20 sec)
+ -u -b 1M -t 20
+ rfsim5g_ue
+ localhost
+ rfsim5g_ext_dn
+ localhost
+ 5
+ 90
+
+
+
+ Undeploy_Object
+ true
+ Undeploy all OAI 5G stack
+ localhost
+ ci-scripts/yaml_files/5g_vrtsim_chanmod
+ 1,0,0,0
+ 1,0,0,0
+
+
+
+ Clean_Test_Server_Images
+ true
+ Clean Test Images on Test Server
+ localhost
+ oai-gnb oai-nr-ue
+
+
+
diff --git a/ci-scripts/xml_files/container_5g_vrtsim_chanmod_gh.xml b/ci-scripts/xml_files/container_5g_vrtsim_chanmod_gh.xml
new file mode 100644
index 0000000000..3d3fd6ee59
--- /dev/null
+++ b/ci-scripts/xml_files/container_5g_vrtsim_chanmod_gh.xml
@@ -0,0 +1,141 @@
+
+
+ vrtsim-5gnr-chanmod-gh
+ Monolithic gNB vrtsim + chanmod
+ wrench
+
+ 111111
+ 800813
+ 000011
+ 000012
+ 000013
+ 020011
+ 020012
+ 030011
+ 030012
+ 100011
+ 222222
+
+
+
+
+ Pull_Local_Registry
+ Pull Images from Local Registry
+ localhost
+ oai-gnb oai-nr-ue
+ arm_
+
+
+ Create_Workspace
+ Create new Workspace
+ localhost
+
+
+ Deploy_Object
+ Deploy OAI 5G CoreNetwork
+ localhost
+ ci-scripts/yaml_files/5g_vrtsim_chanmod
+ mysql oai-amf oai-smf oai-upf oai-ext-dn
+
+
+
+ Deploy_Object
+ Deploy OAI 5G gNB+UE RF sim SA
+ localhost
+ ci-scripts/yaml_files/5g_vrtsim_chanmod
+ oai-gnb oai-nr-ue
+
+
+
+ Attach_UE
+ Attach OAI UE (Wait for IP)
+ rfsim5g_ue
+ localhost
+
+
+
+ Ping
+ Ping ext-dn from NR-UE
+ rfsim5g_ue
+ localhost
+ rfsim5g_ext_dn
+ localhost
+ -c 20 -i 0.25
+ 5
+
+
+
+ Ping
+ Ping NR-UE from ext-dn
+ rfsim5g_ext_dn
+ localhost
+ rfsim5g_ue
+ localhost
+ -c 20 -i 0.25
+ 5
+
+
+
+ Iperf
+ Iperf (DL/3Mbps/UDP)(30 sec)
+ -u -b 3M -t 30 -R
+ rfsim5g_ue
+ localhost
+ rfsim5g_ext_dn
+ localhost
+ 5
+ 90
+
+
+
+ Iperf
+ Iperf (UL/1Mbps/UDP)(30 sec)
+ -u -b 1M -t 30
+ rfsim5g_ue
+ localhost
+ rfsim5g_ext_dn
+ localhost
+ 5
+ 90
+
+
+
+ Undeploy_Object
+ true
+ Undeploy all OAI 5G stack
+ localhost
+ ci-scripts/yaml_files/5g_vrtsim_chanmod
+ 1,0,0,0
+ 1,0,0,0
+
+
+
+ Clean_Test_Server_Images
+ true
+ Clean Test Images on Test Server
+ localhost
+ oai-gnb oai-nr-ue
+
+
+
diff --git a/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml b/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml
new file mode 100644
index 0000000000..503161fc62
--- /dev/null
+++ b/ci-scripts/yaml_files/5g_vrtsim_chanmod/docker-compose.yaml
@@ -0,0 +1,163 @@
+services:
+ mysql:
+ container_name: "rfsim5g-mysql"
+ image: mysql:8.0
+ init: true
+ volumes:
+ - ../5g_rfsimulator/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql
+ - ../5g_rfsimulator/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh
+ environment:
+ - TZ=Europe/Paris
+ - MYSQL_DATABASE=oai_db
+ - MYSQL_USER=test
+ - MYSQL_PASSWORD=test
+ - MYSQL_ROOT_PASSWORD=linux
+ healthcheck:
+ test: /bin/bash -c "/tmp/mysql-healthcheck.sh"
+ interval: 10s
+ timeout: 5s
+ start_period: 10s
+ start_interval: 500ms
+ retries: 30
+ networks:
+ public_net:
+ ipv4_address: 192.168.71.131
+ oai-amf:
+ container_name: "rfsim5g-oai-amf"
+ image: oaisoftwarealliance/oai-amf:v2.1.10
+ environment:
+ - TZ=Europe/paris
+ volumes:
+ - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-amf/etc/config.yaml
+ depends_on:
+ - mysql
+ networks:
+ public_net:
+ ipv4_address: 192.168.71.132
+ oai-smf:
+ container_name: "rfsim5g-oai-smf"
+ image: oaisoftwarealliance/oai-smf:v2.1.10
+ environment:
+ - TZ=Europe/Paris
+ volumes:
+ - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-smf/etc/config.yaml
+ depends_on:
+ - oai-amf
+ networks:
+ public_net:
+ ipv4_address: 192.168.71.133
+ oai-upf:
+ container_name: "rfsim5g-oai-upf"
+ image: oaisoftwarealliance/oai-upf:v2.1.10
+ init: true
+ environment:
+ - TZ=Europe/Paris
+ volumes:
+ - ../5g_rfsimulator/mini_nonrf_config.yaml:/openair-upf/etc/config.yaml
+ depends_on:
+ - oai-smf
+ cap_add:
+ - NET_ADMIN
+ - SYS_ADMIN
+ cap_drop:
+ - ALL
+ privileged: true
+ networks:
+ public_net:
+ ipv4_address: 192.168.71.134
+ interface_name: eth0
+ traffic_net:
+ ipv4_address: 192.168.72.134
+ interface_name: eth1
+ oai-ext-dn:
+ privileged: true
+ container_name: rfsim5g-oai-ext-dn
+ image: oaisoftwarealliance/trf-gen-cn5g:latest
+ init: true
+ entrypoint: /bin/bash -c \
+ "iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE;"\
+ "ip route add 12.1.1.0/24 via 192.168.72.134 dev eth0; sleep infinity"
+ depends_on:
+ - oai-upf
+ networks:
+ traffic_net:
+ ipv4_address: 192.168.72.135
+ healthcheck:
+ test: /bin/bash -c "ping -c 2 192.168.72.134"
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ start_period: 10s
+ start_interval: 500ms
+ oai-gnb:
+ image: ${REGISTRY-oaisoftwarealliance/}${GNB_IMG:-oai-gnb}:${TAG:-develop}
+ container_name: rfsim5g-oai-gnb
+ cap_drop:
+ - ALL
+ environment:
+ USE_ADDITIONAL_OPTIONS: -E --log_config.global_log_options level,nocolor,time --device.name vrtsim --vrtsim.role server --vrtsim.chanmod 1
+ depends_on:
+ - oai-ext-dn
+ networks:
+ public_net:
+ ipv4_address: 192.168.71.140
+ volumes:
+ - ../../conf_files/gnb.sa.band78.106prb.vrtsim.2x2.yaml:/opt/oai-gnb/etc/gnb.yaml
+ - tmp_data:/tmp/
+ healthcheck:
+ test: /bin/bash -c "pgrep nr-softmodem"
+ interval: 10s
+ timeout: 5s
+ start_period: 10s
+ start_interval: 500ms
+ retries: 5
+ ipc: host
+ oai-nr-ue:
+ image: ${REGISTRY-oaisoftwarealliance/}${NRUE_IMG:-oai-nr-ue}:${TAG:-develop}
+ container_name: rfsim5g-oai-nr-ue
+ cap_drop:
+ - ALL
+ cap_add:
+ - NET_ADMIN # for interface bringup
+ - NET_RAW # for ping
+ environment:
+ USE_ADDITIONAL_OPTIONS: -E -r 106 --numerology 1 --band 78 -C 3619200000 --ssb 516 --uicc0.imsi 208990100001100 --log_config.global_log_options level,nocolor,time --device.name vrtsim
+ depends_on:
+ - oai-gnb
+ networks:
+ public_net:
+ ipv4_address: 192.168.71.150
+ devices:
+ - /dev/net/tun:/dev/net/tun
+ volumes:
+ - ../../conf_files/nrue.vrtsim.chanmod.yaml:/opt/oai-nr-ue/etc/nr-ue.yaml
+ - tmp_data:/tmp/
+ healthcheck:
+ test: /bin/bash -c "pgrep nr-uesoftmodem"
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ start_period: 10s
+ start_interval: 500ms
+ ipc: host
+
+networks:
+ public_net:
+ driver: bridge
+ name: rfsim5g-oai-public-net
+ ipam:
+ config:
+ - subnet: 192.168.71.128/26
+ driver_opts:
+ com.docker.network.bridge.name: "rfsim5g-public"
+ traffic_net:
+ driver: bridge
+ name: rfsim5g-oai-traffic-net
+ ipam:
+ config:
+ - subnet: 192.168.72.128/26
+ driver_opts:
+ com.docker.network.bridge.name: "rfsim5g-traffic"
+
+volumes:
+ tmp_data:
diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c
index 9e678a5305..2b40f2f05d 100644
--- a/radio/vrtsim/vrtsim.c
+++ b/radio/vrtsim/vrtsim.c
@@ -54,7 +54,7 @@
typedef enum { ROLE_SERVER = 1, ROLE_CLIENT } role;
#define MAX_NUM_ANTENNAS_TX 4
-#define MAX_CHANNEL_LENGTH (1 << 20)
+#define SAVED_SAMPLES_LEN 256
#define ROLE_CLIENT_STRING "client"
#define ROLE_SERVER_STRING "server"
@@ -125,9 +125,6 @@ typedef struct {
int client_num_rx_antennas;
} vrtsim_state_t;
-// Sample history for channel impulse response
-static c16_t saved_samples[MAX_NUM_ANTENNAS_TX][MAX_CHANNEL_LENGTH] __attribute__((aligned(32))) = {0};
-
static void histogram_add(histogram_t *histogram, double diff)
{
histogram->num_samples++;
@@ -375,6 +372,9 @@ typedef struct {
int nbAnt;
int flags;
int aarx;
+ int batch_size;
+ int num_batches;
+ c16_t saved_samples[MAX_NUM_ANTENNAS_TX][SAVED_SAMPLES_LEN];
} channel_modelling_args_t;
static void perform_channel_modelling(void *arg)
@@ -417,49 +417,55 @@ static void perform_channel_modelling(void *arg)
}
}
- for (int aatx = 0; aatx < nb_tx_ant; aatx++) {
- c16_t *previous_samples = saved_samples[aatx];
- for (int i = 0; i < nsamps; i++) {
- cf_t *impulse_response = channel_impulse_response_p[aatx];
- for (int l = 0; l < channel_desc->channel_length; l++) {
- int idx = i - l;
- // TODO: Use AVX2 for this
- c16_t tx_input = idx >= 0 ? input_samples[aatx][idx]
- : previous_samples[(channel_modelling_args->timestamp + i + idx) % MAX_CHANNEL_LENGTH];
- samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i;
- samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i;
+ for (int batch_index = 0; batch_index < channel_modelling_args->num_batches; batch_index++) {
+ int start_sample = batch_index * channel_modelling_args->batch_size;
+ int num_samples = min(channel_modelling_args->batch_size, nsamps - start_sample);
+ if (start_sample >= nsamps) {
+ break;
+ }
+ for (int aatx = 0; aatx < nb_tx_ant; aatx++) {
+ for (int i = start_sample; i < start_sample + num_samples; i++) {
+ cf_t *impulse_response = channel_impulse_response_p[aatx];
+ for (int l = 0; l < channel_desc->channel_length; l++) {
+ int idx = i - l;
+ // TODO: Use AVX2 for this
+ c16_t tx_input = idx >= 0 ? input_samples[aatx][idx]
+ : channel_modelling_args->saved_samples[aatx][SAVED_SAMPLES_LEN + idx];
+ samples[i].r += tx_input.r * impulse_response[l].r - tx_input.i * impulse_response[l].i;
+ samples[i].i += tx_input.i * impulse_response[l].r + tx_input.r * impulse_response[l].i;
+ }
}
}
- }
- // Convert to c16_t
- c16_t samples_out[aligned_nsamps] __attribute__((aligned(64)));
-#if defined(__AVX512F__)
- for (int i = 0; i < aligned_nsamps / 8; i++) {
- simde__m512 *in = (simde__m512 *)&samples[i * 8];
- simde__m256i *out = (simde__m256i *)&samples_out[i * 8];
- *out = simde_mm512_cvtsepi32_epi16(simde_mm512_cvtps_epi32(*in));
- }
-#elif defined(__AVX2__)
- for (int i = 0; i < aligned_nsamps / 4; i++) {
- simde__m256 *in = (simde__m256 *)&samples[i * 4];
- simde__m128i *out = (simde__m128i *)&samples_out[i * 4];
- *out = simde_mm256_cvtsepi32_epi16(simde_mm256_cvtps_epi32(*in));
- }
-#else
- for (int i = 0; i < nsamps; i++) {
- samples_out[i].r = lroundf(samples[i].r);
- samples_out[i].i = lroundf(samples[i].i);
- }
-#endif
+ // Convert to c16_t
+ c16_t samples_out[aligned_nsamps] __attribute__((aligned(64)));
+ #if defined(__AVX512F__)
+ for (int i = 0; i < aligned_nsamps / 8; i++) {
+ simde__m512 *in = (simde__m512 *)&samples[i * 8];
+ simde__m256i *out = (simde__m256i *)&samples_out[i * 8];
+ *out = simde_mm512_cvtsepi32_epi16(simde_mm512_cvtps_epi32(*in));
+ }
+ #elif defined(__AVX2__)
+ for (int i = 0; i < aligned_nsamps / 4; i++) {
+ simde__m256 *in = (simde__m256 *)&samples[i * 4];
+ simde__m128i *out = (simde__m128i *)&samples_out[i * 4];
+ *out = simde_mm256_cvtsepi32_epi16(simde_mm256_cvtps_epi32(*in));
+ }
+ #else
+ for (int i = 0; i < nsamps; i++) {
+ samples_out[i].r = lroundf(samples[i].r);
+ samples_out[i].i = lroundf(samples[i].i);
+ }
+ #endif
- vrtsim_write_internal(channel_modelling_args->vrtsim_state,
- channel_modelling_args->timestamp,
- samples_out,
- channel_modelling_args->nsamps,
- aarx,
- channel_modelling_args->flags,
- aarx);
+ vrtsim_write_internal(channel_modelling_args->vrtsim_state,
+ channel_modelling_args->timestamp,
+ samples_out,
+ channel_modelling_args->nsamps,
+ aarx,
+ channel_modelling_args->flags,
+ aarx);
+ }
}
static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state,
@@ -469,7 +475,13 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state,
int nbAnt,
int flags)
{
- AssertFatal(nbAnt < MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX);
+ // Sample history for channel impulse response
+ static c16_t saved_samples[MAX_NUM_ANTENNAS_TX][SAVED_SAMPLES_LEN] __attribute__((aligned(32))) = {0};
+ // Indicates what samples are saves in saved_samples
+ static openair0_timestamp last_timestamp = 0;
+ const int batch_size = 4096;
+
+ AssertFatal(nbAnt <= MAX_NUM_ANTENNAS_TX, "Number of antennas %d exceeds maximum %d\n", nbAnt, MAX_NUM_ANTENNAS_TX);
for (int aarx = 0; aarx < vrtsim_state->peer_info.num_rx_antennas; aarx++) {
notifiedFIFO_elt_t *task = newNotifiedFIFO_elt(sizeof(channel_modelling_args_t), 0, NULL, perform_channel_modelling);
channel_modelling_args_t *args = (channel_modelling_args_t *)NotifiedFifoData(task);
@@ -479,28 +491,45 @@ static int vrtsim_write_with_chanmod(vrtsim_state_t *vrtsim_state,
args->nbAnt = nbAnt;
args->flags = flags;
args->aarx = aarx;
+ args->batch_size = batch_size;
+ args->num_batches = (nsamps + batch_size - 1) / batch_size;
for (int i = 0; i < nbAnt; i++) {
args->samples[i] = samplesVoid[i];
}
+
+ // Fill in saved_samples
+ size_t gap_samples = timestamp - last_timestamp;
+ if (gap_samples > 0) {
+ size_t gap_samples_needed = min(SAVED_SAMPLES_LEN, gap_samples);
+ for (int aatx = 0; aatx < nbAnt; aatx++) {
+ memset(&args->saved_samples[aatx][SAVED_SAMPLES_LEN - gap_samples_needed], 0, sizeof(c16_t) * gap_samples_needed);
+ if (gap_samples < SAVED_SAMPLES_LEN) {
+ size_t samples_from_saved = SAVED_SAMPLES_LEN - gap_samples_needed;
+ memcpy(&args->saved_samples[aatx][0], &saved_samples[aatx][SAVED_SAMPLES_LEN - samples_from_saved], sizeof(c16_t) * samples_from_saved);
+ }
+ }
+ } else {
+ for (int aatx = 0; aatx < nbAnt; aatx++)
+ memcpy(&args->saved_samples[aatx][0], saved_samples[aatx], sizeof(c16_t) * SAVED_SAMPLES_LEN);
+ }
+ memcpy(args->saved_samples, saved_samples, sizeof(saved_samples));
pushNotifiedFIFO(&vrtsim_state->channel_modelling_actors[aarx].fifo, task);
}
- int start_index = timestamp % MAX_CHANNEL_LENGTH;
- int end_index = min(start_index + nsamps, MAX_CHANNEL_LENGTH);
- int cp_nsamps = end_index - start_index;
- for (int aatx = 0; aatx < nbAnt; aatx++) {
- c16_t *samples = (c16_t *)samplesVoid[aatx];
- memcpy(&saved_samples[aatx][start_index], &samples[0], sizeof(c16_t) * cp_nsamps);
- }
- if (end_index < start_index + nsamps) {
- // wrap around condition, write at beginning of buffer
- cp_nsamps = nsamps - cp_nsamps; // remaining samples
- start_index = 0;
+ // Save samples for next round
+ if (nsamps < SAVED_SAMPLES_LEN) {
for (int aatx = 0; aatx < nbAnt; aatx++) {
- c16_t *samples = (c16_t *)samplesVoid[aatx];
- memcpy(&saved_samples[aatx][start_index], &samples[0], sizeof(c16_t) * cp_nsamps);
+ memmove(&saved_samples[aatx][0], &saved_samples[aatx][nsamps], sizeof(c16_t) * (SAVED_SAMPLES_LEN - nsamps));
+ memcpy(&saved_samples[aatx][SAVED_SAMPLES_LEN - nsamps], samplesVoid[aatx], sizeof(c16_t) * nsamps);
+ }
+ } else {
+ for (int aatx = 0; aatx < nbAnt; aatx++) {
+ c16_t* samples = (c16_t*)samplesVoid[aatx];
+ memcpy(saved_samples[aatx], &samples[nsamps - SAVED_SAMPLES_LEN], sizeof(c16_t) * (SAVED_SAMPLES_LEN));
}
}
+
+ last_timestamp = timestamp + nsamps;
return nsamps;
}
@@ -630,6 +659,7 @@ static int vrtsim_set_freq(openair0_device *device, openair0_config_t *openair0_
__attribute__((__visibility__("default"))) int device_init(openair0_device *device, openair0_config_t *openair0_cfg)
{
+ randominit();
vrtsim_state_t *vrtsim_state = calloc_or_fail(1, sizeof(vrtsim_state_t));
vrtsim_readconfig(vrtsim_state);
LOG_I(HW,