diff --git a/.ci/docker/uhd-builder-ubuntu1804.Dockerfile b/.ci/docker/uhd-builder-ubuntu1804.Dockerfile
index 9b86e06f74..5ac62457a0 100644
--- a/.ci/docker/uhd-builder-ubuntu1804.Dockerfile
+++ b/.ci/docker/uhd-builder-ubuntu1804.Dockerfile
@@ -27,7 +27,6 @@ RUN apt-get update && \
sudo \
# Install UHD dependencies
abi-dumper \
- cmake \
doxygen \
dpdk \
libboost-all-dev \
@@ -85,3 +84,10 @@ RUN python3 -m pip install \
click-plugins \
zmq \
scipy
+
+RUN wget https://cmake.org/files/v3.12/cmake-3.12.4-Linux-x86_64.tar.gz -O /tmp/cmake.tar.gz && \
+ (echo "486edd6710b5250946b4b199406ccbf8f567ef0e23cfe38f7938b8c78a2ffa5f /tmp/cmake.tar.gz" | sha256sum --check --status ) && \
+ tar -zxvf /tmp/cmake.tar.gz -C /opt && \
+ cp -r /opt/cmake-3.12.4-Linux-x86_64/bin/* /usr/local/bin/ && \
+ cp -r /opt/cmake-3.12.4-Linux-x86_64/share/* /usr/local/share/ && \
+ rm /tmp/cmake.tar.gz
diff --git a/.ci/templates/job-analyze-changeset.yml b/.ci/templates/job-analyze-changeset.yml
index 20cee51f71..c8877796c2 100644
--- a/.ci/templates/job-analyze-changeset.yml
+++ b/.ci/templates/job-analyze-changeset.yml
@@ -40,7 +40,7 @@ jobs:
$AGENT_TEMPDIRECTORY/ac_venv/$VENV_BIN_DIR/python3 tools/changeset_testlist.py \
--target-branch $TARGET_BRANCH \
--set-azdo-var UhdTestList \
- --list-tests $EXTRA_ARGS
+ --list-tests --verbose $EXTRA_ARGS
name: gen_testlist
displayName: Generate Test-List
env:
diff --git a/.ci/templates/job-uhd-rf-tests-pebbles.yml b/.ci/templates/job-uhd-rf-tests-pebbles.yml
index f1e6d12ba5..b52e1aa93c 100644
--- a/.ci/templates/job-uhd-rf-tests-pebbles.yml
+++ b/.ci/templates/job-uhd-rf-tests-pebbles.yml
@@ -37,8 +37,8 @@ jobs:
devType: 'n3xx'
devModel: 'n310'
devName: pebbles-n310-0
- devSerial: '3176DDF'
- devHostname: 'ni-n3xx-3176DDF'
+ devSerial: '$(n310_devSerial)'
+ devHostname: 'ni-n3xx-$(n310_devSerial)'
devBus: 'ip'
devAddr: '192.168.40.17'
sfpAddrs: '192.168.10.17,192.168.40.17'
diff --git a/.ci/templates/job-uhd-streaming-tests-beauty.yml b/.ci/templates/job-uhd-streaming-tests-beauty.yml
index 0aaac1a03e..8c7fd8546d 100644
--- a/.ci/templates/job-uhd-streaming-tests-beauty.yml
+++ b/.ci/templates/job-uhd-streaming-tests-beauty.yml
@@ -46,55 +46,58 @@ jobs:
beauty-X310-0:
dutName: 'beauty-X310-0'
dutType: 'X310'
- dutAddr: '192.168.10.3'
- dutSecondAddr: '192.168.20.3'
+ dutAddr: '$(x310_dutAddr)'
+ dutSecondAddr: '$(x310_dutSecondAddr)'
dutFPGA: 'XG'
dutNameId: ''
dutNumRecvFrames: ''
dutNumSendFrames: ''
jtagSerial: '251635138E94'
- sfpInt0: 'ens4f0'
- sfpInt1: 'ens4f1'
+ sfpInt0: '$(x310_sfpInt0)'
+ sfpInt1: '$(x310_sfpInt1)'
# beauty-X410-0 X4_200:
# dutName: 'beauty-X410-0'
# dutFamily: 'x4xx'
# dutType: 'x410'
- # dutAddr: '192.168.10.2'
- # dutSecondAddr: '192.168.20.2'
+ # dutAddr: '$(x410_dutAddr)'
+ # dutSecondAddr: '$(x410_dutSecondAddr)'
# dutFPGA:'X4_200'
# dutNameId: ''
+ # dutEmbeddedImagesArtifact: 'x4xx-images'
+ # uartSerial: '$(x410_uartSerial)'
# dutNumRecvFrames: ''
# dutNumSendFrames: ''
- # sfpInt0: 'ens6f0'
- # sfpInt1: 'ens6f1'
+ # sfpInt0: '$(x410_sfpInt0)'
+ # sfpInt1: '$(x410_sfpInt1)'
beauty-X410-0 CG_400:
dutName: 'beauty-X410-0'
dutFamily: 'x4xx'
dutType: 'x410'
- dutAddr: '192.168.110.2'
- dutSecondAddr: '192.168.120.2'
+ dutAddr: '$(x410_dutAddr)'
+ dutSecondAddr: '$(x410_dutSecondAddr)'
dutFPGA: 'CG_400'
dutNameId: ''
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '2516351E2C9A'
+ uartSerial: '$(x410_uartSerial)'
dutNumRecvFrames: ''
dutNumSendFrames: ''
- sfpInt0: 'ens6f0'
- sfpInt1: 'ens6f1'
+ sfpInt0: '$(x410_sfpInt0)'
+ sfpInt1: '$(x410_sfpInt1)'
beauty-X410-0 UC_200:
dutName: 'beauty-X410-0'
dutFamily: 'x4xx'
dutType: 'x410'
- dutAddr: '192.168.120.2'
- dutSecondAddr: '192.168.120.2'
+ # UC image: device is reachable only via dutSecondAddr
+ dutAddr: '$(x410_dutSecondAddr)'
+ dutSecondAddr: '$(x410_dutSecondAddr)'
dutFPGA: 'UC_200'
dutNameId: ''
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '2516351E2C9A'
+ uartSerial: '$(x410_uartSerial)'
dutNumRecvFrames: ''
dutNumSendFrames: ''
- sfpInt0: 'ens6f0'
- sfpInt1: 'ens6f1'
+ sfpInt0: '$(x410_sfpInt0)'
+ sfpInt1: '$(x410_sfpInt1)'
# beauty-E320-0:
# dutName: 'beauty-E320-0'
# dutType: 'E320'
diff --git a/.ci/templates/job-uhd-streaming-tests-x440.yml b/.ci/templates/job-uhd-streaming-tests-x440.yml
index c76500a9de..a57779ae42 100644
--- a/.ci/templates/job-uhd-streaming-tests-x440.yml
+++ b/.ci/templates/job-uhd-streaming-tests-x440.yml
@@ -39,27 +39,27 @@ jobs:
dutName: 'streaming-X440-0'
dutFamily: 'x4xx'
dutType: 'x440'
- dutAddr: '192.168.110.2'
- dutSecondAddr: '192.168.120.2'
+ dutAddr: '$(x440_dutAddr)'
+ dutSecondAddr: '$(x440_dutSecondAddr)'
dutFPGA: 'CG_400'
dutNameId: ''
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '251635271947'
+ uartSerial: '$(x440_uartSerial)'
dutNumRecvFrames: ''
dutNumSendFrames: ''
- sfpInt0: 'enp1s0f0np0'
- sfpInt1: 'enp1s0f1np1'
+ sfpInt0: '$(x440_sfpInt0)'
+ sfpInt1: '$(x440_sfpInt1)'
X440-0 CG_1600:
dutName: 'streaming-X440-0'
dutFamily: 'x4xx'
dutType: 'x440'
- dutAddr: '192.168.110.2'
- dutSecondAddr: '192.168.120.2'
+ dutAddr: '$(x440_dutAddr)'
+ dutSecondAddr: '$(x440_dutSecondAddr)'
dutFPGA: 'CG_1600'
dutNameId: ''
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '251635271947'
+ uartSerial: '$(x440_uartSerial)'
dutNumRecvFrames: ''
dutNumSendFrames: ''
- sfpInt0: 'enp1s0f0np0'
- sfpInt1: 'enp1s0f1np1'
+ sfpInt0: '$(x440_sfpInt0)'
+ sfpInt1: '$(x440_sfpInt1)'
diff --git a/.ci/templates/stages-uhd-pipeline.yml b/.ci/templates/stages-uhd-pipeline.yml
index fa444e8236..e5425840b1 100644
--- a/.ci/templates/stages-uhd-pipeline.yml
+++ b/.ci/templates/stages-uhd-pipeline.yml
@@ -253,21 +253,16 @@ stages:
cache_sstate: ${{ parameters.cache_sstate }}
cache_downloads: False
machines:
- ${{ if parameters.build_e310_sg1 }}:
- e310_sg1:
- machineName: e310_sg1
- ${{ if parameters.build_e310_sg3 }}:
- e310_sg3:
- machineName: e310_sg3
- ${{ if parameters.build_e320 }}:
- e320:
- machineName: e320
- ${{ if parameters.build_n3xx }}:
- n3xx:
- machineName: n3xx
- ${{ if parameters.build_x4xx }}:
- x4xx:
- machineName: x4xx
+ - ${{ if parameters.build_e310_sg1 }}:
+ - e310_sg1
+ - ${{ if parameters.build_e310_sg3 }}:
+ - e310_sg3
+ - ${{ if parameters.build_e320 }}:
+ - e320
+ - ${{ if parameters.build_n3xx }}:
+ - n3xx
+ - ${{ if parameters.build_x4xx }}:
+ - x4xx
auto_conf: $AUTO_CONF
run_from_external_repo: true
prebuild_steps:
@@ -380,7 +375,7 @@ stages:
installer: nsis
- stage: devtest_uhd_x3xx_b2xx_stage
- displayName: devtest UHD x3xx b2xx
+ displayName: Dev Test UHD x3xx b2xx
dependsOn:
- build_uhd_stage_linux
- analyze_changeset
@@ -404,7 +399,7 @@ stages:
testDevices: 'x3xx,b2xx'
- stage: devtest_uhd_n3xx_e320_stage
- displayName: devtest UHD n3xx e320
+ displayName: Dev Test UHD n3xx e320
dependsOn:
- build_uhd_stage_linux
- build_uhd_embedded_system_images
@@ -428,8 +423,8 @@ stages:
fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
testDevices: 'n3xx,e320'
-- stage: test_uhd_x4xx_stage
- displayName: Test UHD x4xx
+- stage: test_uhd_x4xx_sdrtest0_stage
+ displayName: RF Test UHD x4xx sdr-test0
dependsOn:
- build_uhd_stage_linux
- build_uhd_embedded_system_images
@@ -463,6 +458,32 @@ stages:
testOS: ubuntu1804
uhdFpgaArtifactSource: uhd_fpga_pipeline
fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+
+- stage: test_uhd_x4xx_pebbles_stage
+ displayName: RF Test UHD x4xx pebbles
+ dependsOn:
+ - build_uhd_stage_linux
+ - build_uhd_embedded_system_images
+ - build_gnuradio_stage_linux
+ - analyze_changeset
+ # This will make $(UhdTestList) available to jobs/steps/tasks, but not for the
+ # condition.
+ variables:
+ UhdTestList: $[stageDependencies.analyze_changeset.analyze.outputs['gen_testlist.UhdTestList']]
+ condition: >
+ and(
+ succeeded(),
+ or(
+ ${{ parameters.skip_analyze_changeset }},
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.rf.all'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.rf.x4xx'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.rf.x410'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.rf.x440'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'devtest.all'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'devtest.x410'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'devtest.x440')
+ ))
+ jobs:
- template: tests/job-uhd-x410-hardware-tests-pebbles.yml
parameters:
testOS: ubuntu1804
@@ -475,6 +496,32 @@ stages:
uhdFpgaArtifactSource: uhd_fpga_pipeline
fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
testLength: ${{ parameters.testLength }}
+
+- stage: test_uhd_x4xx_saison_stage
+ displayName: RF Test UHD x4xx saison
+ dependsOn:
+ - build_uhd_stage_linux
+ - build_uhd_embedded_system_images
+ - build_gnuradio_stage_linux
+ - analyze_changeset
+ # This will make $(UhdTestList) available to jobs/steps/tasks, but not for the
+ # condition.
+ variables:
+ UhdTestList: $[stageDependencies.analyze_changeset.analyze.outputs['gen_testlist.UhdTestList']]
+ condition: >
+ and(
+ succeeded(),
+ or(
+ ${{ parameters.skip_analyze_changeset }},
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.rf.all'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.rf.x4xx'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.rf.x410'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.rf.x440'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'devtest.all'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'devtest.x410'),
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'devtest.x440')
+ ))
+ jobs:
- template: tests/job-uhd-x440-hardware-tests-saison.yml
parameters:
testOS: ubuntu2204
@@ -484,7 +531,7 @@ stages:
testLength: ${{ parameters.testLength }}
- stage: test_uhd_rf_test_stage
- displayName: Run rf tests n3xx
+ displayName: RF Test UHD n3xx pebbles
dependsOn:
- analyze_changeset
- build_uhd_stage_linux
@@ -509,8 +556,8 @@ stages:
testOS: ubuntu1804
testDevices: 'n3xx'
-- stage: test_streaming_stage
- displayName: Test UHD Streaming
+- stage: test_streaming_beauty_stage
+ displayName: Test UHD Streaming beauty
dependsOn:
- analyze_changeset
- build_uhd_stage_linux
@@ -533,6 +580,24 @@ stages:
uhdFpgaArtifactSource: uhd_fpga_pipeline
fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
testLength: ${{ parameters.testLength }}
+
+- stage: test_streaming_x440_stage
+ displayName: Test UHD Streaming x440
+ dependsOn:
+ - analyze_changeset
+ - build_uhd_stage_linux
+ - build_uhd_embedded_system_images
+ condition: >
+ and(
+ succeeded('build_uhd_stage_linux'),
+ succeeded('build_uhd_embedded_system_images'),
+ ${{ parameters.run_streaming_tests }},
+ or(
+ ${{ parameters.skip_analyze_changeset }},
+ contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'hw.streaming')
+ )
+ )
+ jobs:
- template: job-uhd-streaming-tests-x440.yml
parameters:
testOS: ubuntu2204
diff --git a/.ci/templates/tests/job-uhd-x410-hardware-tests-pebbles.yml b/.ci/templates/tests/job-uhd-x410-hardware-tests-pebbles.yml
index d9a1d3f55d..c66b18f225 100644
--- a/.ci/templates/tests/job-uhd-x410-hardware-tests-pebbles.yml
+++ b/.ci/templates/tests/job-uhd-x410-hardware-tests-pebbles.yml
@@ -38,7 +38,7 @@ jobs:
devtestPattern: 'x4x0'
dutFPGA: 'X4_200'
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '2516351DDCC0'
+ uartSerial: $(x410_uartSerial)
pipelineAgent: pebbles-agent-1
pytestAtsConfig: uhd_oss_ats
pytestDUT: 'x410'
diff --git a/.ci/templates/tests/job-uhd-x410-hardware-tests-sdr-test0.yml b/.ci/templates/tests/job-uhd-x410-hardware-tests-sdr-test0.yml
index af91d82572..757b826aec 100644
--- a/.ci/templates/tests/job-uhd-x410-hardware-tests-sdr-test0.yml
+++ b/.ci/templates/tests/job-uhd-x410-hardware-tests-sdr-test0.yml
@@ -31,6 +31,6 @@ jobs:
devtestPattern: 'x410'
dutFPGA: 'X4_200'
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '2516351FE64E'
+ uartSerial: $(x410_uartSerial)
pytestDUT: 'x410'
pipelineAgent: sdr-test0
diff --git a/.ci/templates/tests/job-uhd-x440-hardware-tests-pebbles.yml b/.ci/templates/tests/job-uhd-x440-hardware-tests-pebbles.yml
index 18c87ef194..2bbd9b5848 100644
--- a/.ci/templates/tests/job-uhd-x440-hardware-tests-pebbles.yml
+++ b/.ci/templates/tests/job-uhd-x440-hardware-tests-pebbles.yml
@@ -38,7 +38,7 @@ jobs:
devtestPattern: 'x4x0'
dutFPGA: 'X4_400'
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '251635284FC9'
+ uartSerial: $(x440_uartSerial)
pipelineAgent: pebbles-agent-1
pytestAtsConfig: uhd_oss_ats
pytestDUT: 'x440'
diff --git a/.ci/templates/tests/job-uhd-x440-hardware-tests-saison.yml b/.ci/templates/tests/job-uhd-x440-hardware-tests-saison.yml
index 543b26a71d..824b2c45e2 100644
--- a/.ci/templates/tests/job-uhd-x440-hardware-tests-saison.yml
+++ b/.ci/templates/tests/job-uhd-x440-hardware-tests-saison.yml
@@ -45,7 +45,7 @@ jobs:
devtestPattern: 'x4x0'
dutFPGA: 'X4_400'
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '251635284FCA'
+ uartSerial: $(x440_uartSerial)
pipelineAgent: saison-agent-1
pytestAtsConfig: saison_multichan_ats
pytestDUT: 'x440'
diff --git a/.ci/templates/tests/job-uhd-x440-hardware-tests-sdr-test0.yml b/.ci/templates/tests/job-uhd-x440-hardware-tests-sdr-test0.yml
index 8e83c90009..61a22ed569 100644
--- a/.ci/templates/tests/job-uhd-x440-hardware-tests-sdr-test0.yml
+++ b/.ci/templates/tests/job-uhd-x440-hardware-tests-sdr-test0.yml
@@ -32,6 +32,6 @@ jobs:
master_clock_rate: '125e6'
dutFPGA: 'X4_400'
dutEmbeddedImagesArtifact: 'x4xx-images'
- uartSerial: '25163525D2B3'
+ uartSerial: $(x440_uartSerial)
pytestDUT: 'x440'
pipelineAgent: sdr-test0
diff --git a/.ci/templates/tests/pebbles-labgrid/exporter-conf/exporter.yaml b/.ci/templates/tests/pebbles-labgrid/exporter-conf/exporter.yaml
index 57aae25c51..693f6413bc 100755
--- a/.ci/templates/tests/pebbles-labgrid/exporter-conf/exporter.yaml
+++ b/.ci/templates/tests/pebbles-labgrid/exporter-conf/exporter.yaml
@@ -2,13 +2,13 @@ pebbles-n310-0-group:
console-scu:
cls: USBSerialPort
match:
- ID_SERIAL: 'Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_0097D46F'
+ ID_SERIAL: 'Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_00B56895'
ID_USB_INTERFACE_NUM: '01'
speed: 115200
console-linux:
cls: USBSerialPort
match:
- ID_SERIAL: 'Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_0097D46F'
+ ID_SERIAL: 'Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_00B56895'
ID_USB_INTERFACE_NUM: '00'
speed: 115200
USBSDMuxDevice:
diff --git a/.ci/uhd-hardware-test-weekly-pipeline.yml b/.ci/uhd-hardware-test-weekly-pipeline.yml
new file mode 100644
index 0000000000..a785b8766b
--- /dev/null
+++ b/.ci/uhd-hardware-test-weekly-pipeline.yml
@@ -0,0 +1,150 @@
+trigger: none
+schedules:
+- cron: '0 13 * * 6'
+ displayName: Weekly Test
+ branches:
+ include:
+ - master
+ always: true
+
+pr: none
+
+parameters:
+- name: fpga_imgs_source
+ type: string
+ values:
+ - 'Filesytem/Images Downloader'
+ - 'FPGA Pipeline'
+ - 'FPGA Pipeline PR'
+ displayName: FPGA Images Source
+ default: 'FPGA Pipeline'
+- name: testLength
+ type: string
+ values:
+ - 'smoke'
+ - 'full'
+ - 'stress'
+ default: 'smoke'
+
+variables:
+ - name: uhd_fpga_artifact_source
+ ${{ if eq(parameters.fpga_imgs_source, 'FPGA Pipeline PR') }}:
+ value: uhd_fpga_pr_pipeline
+ ${{ else }}:
+ value: uhd_fpga_pipeline
+
+resources:
+ pipelines:
+ - pipeline: uhd_mono_pipeline
+ source: 'uhddev mono pipeline'
+ branch: master
+ - pipeline: usrp-kas-pipeline
+ source: 'usrp-kas'
+ branch: kirkstone
+ - pipeline: uhd_fpga_pipeline
+ source: 'uhddev fpga pipeline'
+ branch: master
+ - pipeline: uhd_fpga_pr_pipeline
+ source: 'uhddev fpga pipeline PR'
+ branch: master
+ repositories:
+ - repository: meta-ettus
+ type: github
+ name: EttusResearch/meta-ettus-dev
+ endpoint: EttusResearch
+ ref: kirkstone
+ - repository: gr-ettus
+ type: github
+ name: EttusResearch/gr-ettusdev
+ endpoint: EttusResearch
+ ref: maint-3.8-uhd4.0
+ - repository: ettus-rts
+ type: github
+ endpoint: EttusResearch
+ name: EttusResearch/ettus-rts
+ ref: master
+
+stages:
+- stage: test_uhd_devtest_stage
+ displayName: Test UHD Devtest
+ dependsOn: []
+ jobs:
+ - template: templates/tests/job-uhd-x410-hardware-tests-sdr-test0.yml
+ parameters:
+ testOS: 'ubuntu1804'
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+ - template: templates/tests/job-uhd-x440-hardware-tests-sdr-test0.yml
+ parameters:
+ testOS: 'ubuntu1804'
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+ - template: templates/job-uhd-devtest-rhombus.yml
+ parameters:
+ testOS: 'ubuntu2004'
+ uhdSrcDir: $(Build.SourcesDirectory)
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+
+- stage: test_streaming_stage
+ displayName: Test UHD Streaming
+ dependsOn: []
+ jobs:
+ - template: templates/job-uhd-streaming-tests-beauty.yml
+ parameters:
+ testOS: 'ubuntu2004'
+ uhdSrcDir: $(Build.SourcesDirectory)/uhddev
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+ testLength: ${{ parameters.testLength }}
+ - template: templates/job-uhd-streaming-tests-x440.yml
+ parameters:
+ testOS: 'ubuntu2204'
+ uhdSrcDir: $(Build.SourcesDirectory)/uhddev
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+ testLength: ${{ parameters.testLength }}
+
+- stage: test_rf_tests_stage
+ displayName: Test UHD RF Tests
+ dependsOn: []
+ jobs:
+ - template: templates/job-uhd-rf-tests-pebbles.yml
+ parameters:
+ testOS: 'ubuntu1804'
+ uhdSrcDir: $(Build.SourcesDirectory)/uhddev
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+ - template: templates/tests/job-uhd-x410-hardware-tests-pebbles.yml
+ parameters:
+ testOS: 'ubuntu1804'
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+ testLength: ${{ parameters.testLength }}
+ - template: templates/tests/job-uhd-x440-hardware-tests-pebbles.yml
+ parameters:
+ testOS: 'ubuntu1804'
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+ testLength: ${{ parameters.testLength }}
+
+- stage: test_uhd_phase_tests
+ displayName: Test UHD Phase Tests
+ dependsOn: []
+ jobs:
+ - template: templates/tests/job-uhd-x440-hardware-tests-saison.yml
+ parameters:
+ testOS: 'ubuntu2204'
+ uhdArtifactSource: uhd_mono_pipeline
+ uhdFpgaArtifactSource: ${{ variables.uhd_fpga_artifact_source }}
+ fpga_imgs_source: ${{ parameters.fpga_imgs_source }}
+ testLength: ${{ parameters.testLength }}
+ extra_rf_test_args: --test_selector test_rx_phase_coherence.py test_tx_phase_coherence.py
diff --git a/CHANGELOG b/CHANGELOG
index 58fb24c131..9e7d785bf2 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,69 @@
Change Log for Releases
==============================
+## Next Release
+* New Features:
+ - Image Builder:
+ - Add GRC support. This allows designing RFNoC bitfiles from GNU Radio
+ Companion (GRC).
+ - Improve clock connection checks and checks for duplicate connections.
+ - Improve IO port compat check (e.g., check if wire widths match).
+ - Allow default clocks in domain checks.
+ - Simplify image core YAMLs by better usage of RADIO_NIPC parameter.
+ - Improve parameter resolution.
+ - Add --SYNTH and --CHECK options.
+ - Add support for building an FPGA image using multiple parallel jobs and
+ unique seeds with repeat_fpga_build.py and the --fpga-jobs option.
+ - rfnoc-gain (OOT RFNoC example):
+ - Overhaul directory structure, and rename to rfnoc-gain from
+ rfnoc-example.
+ - Simplify dynamic loading of OOT DLLs by using the new modules.d feature.
+ - Add CE clock support to gain block. This enables the example on X4x0.
+ - Add a GNU Radio subdirectory with examples of how to run the gain block
+ in GNU Radio.
+ - Add rfnoc_modtool. This is a command line utility to help design OOT RFNoC
+ blocks.
+ - RFNoC:
+ - Add tune requests. This allows tuning a complete graph as known from
+ multi_usrp instead of single blocks individually.
+ - multi_usrp:
+ - Add Python bindings for get_user_settings_iface()
+ - General UHD:
+ - Add modules.d support
+* Bug Fixes
+ - E320: Ensure consistent sequencing when powering on/off GPSDO
+ - RFNoC:
+ - RFNoC DDC/DUC block (used in all Gen-3 USRPs and X410): Fix fractional
+ frequency offset.
+ - Fix AIS/spp calculation (e.g., for connecting FFT blocks).
+ - Image Builder:
+ - Fix colors
+ - Fix error message for missing control SEP
+ - Improve error reporting for invalid connections
+ - Accept ~ and ~user on command line
+ - Fix deprecated usage of yaml.load()
+ - Ensure correct device tree files generation when chosing a custom build
+ directory
+ - rfnoc_modtool:
+ - Fix generation of noc_shells
+ - General UHD:
+ - Fix compatibility with DPDK >= 22.11
+ - Fix compiler warnings for better compatibility with C++ 17 and 20.
+ - Add logic for loading uhd.dll from the correct path for Windows with Python3.8+.
+ - Remove duplicate results from find
+ - Release GIL when calling find from Python which improves response time for large setups.
+ - MPM:
+ - Allow images without RF frontend (will only be initialized if FPGA reports availability)
+* Validated OS Environments
+ (Versions for build and runtime dependencies can be determined from the
+ docker container definitions in the UHD repository at .ci/docker/...)
+ - Linux:
+ - Ubuntu: bionic (18.04), focal (20.04), jammy (22.04), noble (24.04)
+ - Fedora: 39, 40, 41
+ - Windows: 10 21H2, 11 21H2
+ - MacOS: Monterey (12.6)
+
+
## 004.007.000.000
* Highlights / Main Changes
- Major updates to rfnoc_image_builder (a98ce26). This change adds support for
diff --git a/fpga/usrp3/tools/utils/repeat_fpga_build.py b/fpga/usrp3/tools/utils/repeat_fpga_build.py
index b38ef35b0a..0003debce5 100755
--- a/fpga/usrp3/tools/utils/repeat_fpga_build.py
+++ b/fpga/usrp3/tools/utils/repeat_fpga_build.py
@@ -202,6 +202,12 @@ def parse_args():
"location (e.g., /tools/Xilinx/Vivado).",
default=None,
)
+ parser.add_argument(
+ "--ignore-warnings",
+ "-W",
+ help="Run build even when there are warnings from the RFNoC image builder",
+ action="store_true",
+ )
parser.add_argument(
"--num",
"-n",
@@ -282,6 +288,7 @@ def rfnoc_image_builder_cmd(
image_core_name,
fpga_dir,
vivado_path,
+ ignore_warnings,
build_num=None,
):
"""
@@ -300,6 +307,8 @@ def rfnoc_image_builder_cmd(
cmd += f"--fpga-dir {fpga_dir} "
if vivado_path:
cmd += f"--vivado-path {vivado_path} "
+ if ignore_warnings:
+ cmd += "--ignore-warnings "
return cmd
@@ -313,6 +322,7 @@ def run_fpga_build(
image_core_name,
fpga_dir,
vivado_path,
+ ignore_warnings,
parallel_builds,
):
"""Performs one iteration of an FPGA build.
@@ -327,6 +337,8 @@ def run_fpga_build(
image_core_name: --image-core-name argument to be passed
fpga_dir: --fpga-dir argument to be passed
vivado_path: --vivado-path argument to be passed
+ ignore_warnings: --ignore-warnings argument to be passed
+ parallel_builds: Indicates if we are doing builds in parallel
Returns:
Status.SUCCESS: The build succeeded
@@ -343,6 +355,7 @@ def run_fpga_build(
image_core_name,
fpga_dir,
vivado_path,
+ ignore_warnings,
cmd_build_num,
)
logging.info(f"Running FPGA build command: {cmd}")
@@ -388,7 +401,9 @@ def run_fpga_build(
return status
-def run_ip_build(ip_jobs, target, image_core, image_core_name, fpga_dir, vivado_path):
+def run_ip_build(
+ ip_jobs, target, image_core, image_core_name, fpga_dir, vivado_path, ignore_warnings
+):
"""Performs the IP build.
This is done separately so that when we do parallel FPGA builds, they don't
@@ -401,13 +416,21 @@ def run_ip_build(ip_jobs, target, image_core, image_core_name, fpga_dir, vivado_
image_core_name: --image-core-name argument to be passed
fpga_dir: --fpga-dir argument to be passed
vivado_path: --vivado-path argument to be passed
+ ignore_warnings: --ignore-warnings argument to be passed
Returns:
0: The IP build succeeded
non-zero: The IP build failed
"""
cmd = rfnoc_image_builder_cmd(
- None, target, image_core, image_core_name, fpga_dir, vivado_path, None
+ None,
+ target,
+ image_core,
+ image_core_name,
+ fpga_dir,
+ vivado_path,
+ ignore_warnings,
+ None,
)
cmd += f" --ip-only --jobs {ip_jobs}"
logging.info(f"Running IP build with command: {cmd}")
@@ -475,6 +498,7 @@ def main():
args.image_core_name,
args.fpga_dir,
args.vivado_path,
+ args.ignore_warnings,
)
if status != Status.SUCCESS:
return status.value
@@ -502,6 +526,7 @@ def main():
args.image_core_name,
args.fpga_dir,
args.vivado_path,
+ args.ignore_warnings,
args.fpga_jobs > 1,
),
)
diff --git a/fpga/usrp3/top/x400/.gitignore b/fpga/usrp3/top/x400/.gitignore
index d96446d270..21b2f49993 100644
--- a/fpga/usrp3/top/x400/.gitignore
+++ b/fpga/usrp3/top/x400/.gitignore
@@ -4,4 +4,3 @@ build-*
*.jou
vivado*.str
ip/*/sim/
-dts/x4*0-version-info.dtsi
diff --git a/fpga/usrp3/top/x400/Makefile b/fpga/usrp3/top/x400/Makefile
index 72be08fa51..6e9f6b1a64 100644
--- a/fpga/usrp3/top/x400/Makefile
+++ b/fpga/usrp3/top/x400/Makefile
@@ -134,24 +134,24 @@ X410_IP: ##Build X410 IP only. Use the -j option to build multiple IP block
X440_IP: ##Build X440 IP only. Use the -j option to build multiple IP blocks simultaneously.
+$(call vivado_ip,X440,$(DEFS) X440=1)
-dts/x410-version-info.dtsi: regmap/x410/versioning_regs_regmap_utils.vh
+$(BUILD_DIR)/x410-version-info.dtsi: regmap/x410/versioning_regs_regmap_utils.vh
tools/parse_versions_for_dts.py \
--input $< --output $@ \
--components fpga,cpld_ifc,db_gpio_ifc,rf_core_100m,rf_core_400m
-dts/x440-version-info.dtsi: regmap/x440/versioning_regs_regmap_utils.vh
+$(BUILD_DIR)/x440-version-info.dtsi: regmap/x440/versioning_regs_regmap_utils.vh
tools/parse_versions_for_dts.py \
--input $< --output $@ \
--components fpga,cpld_ifc,db_gpio_ifc,rf_core_full
# The device tree source file $(BUILD_DIR)/device_tree.dts is generated by the
# RFNoC image builder.
-$(BUILD_DIR)/X410.dts: $(BUILD_DIR)/device_tree.dts dts/x410-version-info.dtsi dts/*.dtsi
+$(BUILD_DIR)/X410.dts: $(BUILD_DIR)/device_tree.dts $(BUILD_DIR)/x410-version-info.dtsi dts/*.dtsi
${CC} -o $@ -C -E -I dts -nostdinc -undef -x assembler-with-cpp -D__DTS__ $<
# The device tree source file $(BUILD_DIR)/device_tree.dts is generated by the
# RFNoC image builder.
-$(BUILD_DIR)/X440.dts: $(BUILD_DIR)/device_tree.dts dts/x440-version-info.dtsi dts/*.dtsi
+$(BUILD_DIR)/X440.dts: $(BUILD_DIR)/device_tree.dts $(BUILD_DIR)/x440-version-info.dtsi dts/*.dtsi
${CC} -o $@ -C -E -I dts -nostdinc -undef -x assembler-with-cpp -D__DTS__ $<
clean: ##Clean up all target build outputs.
diff --git a/fpga/usrp3/top/x400/regmap/radio_ctrlport_regmap_utils.vh b/fpga/usrp3/top/x400/regmap/radio_ctrlport_regmap_utils.vh
index 861752b4a3..4633d97fec 100644
--- a/fpga/usrp3/top/x400/regmap/radio_ctrlport_regmap_utils.vh
+++ b/fpga/usrp3/top/x400/regmap/radio_ctrlport_regmap_utils.vh
@@ -13,6 +13,7 @@
// DB_WINDOW : 0x0 (x4xx_core_common.v)
// RFDC_TIMING_WINDOW : 0x8000 (x4xx_core_common.v)
+ // RF_CORE_WINDOW : 0xA000 (x4xx_core_common.v)
// DIO_WINDOW : 0xC000 (x4xx_core_common.v)
//===============================================================================
@@ -29,7 +30,11 @@
// RFDC_TIMING_WINDOW Window (from x4xx_core_common.v)
localparam RFDC_TIMING_WINDOW = 'h8000; // Window Offset
- localparam RFDC_TIMING_WINDOW_SIZE = 'h4000; // size in bytes
+ localparam RFDC_TIMING_WINDOW_SIZE = 'h2000; // size in bytes
+
+ // RF_CORE_WINDOW Window (from x4xx_core_common.v)
+ localparam RF_CORE_WINDOW = 'hA000; // Window Offset
+ localparam RF_CORE_WINDOW_SIZE = 'h2000; // size in bytes
// DIO_WINDOW Window (from x4xx_core_common.v)
localparam DIO_WINDOW = 'hC000; // Window Offset
diff --git a/fpga/usrp3/top/x400/x4xx.sv b/fpga/usrp3/top/x400/x4xx.sv
index c73b9e9342..80b6e427f1 100644
--- a/fpga/usrp3/top/x400/x4xx.sv
+++ b/fpga/usrp3/top/x400/x4xx.sv
@@ -272,6 +272,7 @@ module x4xx (
`include "regmap/global_regs_regmap_utils.vh"
`include "regmap/versioning_utils.vh"
+ `include "../../lib/rfnoc/core/ctrlport.vh"
//---------------------------------------------------------------------------
@@ -1922,6 +1923,15 @@ module x4xx (
wire [31:0] db_ctrlport_resp_data [0:NUM_DBOARDS-1];
wire [ 1:0] db_ctrlport_resp_status [0:NUM_DBOARDS-1];
+ // RF core ctrlport interface
+ wire rf_core_ctrlport_req_rd [0:NUM_DBOARDS-1];
+ wire rf_core_ctrlport_req_wr [0:NUM_DBOARDS-1];
+ wire [19:0] rf_core_ctrlport_req_addr [0:NUM_DBOARDS-1];
+ wire [31:0] rf_core_ctrlport_req_data [0:NUM_DBOARDS-1];
+ wire rf_core_ctrlport_resp_ack [0:NUM_DBOARDS-1];
+ wire [31:0] rf_core_ctrlport_resp_data [0:NUM_DBOARDS-1];
+ wire [ 1:0] rf_core_ctrlport_resp_status [0:NUM_DBOARDS-1];
+
// GPIO to CPLD ctrlport interface
wire db_to_cpld_ctrlport_req_rd [0:NUM_DBOARDS-1];
wire db_to_cpld_ctrlport_req_wr [0:NUM_DBOARDS-1];
@@ -2162,6 +2172,22 @@ module x4xx (
.version_info (rf_core_version[db_i])
);
end // gen_rf_core_full
+
+ // terminate unused rf core ctrlport interfaces
+ ctrlport_terminator #(
+ .START_ADDRESS (0),
+ .LAST_ADDRESS (2**CTRLPORT_ADDR_W-1)
+ ) pl_terminator (
+ .ctrlport_clk (rfdc_clk[db_i]),
+ .ctrlport_rst (radio_rst[db_i]),
+ .s_ctrlport_req_wr (rf_core_ctrlport_req_wr[db_i]),
+ .s_ctrlport_req_rd (rf_core_ctrlport_req_rd[db_i]),
+ .s_ctrlport_req_addr (rf_core_ctrlport_req_addr[db_i]),
+ .s_ctrlport_req_data (rf_core_ctrlport_req_data[db_i]),
+ .s_ctrlport_resp_ack (rf_core_ctrlport_resp_ack[db_i]),
+ .s_ctrlport_resp_status (rf_core_ctrlport_resp_status[db_i]),
+ .s_ctrlport_resp_data (rf_core_ctrlport_resp_data[db_i])
+ );
end // gen_rf_cores
`ifdef X440
@@ -2975,6 +3001,13 @@ module x4xx (
.m_ctrlport_radio_resp_ack ({ db_ctrlport_resp_ack [1], db_ctrlport_resp_ack [0] }),
.m_ctrlport_radio_resp_status ({ db_ctrlport_resp_status [1], db_ctrlport_resp_status [0] }),
.m_ctrlport_radio_resp_data ({ db_ctrlport_resp_data [1], db_ctrlport_resp_data [0] }),
+ .m_ctrlport_rf_core_req_wr ({ rf_core_ctrlport_req_wr [1], rf_core_ctrlport_req_wr [0] }),
+ .m_ctrlport_rf_core_req_rd ({ rf_core_ctrlport_req_rd [1], rf_core_ctrlport_req_rd [0] }),
+ .m_ctrlport_rf_core_req_addr ({ rf_core_ctrlport_req_addr [1], rf_core_ctrlport_req_addr [0] }),
+ .m_ctrlport_rf_core_req_data ({ rf_core_ctrlport_req_data [1], rf_core_ctrlport_req_data [0] }),
+ .m_ctrlport_rf_core_resp_ack ({ rf_core_ctrlport_resp_ack [1], rf_core_ctrlport_resp_ack [0] }),
+ .m_ctrlport_rf_core_resp_status({ rf_core_ctrlport_resp_status [1], rf_core_ctrlport_resp_status [0] }),
+ .m_ctrlport_rf_core_resp_data ({ rf_core_ctrlport_resp_data [1], rf_core_ctrlport_resp_data [0] }),
.start_nco_reset (start_nco_reset),
.nco_reset_done (nco_reset_done),
.adc_reset_pulse (adc_reset_pulse),
diff --git a/fpga/usrp3/top/x400/x4xx_core.v b/fpga/usrp3/top/x400/x4xx_core.v
index 638dca1af2..4294c63d31 100644
--- a/fpga/usrp3/top/x400/x4xx_core.v
+++ b/fpga/usrp3/top/x400/x4xx_core.v
@@ -326,6 +326,14 @@ module x4xx_core #(
input wire [ 2*NUM_DBOARDS-1:0] m_ctrlport_radio_resp_status,
input wire [ 32*NUM_DBOARDS-1:0] m_ctrlport_radio_resp_data,
+ output wire [ 1*NUM_DBOARDS-1:0] m_ctrlport_rf_core_req_wr,
+ output wire [ 1*NUM_DBOARDS-1:0] m_ctrlport_rf_core_req_rd,
+ output wire [ 20*NUM_DBOARDS-1:0] m_ctrlport_rf_core_req_addr,
+ output wire [ 32*NUM_DBOARDS-1:0] m_ctrlport_rf_core_req_data,
+ input wire [ 1*NUM_DBOARDS-1:0] m_ctrlport_rf_core_resp_ack,
+ input wire [ 2*NUM_DBOARDS-1:0] m_ctrlport_rf_core_resp_status,
+ input wire [ 32*NUM_DBOARDS-1:0] m_ctrlport_rf_core_resp_data,
+
// RF Reset Control
output wire start_nco_reset,
input wire nco_reset_done,
@@ -501,6 +509,13 @@ module x4xx_core #(
.m_radio_ctrlport_resp_ack (m_ctrlport_radio_resp_ack),
.m_radio_ctrlport_resp_status (m_ctrlport_radio_resp_status),
.m_radio_ctrlport_resp_data (m_ctrlport_radio_resp_data),
+ .m_rf_core_ctrlport_req_wr (m_ctrlport_rf_core_req_wr),
+ .m_rf_core_ctrlport_req_rd (m_ctrlport_rf_core_req_rd),
+ .m_rf_core_ctrlport_req_addr (m_ctrlport_rf_core_req_addr),
+ .m_rf_core_ctrlport_req_data (m_ctrlport_rf_core_req_data),
+ .m_rf_core_ctrlport_resp_ack (m_ctrlport_rf_core_resp_ack),
+ .m_rf_core_ctrlport_resp_status (m_ctrlport_rf_core_resp_status),
+ .m_rf_core_ctrlport_resp_data (m_ctrlport_rf_core_resp_data),
.start_nco_reset (start_nco_reset),
.nco_reset_done (nco_reset_done),
.adc_reset_pulse (adc_reset_pulse),
diff --git a/fpga/usrp3/top/x400/x4xx_core_common.v b/fpga/usrp3/top/x400/x4xx_core_common.v
index ca82abd07a..c816941f37 100644
--- a/fpga/usrp3/top/x400/x4xx_core_common.v
+++ b/fpga/usrp3/top/x400/x4xx_core_common.v
@@ -133,6 +133,15 @@ module x4xx_core_common #(
input wire [ 2*NUM_DBOARDS-1:0] m_radio_ctrlport_resp_status,
input wire [ 32*NUM_DBOARDS-1:0] m_radio_ctrlport_resp_data,
+ // CtrlPort Master (to RF cores, Domain: radio_clk)
+ output wire [ 1*NUM_DBOARDS-1:0] m_rf_core_ctrlport_req_wr,
+ output wire [ 1*NUM_DBOARDS-1:0] m_rf_core_ctrlport_req_rd,
+ output wire [ 20*NUM_DBOARDS-1:0] m_rf_core_ctrlport_req_addr,
+ output wire [ 32*NUM_DBOARDS-1:0] m_rf_core_ctrlport_req_data,
+ input wire [ 1*NUM_DBOARDS-1:0] m_rf_core_ctrlport_resp_ack,
+ input wire [ 2*NUM_DBOARDS-1:0] m_rf_core_ctrlport_resp_status,
+ input wire [ 32*NUM_DBOARDS-1:0] m_rf_core_ctrlport_resp_data,
+
// RF Reset Control
output wire start_nco_reset,
input wire nco_reset_done,
@@ -477,6 +486,7 @@ module x4xx_core_common #(
localparam [19:0] DIGITAL_IFC_OFFSET = DIO_WINDOW + DIGITAL_IFC_REGS;
// Register space size calculation
+ localparam [31:0] RF_CORE_WINDOW_SIZE_W = $clog2(RF_CORE_WINDOW_SIZE);
localparam [31:0] RFDC_TIMING_WINDOW_SIZE_W = $clog2(RFDC_TIMING_WINDOW_SIZE);
localparam [31:0] DB_WINDOW_SIZE_W = $clog2(DB_WINDOW_SIZE);
localparam [31:0] DIO_SOURCE_CONTROL_SIZE_W = $clog2(DIO_SOURCE_CONTROL_SIZE);
@@ -484,16 +494,18 @@ module x4xx_core_common #(
localparam [31:0] DIGITAL_IFC_REGS_SIZE_W = $clog2(DIGITAL_IFC_REGS_SIZE);
ctrlport_decoder_param #(
- .NUM_SLAVES (5),
+ .NUM_SLAVES (6),
.PORT_BASE ({ DIGITAL_IFC_OFFSET,
DIO_SOURCE_CONTROL_OFFSET,
RADIO_GPIO_ATR_OFFSET,
+ RF_CORE_WINDOW[19:0],
RFDC_TIMING_WINDOW[19:0],
DB_WINDOW[19:0]
}),
.PORT_ADDR_W ({ DIGITAL_IFC_REGS_SIZE_W,
DIO_SOURCE_CONTROL_SIZE_W,
RADIO_GPIO_ATR_SIZE_W,
+ RF_CORE_WINDOW_SIZE_W,
RFDC_TIMING_WINDOW_SIZE_W,
DB_WINDOW_SIZE_W
})
@@ -513,21 +525,25 @@ module x4xx_core_common #(
.m_ctrlport_req_wr ({ gpio_spi_ctrlport_req_wr [ 1*db_i+: 1],
radio_dio_req_wr [ 1*db_i+: 1],
gpio_atr_ctrlport_req_wr [ 1*db_i+: 1],
+ m_rf_core_ctrlport_req_wr [ 1*db_i+: 1],
rf_ctrlport_req_wr [ 1*db_i+: 1],
m_radio_ctrlport_req_wr [ 1*db_i+: 1] }),
.m_ctrlport_req_rd ({ gpio_spi_ctrlport_req_rd [ 1*db_i+: 1],
radio_dio_req_rd [ 1*db_i+: 1],
gpio_atr_ctrlport_req_rd [ 1*db_i+: 1],
+ m_rf_core_ctrlport_req_rd [ 1*db_i+: 1],
rf_ctrlport_req_rd [ 1*db_i+: 1],
m_radio_ctrlport_req_rd [ 1*db_i+: 1] }),
.m_ctrlport_req_addr ({ gpio_spi_ctrlport_req_addr [20*db_i+:20],
radio_dio_req_addr [20*db_i+:20],
gpio_atr_ctrlport_req_addr [20*db_i+:20],
+ m_rf_core_ctrlport_req_addr [20*db_i+:20],
rf_ctrlport_req_addr [20*db_i+:20],
m_radio_ctrlport_req_addr [20*db_i+:20] }),
.m_ctrlport_req_data ({ gpio_spi_ctrlport_req_data [32*db_i+:32],
radio_dio_req_data [32*db_i+:32],
gpio_atr_ctrlport_req_data [32*db_i+:32],
+ m_rf_core_ctrlport_req_data [32*db_i+:32],
rf_ctrlport_req_data [32*db_i+:32],
m_radio_ctrlport_req_data [32*db_i+:32] }),
.m_ctrlport_req_byte_en (),
@@ -536,16 +552,19 @@ module x4xx_core_common #(
.m_ctrlport_resp_ack ({ gpio_spi_ctrlport_resp_ack [ 1*db_i+: 1],
radio_dio_resp_ack [ 1*db_i+: 1],
gpio_atr_ctrlport_resp_ack [ 1*db_i+: 1],
+ m_rf_core_ctrlport_resp_ack [ 1*db_i+: 1],
rf_ctrlport_resp_ack [ 1*db_i+: 1],
m_radio_ctrlport_resp_ack [ 1*db_i+: 1] }),
.m_ctrlport_resp_status ({ gpio_spi_ctrlport_resp_status [ 2*db_i+: 2],
radio_dio_resp_status [ 2*db_i+: 2],
gpio_atr_ctrlport_resp_status [ 2*db_i+: 2],
+ m_rf_core_ctrlport_resp_status [ 2*db_i+: 2],
rf_ctrlport_resp_status [ 2*db_i+: 2],
m_radio_ctrlport_resp_status [ 2*db_i+: 2] }),
.m_ctrlport_resp_data ({ gpio_spi_ctrlport_resp_data [32*db_i+:32],
radio_dio_resp_data [32*db_i+:32],
gpio_atr_ctrlport_resp_data [32*db_i+:32],
+ m_rf_core_ctrlport_resp_data [32*db_i+:32],
rf_ctrlport_resp_data [32*db_i+:32],
m_radio_ctrlport_resp_data [32*db_i+:32] })
);
@@ -891,9 +910,12 @@ endmodule
// Daughterboard GPIO interface. Register access within this space
// is directed to the associated daughterboard CPLD.
//
-//
+//
// RFDC timing control interface.
//
+//
+// Interface for the RF core.
+//
//
// DIO control interface. Interacts with the DIO source selection
// block, ATR-based DIO control and the DIO digital interface
diff --git a/host/docs/install.dox b/host/docs/install.dox
index 6ec796daae..16be561865 100644
--- a/host/docs/install.dox
+++ b/host/docs/install.dox
@@ -40,7 +40,7 @@ and compiler version used for the UHD binaries. This detail is indicated
in the name of the installer executable;
for example, uhd_4.7.0.0-release_Win64_VS2017.exe indicates it was built
for the 64-bit Windows platform using the Visual Studio 2017 compiler suite.
-Copy all files from the path \VS20XX\MSYY\dll within the archive to the bin folder
+Copy all files from the path \\VS20XX\\MSYY\\dll within the archive to the bin folder
of the UHD installation location (by default "C:\Program Files\UHD\bin").
VS20XX is the Visual Studio version that you find in the name of the UHD installer.
YY is the bitness of your Windows version (32 or 64).
diff --git a/host/docs/sphinx/environment.yml b/host/docs/sphinx/environment.yml
index e4eb11154f..9e78686275 100644
--- a/host/docs/sphinx/environment.yml
+++ b/host/docs/sphinx/environment.yml
@@ -3,6 +3,7 @@ channels:
- conda-forge
- defaults
dependencies:
+ - python=3.12
- pip
- cmake
- compilers
diff --git a/host/docs/sphinx/source/conf.py b/host/docs/sphinx/source/conf.py
index e8a7c413c1..c662521e12 100644
--- a/host/docs/sphinx/source/conf.py
+++ b/host/docs/sphinx/source/conf.py
@@ -60,7 +60,7 @@
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
-language = None
+language = 'en'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@@ -87,7 +87,7 @@
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+# html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
diff --git a/host/include/uhd/rfnoc/rf_control/core_iface.hpp b/host/include/uhd/rfnoc/rf_control/core_iface.hpp
index a557bf9df4..c297e154b2 100644
--- a/host/include/uhd/rfnoc/rf_control/core_iface.hpp
+++ b/host/include/uhd/rfnoc/rf_control/core_iface.hpp
@@ -79,6 +79,15 @@ class core_iface
* If there is a single LO in this radio, and we're doing direct conversion,
* then this is the LO frequency.
*
+ * Note that unlike the uhd::usrp::multi_usrp::set_tx_freq() API, this does
+ * not attempt to tune any attached digital frequency shifter, unless it is
+ * part of the radio. That is why this API only returns a double value (the
+ * actual frequency) instead of a uhd::tune_result_t. If a combined tuning
+ * of digital frequency correction and LO tuning is desired (the same way
+ * that uhd::usrp::multi_usrp does by default), then the caller has to
+ * either also call uhd::rfnoc::dc_block_control::set_freq() with the
+ * residual frequency, or tune through the graph.
+ *
* \param freq Frequency in Hz
* \param chan Channel to tune
*
@@ -110,6 +119,15 @@ class core_iface
* If there is a single LO in this radio, and we're doing direct conversion,
* then this is the LO frequency.
*
+ * Note that unlike the uhd::usrp::multi_usrp::set_rx_freq() API, this does
+ * not attempt to tune any attached digital frequency shifter, unless it is
+ * part of the radio. That is why this API only returns a double value (the
+ * actual frequency) instead of a uhd::tune_result_t. If a combined tuning
+ * of digital frequency correction and LO tuning is desired (the same way
+ * that uhd::usrp::multi_usrp does by default), then the caller has to
+ * either also call uhd::rfnoc::ddc_block_control::set_freq() with the
+ * residual frequency, or tune through the graph.
+ *
* \param freq Requested frequency
* \param chan Channel number.
* \return The actual frequency.
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 683c1a4cce..93166624a4 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -143,7 +143,6 @@ LIBUHD_APPEND_LIBS(uhd_rc)
# Add DLL resource file to Windows build
########################################################################
if(MSVC)
- math(EXPR RC_VERSION_MAJOR_API "${UHD_VERSION_MAJOR} * 1000 + ${UHD_VERSION_API}")
set(RC_VERSION_PATCH ${UHD_VERSION_PATCH})
if(UHD_VERSION_DEVEL)
set(RC_VERSION_PATCH "999")
diff --git a/host/lib/deps/rpclib/include/rpc/msgpack/predef/architecture/arm.h b/host/lib/deps/rpclib/include/rpc/msgpack/predef/architecture/arm.h
index bfc4a3404a..737a066e1e 100644
--- a/host/lib/deps/rpclib/include/rpc/msgpack/predef/architecture/arm.h
+++ b/host/lib/deps/rpclib/include/rpc/msgpack/predef/architecture/arm.h
@@ -27,11 +27,13 @@ Distributed under the Boost Software License, Version 1.0.
[[`__TARGET_ARCH_ARM`] [__predef_detection__]]
[[`__TARGET_ARCH_THUMB`] [__predef_detection__]]
[[`_M_ARM`] [__predef_detection__]]
+ [[`_M_ARM64`] [__predef_detection__]]
[[`__arm64`] [8.0.0]]
[[`__TARGET_ARCH_ARM`] [V.0.0]]
[[`__TARGET_ARCH_THUMB`] [V.0.0]]
[[`_M_ARM`] [V.0.0]]
+ [[`_M_ARM64`] [V.0.0]]
]
*/
@@ -39,7 +41,7 @@ Distributed under the Boost Software License, Version 1.0.
#if defined(__arm__) || defined(__arm64) || defined(__thumb__) || \
defined(__TARGET_ARCH_ARM) || defined(__TARGET_ARCH_THUMB) || \
- defined(_M_ARM)
+ defined(_M_ARM) || defined(_M_ARM64)
# undef MSGPACK_ARCH_ARM
# if !defined(MSGPACK_ARCH_ARM) && defined(__arm64)
# define MSGPACK_ARCH_ARM MSGPACK_VERSION_NUMBER(8,0,0)
@@ -53,6 +55,9 @@ Distributed under the Boost Software License, Version 1.0.
# if !defined(MSGPACK_ARCH_ARM) && defined(_M_ARM)
# define MSGPACK_ARCH_ARM MSGPACK_VERSION_NUMBER(_M_ARM,0,0)
# endif
+# if !defined(MSGPACK_ARCH_ARM) && defined(_M_ARM64)
+# define MSGPACK_ARCH_ARM MSGPACK_VERSION_NUMBER(_M_ARM64,0,0)
+# endif
# if !defined(MSGPACK_ARCH_ARM)
# define MSGPACK_ARCH_ARM MSGPACK_VERSION_NUMBER_AVAILABLE
# endif
diff --git a/host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp b/host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp
index 6371eb2e52..d83a8239a1 100644
--- a/host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp
+++ b/host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp
@@ -7,21 +7,66 @@
#pragma once
+#include
+#include
+#include
+#include
+#include
#include
/*! For a requested frequency, sampling rate, and frequency word width (in
* number of bits), return the correct frequency word (to set the CORDIC or
* DDS) and the actual frequency.
*/
+template
void get_freq_and_freq_word(const double requested_freq,
const double tick_rate,
double& actual_freq,
- int32_t& freq_word,
- int word_width = 32);
+ int32_t& freq_word)
+{
+ constexpr int32_t MAX_FREQ_WORD = std::numeric_limits::max();
+ constexpr int32_t MIN_FREQ_WORD = std::numeric_limits::min();
+ constexpr double scale_factor = static_cast(uint64_t(1) << word_width);
+ // Frequency normalized by sampling rate, and wrapped to [-0.5, 0.5).
+ const double freq_norm_scaled =
+ uhd::math::wrap_frequency(requested_freq / tick_rate, 1.0) * scale_factor;
+
+ // confirm that the target frequency is within range of the CORDIC
+ UHD_ASSERT_THROW(std::abs(freq_norm_scaled) - 1 <= MAX_FREQ_WORD);
+
+ /* Now calculate the frequency word. It is possible for this calculation
+ * to cause an overflow. As the requested DSP frequency approaches the
+ * master clock rate, that ratio multiplied by the scaling factor (2^32)
+ * will generally overflow within the last few kHz of tunable range.
+ * Thus, we check to see if the operation will overflow before doing it,
+ * and if it will, we set it to the integer min or max of this system.
+ */
+ if (freq_norm_scaled >= MAX_FREQ_WORD) {
+ /* Operation would have caused a positive overflow of int32. */
+ freq_word = MAX_FREQ_WORD;
+
+ } else if (freq_norm_scaled <= MIN_FREQ_WORD) {
+ /* Operation would have caused a negative overflow of int32. */
+ freq_word = MIN_FREQ_WORD;
+
+ } else {
+ /* The operation is safe. Perform normally. */
+ freq_word = int32_t(std::lround(freq_norm_scaled));
+ }
+
+ actual_freq = (double(freq_word) / scale_factor) * tick_rate;
+}
/*! For a requested frequency, sampling rate, and frequency word width (in
* number of bits), return the correct frequency word (to set the CORDIC or
* DDS) and the actual frequency.
*/
+template
std::tuple get_freq_and_freq_word(
- const double requested_freq, const double tick_rate, int word_width = 32);
+ const double requested_freq, const double tick_rate)
+{
+ double actual_freq;
+ int32_t freq_word;
+ get_freq_and_freq_word(requested_freq, tick_rate, actual_freq, freq_word);
+ return {actual_freq, freq_word};
+}
diff --git a/host/lib/include/uhdlib/usrp/dboard/fbx/fbx_constants.hpp b/host/lib/include/uhdlib/usrp/dboard/fbx/fbx_constants.hpp
index eefb173360..fd23fb8efd 100644
--- a/host/lib/include/uhdlib/usrp/dboard/fbx/fbx_constants.hpp
+++ b/host/lib/include/uhdlib/usrp/dboard/fbx/fbx_constants.hpp
@@ -72,11 +72,12 @@ static const std::vector FBX_LOS = {RFDC_NCO};
static constexpr size_t FBX_MAX_NUM_CHANS = 4;
// These are addresses for the various table-based registers
-static constexpr uint32_t ATR_ADDR_0X = 0;
-static constexpr uint32_t ATR_ADDR_RX = 1;
-static constexpr uint32_t ATR_ADDR_TX = 2;
-static constexpr uint32_t ATR_ADDR_XX = 3; // Full-duplex
+static constexpr uint32_t ATR_ADDR_0X = 0;
+static constexpr uint32_t ATR_ADDR_RX = 1;
+static constexpr uint32_t ATR_ADDR_TX = 2;
+static constexpr uint32_t ATR_ADDR_XX = 3; // Full-duplex
+static constexpr uint32_t NUM_ATR_STATES = 4;
// Helper for looping
-static constexpr std::array ATR_ADDRS{0, 1, 2, 3};
+static constexpr std::array ATR_ADDRS{0, 1, 2, 3};
}}} // namespace uhd::usrp::fbx
diff --git a/host/lib/include/uhdlib/usrp/dboard/zbx/zbx_constants.hpp b/host/lib/include/uhdlib/usrp/dboard/zbx/zbx_constants.hpp
index 63762be4ee..501abb28b4 100644
--- a/host/lib/include/uhdlib/usrp/dboard/zbx/zbx_constants.hpp
+++ b/host/lib/include/uhdlib/usrp/dboard/zbx/zbx_constants.hpp
@@ -184,12 +184,13 @@ static constexpr std::array ZBX_CHANNELS{0, 1};
static constexpr double ZBX_MIX1_MN_THRESHOLD = 4e9;
// These are addresses for the various table-based registers
-static constexpr uint32_t ATR_ADDR_0X = 0;
-static constexpr uint32_t ATR_ADDR_RX = 1;
-static constexpr uint32_t ATR_ADDR_TX = 2;
-static constexpr uint32_t ATR_ADDR_XX = 3; // Full-duplex
+static constexpr uint32_t ATR_ADDR_0X = 0;
+static constexpr uint32_t ATR_ADDR_RX = 1;
+static constexpr uint32_t ATR_ADDR_TX = 2;
+static constexpr uint32_t ATR_ADDR_XX = 3; // Full-duplex
+static constexpr uint32_t NUM_ATR_STATES = 4;
// Helper for looping
-static constexpr std::array ATR_ADDRS{0, 1, 2, 3};
+static constexpr std::array ATR_ADDRS{0, 1, 2, 3};
// Turn clang-formatting off so it doesn't compress these tables into a mess.
// clang-format off
diff --git a/host/lib/uhd.rc.in b/host/lib/uhd.rc.in
index dee6bb8a3d..89045400ed 100644
--- a/host/lib/uhd.rc.in
+++ b/host/lib/uhd.rc.in
@@ -1,8 +1,8 @@
#include
VS_VERSION_INFO VERSIONINFO
- FILEVERSION @RC_VERSION_MAJOR_API@,@UHD_VERSION_ABI@,@RC_VERSION_PATCH@,@UHD_GIT_COUNT@
- PRODUCTVERSION @RC_VERSION_MAJOR_API@,@UHD_VERSION_ABI@,@RC_VERSION_PATCH@,@UHD_GIT_COUNT@
+ FILEVERSION @UHD_VERSION_MAJOR@,@UHD_VERSION_API@,@UHD_VERSION_ABI@,@RC_VERSION_PATCH@
+ PRODUCTVERSION @UHD_VERSION_MAJOR@,@UHD_VERSION_API@,@UHD_VERSION_ABI@,@RC_VERSION_PATCH@
FILEFLAGSMASK 0x3fL
#ifndef NDEBUG
FILEFLAGS 0x0L
diff --git a/host/lib/usrp/cores/CMakeLists.txt b/host/lib/usrp/cores/CMakeLists.txt
index 2e2132ad3b..f43161a571 100644
--- a/host/lib/usrp/cores/CMakeLists.txt
+++ b/host/lib/usrp/cores/CMakeLists.txt
@@ -28,7 +28,6 @@ endif()
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/dma_fifo_core_3000.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/dsp_core_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gpio_atr_3000.cpp
${CMAKE_CURRENT_SOURCE_DIR}/i2c_core_100_wb32.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rx_dsp_core_3000.cpp
diff --git a/host/lib/usrp/cores/dsp_core_utils.cpp b/host/lib/usrp/cores/dsp_core_utils.cpp
deleted file mode 100644
index 5575d97759..0000000000
--- a/host/lib/usrp/cores/dsp_core_utils.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright 2016 Ettus Research LLC
-// Copyright 2018 Ettus Research, a National Instruments Company
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-#include
-#include
-#include
-#include
-#include
-
-static const int32_t MAX_FREQ_WORD = std::numeric_limits::max();
-static const int32_t MIN_FREQ_WORD = std::numeric_limits::min();
-
-void get_freq_and_freq_word(const double requested_freq,
- const double tick_rate,
- double& actual_freq,
- int32_t& freq_word,
- int word_width)
-{
- const double freq = uhd::math::wrap_frequency(requested_freq, tick_rate);
-
- // confirm that the target frequency is within range of the CORDIC
- UHD_ASSERT_THROW(std::abs(freq) <= tick_rate / 2.0);
-
- /* Now calculate the frequency word. It is possible for this calculation
- * to cause an overflow. As the requested DSP frequency approaches the
- * master clock rate, that ratio multiplied by the scaling factor (2^32)
- * will generally overflow within the last few kHz of tunable range.
- * Thus, we check to see if the operation will overflow before doing it,
- * and if it will, we set it to the integer min or max of this system.
- */
- freq_word = 0;
-
- static const double scale_factor = std::pow(2.0, word_width);
- if ((freq / tick_rate) >= (MAX_FREQ_WORD / scale_factor)) {
- /* Operation would have caused a positive overflow of int32. */
- freq_word = MAX_FREQ_WORD;
-
- } else if ((freq / tick_rate) <= (MIN_FREQ_WORD / scale_factor)) {
- /* Operation would have caused a negative overflow of int32. */
- freq_word = MIN_FREQ_WORD;
-
- } else {
- /* The operation is safe. Perform normally. */
- freq_word = int32_t(std::lround((freq / tick_rate) * scale_factor));
- }
-
- actual_freq = (double(freq_word) / scale_factor) * tick_rate;
-}
-
-std::tuple get_freq_and_freq_word(
- const double requested_freq, const double tick_rate, int word_width)
-{
- double actual_freq;
- int32_t freq_word;
- get_freq_and_freq_word(requested_freq, tick_rate, actual_freq, freq_word, word_width);
- return std::make_tuple(actual_freq, freq_word);
-}
diff --git a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp
index ca4fd17079..636c9551ac 100644
--- a/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp
+++ b/host/lib/usrp/dboard/magnesium/magnesium_radio_control.cpp
@@ -897,7 +897,7 @@ double magnesium_radio_control_impl::get_rx_lo_freq(
std::string source = this->get_rx_lo_source(name, chan);
if (name == MAGNESIUM_LO1) {
return _ad9371_freq.at(RX_DIRECTION);
- } else if (name == "adf4531") {
+ } else if (name == MAGNESIUM_LO2) {
return _adf4351_freq.at(RX_DIRECTION);
} else {
RFNOC_LOG_ERROR("get_rx_lo_freq(): No such LO: " << name);
diff --git a/tools/changeset_testlist.py b/tools/changeset_testlist.py
index cd668edcb2..2b9a96bda6 100644
--- a/tools/changeset_testlist.py
+++ b/tools/changeset_testlist.py
@@ -55,10 +55,96 @@ def parse_args():
return parser.parse_args()
-def get_changed_files(repo_path, target_branch, source_branch, include_target):
+def check_changeset_content(file, **kwargs):
+ """Check changeset content for code and/or comments changes
+
+ For example, if a .cpp file only has a comment change, we can use this to
+ remove it from the "changed files" list. This is useful when we only want to
+ only include tests if the underlying code was actually changed, and not just
+ a comment (which cannot change the outcome of a hardware test).
+
+ The values of the include_content argument have the following meaning:
+ - 'code': at least one line with code changed
+ - 'code-only': all changed lines must be code changes
+ - 'comments': at least one line with comments changed
+ - 'comments-only': all changed lines must be comment changes
+ - 'code-and-comments': either code or comments changes (always True)
+
+ Arguments:
+ file: List of files that have been changed.
+ repo_path: Path to the UHD repository.
+ git_cmd: Path to the git command.
+ include_content: allowed values are: code, code-only, comments,
+ comments-only, code-and-comments
+
+ Returns: True if the file should be included, False otherwise.
"""
- Returns a list of paths in the UHD repository that have are different between
- two branches.
+
+ def identify_comment_line_cpp(line):
+ """Identify if a line is a comment in a C++ file."""
+ line = line.strip()
+ return line.startswith("//") or line.startswith("/*") or line.startswith("*")
+
+ def identify_comment_line_py(line):
+ """Identify if a line is a comment in a Python file."""
+ line = line.strip()
+ return line.startswith("#")
+
+ comment_identifer = {
+ ".cpp": identify_comment_line_cpp,
+ ".hpp": identify_comment_line_cpp,
+ ".c": identify_comment_line_cpp,
+ ".h": identify_comment_line_cpp,
+ ".py": identify_comment_line_py,
+ }
+
+ include_content = kwargs.get("include_content", None)
+ if include_content == "code-and-comments":
+ # No need to check, result will always be true
+ return True
+ elif include_content in ["code", "code-only"]:
+ invert = True
+ elif include_content in ["comments", "comments-only"]:
+ invert = False
+ else:
+ raise ValueError(f"Unsupported argument: include_content={include_content}")
+
+ target_branch = kwargs["target_branch"]
+ if kwargs.get("include_target"):
+ target_branch += "..."
+ get_diff_args = [
+ shutil.which("git"),
+ "-C",
+ kwargs["repo_path"],
+ "diff",
+ "--no-color",
+ "--unified=0",
+ target_branch,
+ "--",
+ ]
+
+ ext = os.path.splitext(file)[1]
+ if ext not in comment_identifer:
+ # If we have no rule to check, then always include the file.
+ return True
+ diff_lines = (
+ subprocess.check_output(get_diff_args + [file], encoding="utf-8").strip().split("\n")[4:]
+ )
+ line_matches = [comment_identifer[ext](line[1:])^invert for line in diff_lines if line[0] in ("-", "+")]
+ if include_content.endswith("-only"):
+ return all(line_matches)
+ else:
+ return any(line_matches)
+
+
+def get_changed_files(repo_path, target_branch, source_branch, include_target):
+ """Return a list of paths in the UHD repository that have are different between two branches.
+
+ Arguments:
+ repo_path: Path to the UHD repository.
+ target_branch: Branch to compare against (e.g., master).
+ source_branch: Branch to compare from. Defaults to the current branch.
+ include_target: Include changes that originate from the target branch.
"""
assert target_branch
# If include_target is false, then current (unstaged/uncommited) changes are
@@ -84,14 +170,16 @@ def load_rules(rule_file):
class RuleApplier:
"""Helper class to update an internal test list based on a set of rules."""
- def __init__(self, rules, labels):
+ def __init__(self, rules, labels, **kwargs):
"""Initialize.
Arguments:
rules: List of rules to apply.
+ labels: List of labels relevant to the current changeset.
"""
self.rules = rules
self.labels = labels
+ self.args = kwargs
self.test_list = set()
def apply(self, filename, verbose=False):
@@ -130,9 +218,20 @@ def _apply_rule(self, rule, filename, verbose=False):
if verbose:
sys.stderr.write(f"Filename {filename} matches rule: {rule}\n")
if "label" in rule and not rule["label"] in self.labels:
+ if verbose:
+ sys.stderr.write(f"Skipping file based on missing label: {rule['label']}\n")
return False
if "label" in rule and verbose:
sys.stderr.write(f"Label {rule['label']} found\n")
+ include_content = rule.get("include_content", "code")
+ if not check_changeset_content(
+ filename, **self.args, include_content=include_content
+ ):
+ if verbose:
+ sys.stderr.write(
+ f"Skipping {filename} based on content rule: include_content='{include_content}'\n"
+ )
+ return False
if "add" in rule:
self.test_list.update(rule["add"])
if "remove" in rule:
@@ -170,7 +269,15 @@ def main():
args.include_target,
)
labels = get_labels(args.github_label_api_endpoint, args.github_token)
- rule_applier = RuleApplier(load_rules(rule_file), labels)
+ rule_applier = RuleApplier(
+ load_rules(rule_file),
+ labels,
+ repo_path=args.repo_path,
+ target_branch=args.target_branch,
+ source_branch=args.source_branch,
+ include_target=args.include_target,
+ verbose=args.verbose,
+ )
for filename in file_list:
rule_applier.apply(filename, args.verbose)
rule_applier.apply_labels()
diff --git a/tools/changeset_testlist.yaml b/tools/changeset_testlist.yaml
index 71dcc280b1..ebbac6157c 100644
--- a/tools/changeset_testlist.yaml
+++ b/tools/changeset_testlist.yaml
@@ -25,6 +25,13 @@
- re: ^host/docs/
add:
- uhd.docs
+# If a comment in a public header changed, then most likely the documentation
+# changed, but we still want to run other tests, too
+- re: ^host/include/uhd/.+\.hpp$
+ add:
+ - uhd.docs
+ include_content: comments
+ stop: False
# Device-specific changes. These should trigger HW tests only on those devices
# they affect. We start with daughterboard rules, then motherboard rules.
- re: host/lib/usrp/dboard/zbx/
@@ -196,7 +203,36 @@
###############################################################################
# CI CHANGES
###############################################################################
-- re: .ci/templates/tests/templates/job-uhd-x4xx-hardware-tests.yml
+# Changes to pipeline infrastructure or build jobs -> build and test all
+- re: .ci/templates/stages-.*.yml
+ add:
+ - uhd.build.all
+ - hw.streaming.all
+ - hw.rf.all
+ - devtest.all
+- re: .ci/templates/.*-build.*.yml
+ add:
+ - uhd.build.all
+ - hw.streaming.all
+ - hw.rf.all
+ - devtest.all
+# Devtest
+- re: .ci/templates/.*-devtest.*.yml
+ add:
+ - uhd.build.linux
+ - devtest.all
+# RF Test
+- re: .ci/templates/.*-rf-tests.*.yml
+ add:
+ - uhd.build.linux
+ - hw.rf.all
+# Streaming Test
+- re: .ci/templates/.*-streaming.*.yml
+ add:
+ - uhd.build.linux
+ - hw.streaming.all
+# RF Test x4xx
+- re: .ci/templates/tests/.*.yml
add:
- uhd.build.linux
- hw.rf.x4xx