fpga: ci: add CPLD compile job

This commit is contained in:
Max Köhler 2025-06-24 12:55:48 +02:00 committed by Jörg Hofrichter
parent 533d2e7403
commit 11b56b9650
10 changed files with 182 additions and 179 deletions

View File

@ -1,35 +0,0 @@
#!/usr/bin/env python3
#
# Copyright 2021 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Description:
#
# Our pipelines reuse IP builds to save time. In the case where an IP build
# fails or is terminated before completion, it is sometimes necessary to
# clean up the build so that the next build can complete properly. This
# script searches for and deletes any incomplete IP builds.
#
import argparse
import os
import shutil
# argument parsing
parser = argparse.ArgumentParser(description="This script removes all directories where the .build_lock file still exists")
parser.add_argument('--directory', '-d', required=True, help='directory to search for lock files (recursively)')
args = parser.parse_args()
# search .build_lock files
lockFiles = []
for root, dirs, files in os.walk(args.directory):
for file in files:
if file == ".build_lock":
lockFiles.append(os.path.join(root, file))
# remove all directories containing lock files
for lockFile in lockFiles:
dirPath = os.path.dirname(lockFile)
print("delete " + dirPath)
shutil.rmtree(dirPath)

View File

@ -0,0 +1,22 @@
#!/usr/bin/env python3
"""
Copyright 2025 Ettus Research, a National Instruments Brand
SPDX-License-Identifier: LGPL-3.0-or-later
Merge multiple INI files into a single one.
"""
import configparser
import argparse
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('files', type=str, nargs='+', help='a list of INI files to merge')
parser.add_argument('-o', '--output', type=str, default='modelsim.ini', help='the output file name')
args = parser.parse_args()
config = configparser.ConfigParser()
config.read(args.files)
with open(args.output, 'w') as configfile:
config.write(configfile)

View File

@ -37,11 +37,20 @@ source hwsetup.sh hwtools=0.1.3
popd
echo "---- Fetch the FPGA simulation libraries ----"
# The simulation libraries for our versions have been pre-compiled, so this
# should simply copy them if they're not already on this agent.
compileFpgaLibs vivado
# This is where compileFpgaLibs puts the simulation libraries
export MODELSIM_INI_DIR=/usr/hwlibs/vivado/2021.1/modelsim_SE-64_2020
# Compiling the simulation libraries.
# Extracting the modelsim.ini path from the output.
# Creating a temporary modelsim.mpf file for the scripting to work.
echo "[Library]" > modelsim.mpf
compileFpgaLibs vivado | tee compileFpgaLib.log
VIVADO_MODELSIM_INI_PATH=$(grep Reading compileFpgaLib.log | awk '{print $3}' | sed 's/\x1b\[[0-9;]*m//g')
compileFpgaLibs diamond | tee compileFpgaLib.log
DIAMOND_MODELSIM_INI_PATH=$(grep Reading compileFpgaLib.log | awk '{print $3}' | sed 's/\x1b\[[0-9;]*m//g')
# Combine all modelsim.ini files to local copy
python $(dirname $BASH_SOURCE)/merge_modelsim_ini.py \
-o $BUILD_SOURCESDIRECTORY/modelsim.ini \
$VIVADO_MODELSIM_INI_PATH $DIAMOND_MODELSIM_INI_PATH
# Removing the temporary files
rm -f modelsim.mpf compileFpgaLib.log
echo "---- Fetch Vivado patches ----"
export PATCHES_DIR=$BUILD_SOURCESDIRECTORY/patches
@ -61,8 +70,7 @@ echo "---- Apply the Vivado patches ----"
pushd $BUILD_SOURCESDIRECTORY
# Apply the patch to Vivado
export XILINX_PATH=$PATCHES_DIR/AR76780_Vivado_2021/vivado
# Create a local copy of modelsim.ini and add the FIR compiler simulation model
cp $MODELSIM_INI_DIR/modelsim.ini ./
# Add the FIR compiler simulation model to local modelsim.ini
# Delete all lines containing "fir_compiler_v7_2_76780" to avoid duplicates
sed -i -e '/fir_compiler_v7_2_76780/d' ./modelsim.ini
# Duplicate line containing "fir_compiler_v7_2_16"

View File

@ -0,0 +1,93 @@
#
# Copyright 2025 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Description:
#
# This template should be used for CPLD builds.
# Exports the final programming files as pipeline artifacts.
#
# See description for the parameters below.
#
parameters:
# Publishes the intermediate files from the build-* directories as pipeline artifacts.
- name: publish_int_files
type: boolean
default: false
# cpldBuilds: List of CPLD builds to be executed
# each element is a list of 3 strings (displayName, workingDirectory, artifactName)
# e.g ['ZBX CPLD Build', './top/x400/dboards/zbx/cpld', 'CPLD_ZBX']
- name: cpldBuilds
type: object
default: []
jobs:
- ${{ each cpldBuild in parameters.cpldBuilds }}:
- job:
displayName: ${{ cpldBuild.displayName }}
timeoutInMinutes: 30
pool:
name: Drivers-NIBuildFarm-RFMIBUILD
demands:
- Agent.OS -equals Linux
variables:
- group: sdr-pipeline-vars
steps:
- template: setup_steps.yml
- bash: |
# Find the directory containing setupenv.sh by searching upwards from the working directory
search_dir="${{ cpldBuild.workingDirectory }}"
while [[ "$search_dir" != "." && "$search_dir" != "/" ]]; do
if [[ -f "$search_dir/setupenv.sh" ]]; then
setup_dir="$search_dir"
break
fi
search_dir="$(dirname "$search_dir")"
done
if [[ -z "$setup_dir" ]]; then
echo "setupenv.sh not found in hierarchy."
exit 1
else
echo "Found setupenv.sh in: $setup_dir"
fi
source $(Build.SourcesDirectory)/uhddev/.ci/fpga/scripts/run_setup.sh $setup_dir
echo "---- Run build: ${{ cpldBuild.displayName }} ----"
cd ${{ cpldBuild.workingDirectory }}
make
workingDirectory: uhddev/fpga/usrp3
env:
PATCHES_PATH: $(sdr-vivado-patches)
displayName: ${{ cpldBuild.displayName }}
# Publish the final result only if all previous steps passed
- publish: uhddev/fpga/usrp3/${{ cpldBuild.workingDirectory }}/build
artifact: ${{ cpldBuild.artifactName }}
displayName: 'Publish ${{ cpldBuild.displayName }}'
# Publish CPLD build intermediate files on request (even if the build failed)
# Publish uhddev/fpga/usrp3/${{ cpldBuild.workingDirectory }}/build-*
- bash: |
cd ${{ cpldBuild.workingDirectory }}
cp -r build-* $(Build.ArtifactStagingDirectory)
workingDirectory: uhddev/fpga/usrp3
env:
PATCHES_PATH: $(sdr-vivado-patches)
displayName: 'Copy build directories'
condition: and(always(), eq('${{ parameters.publish_int_files }}', true))
- publish: $(Build.ArtifactStagingDirectory)
artifact: '${{ cpldBuild.artifactName }}_Build_Directory Attempt $(System.JobAttempt)'
displayName: 'Publish ${{ cpldBuild.displayName }} Directory'
condition: and(always(), eq('${{ parameters.publish_int_files }}', true))
# Check if CPLD build left any untracked files.
- template: check_clean_repo_steps.yml
parameters:
directory: uhddev/

View File

@ -1,67 +0,0 @@
#
# Copyright 2021 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Description:
#
# This template is used to build the MB CPLD within the uhddev repository.
# Exports the CPLD build results (from build directory) as artifacts 'MB CPLD
# image'.
#
# See description for the parameters below.
#
parameters:
### Optional parameters
# Set to true if the intermediate files from build-<target> directory should
# be exported for debugging as artifact 'MB CPLD build (<attempt>)'
- name: debug
type: boolean
default: false
# Checkout repository in a clean state as described in
# https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#checkout
- name: clean
type: boolean
default: true
jobs:
- job: MB_CPLD
displayName: 'Build MB CPLD'
pool:
name: de-dre-lab
demands:
- ettus_fpga_build
- quartus18.1_lite
timeoutInMinutes: 30
steps:
# Currently limited to be executed in same repo.
# Removes all unversioned files if necessary.
# Checkout path defined by single repository case in
# https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/multi-repo-checkout?view=azure-devops#checkout-path
- checkout: self
clean: ${{ parameters.clean }}
# Run CPLD build
# Increase license server timeout as there might appear timeouts during
# static timing analysis which end up setting the build to fail.
- script: |
call set FLEXLM_TIMEOUT=20000000
call make
workingDirectory: $(Agent.BuildDirectory)/s/fpga/usrp3/top/x400/cpld
displayName: 'Build CPLD'
# Publish the final result only if all previous steps passed
- publish: $(Agent.BuildDirectory)/s/fpga/usrp3/top/x400/cpld/build
artifact: 'MB CPLD image'
displayName: 'Publish CPLD'
# always publish intermediate files
- publish: $(Agent.BuildDirectory)/s/fpga/usrp3/top/x400/cpld/output_files
artifact: 'MB CPLD build ($(System.JobAttempt))'
condition: and(always(), eq('${{ parameters.debug }}', true))
displayName: 'Publish Build Directory'
# Check if FPGA build left any untracked files.
- ${{ if eq(parameters.debug, true) }}:
- template: check_clean_repo_steps.yml

View File

@ -1,67 +0,0 @@
#
# Copyright 2021 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
# Description:
#
# This template is used to build the ZBX daughterboard CPLD within the uhddev
# repository. Exports the CPLD build results (from build directory) as
# artifacts 'ZBX CPLD image'.
#
# See description for the parameters below.
#
parameters:
### Optional parameters
# Set to true if the intermediate files from build-<target> directory should
# be exported for debugging as artifact 'ZBX CPLD build (<attempt>)'
- name: debug
type: boolean
default: false
# Checkout repository in a clean state as described in
# https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema#checkout
- name: clean
type: boolean
default: true
jobs:
- job: ZBX_CPLD
displayName: 'Build ZBX CPLD'
pool:
name: de-dre-lab
demands:
- ettus_fpga_build
- quartus18.1_lite
timeoutInMinutes: 30
steps:
# Currently limited to be executed in same repo.
# Removes all unversioned files if necessary.
# Checkout path defined by single repository case in
# https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/multi-repo-checkout?view=azure-devops#checkout-path
- checkout: self
clean: ${{ parameters.clean }}
# Run CPLD build
# Increase license server timeout as there might appear timeouts during
# static timing analysis which end up setting the build to fail.
- script: |
call set FLEXLM_TIMEOUT=20000000
call make
workingDirectory: $(Agent.BuildDirectory)/s/fpga/usrp3/top/x400/dboards/zbx/cpld
displayName: 'Build CPLD'
# Publish the final result only if all previous steps passed
- publish: $(Agent.BuildDirectory)/s/fpga/usrp3/top/x400/dboards/zbx/cpld/build
artifact: 'ZBX CPLD image'
displayName: 'Publish CPLD'
# Always publish intermediate files
- publish: $(Agent.BuildDirectory)/s/fpga/usrp3/top/x400/dboards/zbx/cpld/output_files
artifact: 'ZBX CPLD build ($(System.JobAttempt))'
condition: and(always(), eq('${{ parameters.debug }}', true))
displayName: 'Publish Build Directory'
# Check if FPGA build left any untracked files.
- ${{ if eq(parameters.debug, true) }}:
- template: check_clean_repo_steps.yml

View File

@ -21,6 +21,8 @@ def do_setup():
rootapi.add_tool(name="hwtools", version="head")
rootapi.add_tool(name="Vivado", version="2021.1", allowlater=False)
rootapi.add_tool(name="modelsim", version="2020.4", allowlater=True)
rootapi.add_tool(name="Diamond", version="3.12" , allowlater=True)
rootapi.add_tool(name="Quartus", version="20.1" , allowlater=True)
def do_finish():
pass

View File

@ -485,6 +485,29 @@ stages:
### END: Testbenches stage
### START: CPLD Build Stage
- stage: build_cpld_stage
displayName: x4xx CPLD Build Stage
dependsOn: analyze_changeset
condition: >
and(succeeded(),
contains(dependencies.analyze_changeset.outputs['analyze.gen_testlist.UhdTestList'], 'fpga.usrp3.cpld.x4xx')
)
jobs:
- template: ../fpga/templates/job-build-cpld.yml
parameters:
publish_int_files: true
cpldBuilds:
- displayName: 'MB CPLD Build'
workingDirectory: './top/x400/cpld'
artifactName: 'CPLD_MB'
- displayName: 'ZBX CPLD Build'
workingDirectory: './top/x400/dboards/zbx/cpld'
artifactName: 'CPLD_ZBX'
### END: CPLD Build Stage
- template: ../fpga/templates/job-build-fpga-all.yml
parameters:
clean_ip_build: ${{ parameters.clean_ip_build }}

View File

@ -45,6 +45,10 @@ parameters:
type: boolean
displayName: Build X440
default: false
- name: build_x4xx_cplds
type: boolean
displayName: Build X4xx CPLDs
default: false
- name: package_and_publish_images
type: boolean
displayName: Package & Publish Images
@ -137,14 +141,15 @@ extends:
parameters:
add_tests: ${{
format(
'{0};{1};{2};{3};{4};{5};{6};',
'{0};{1};{2};{3};{4};{5};{6};{7};',
iif(parameters.run_testbenches,'fpga.usrp3.testbenches',''),
iif(parameters.build_x3x0,'fpga.usrp3.x3xx',''),
iif(parameters.build_n3xx,'fpga.usrp3.n3xx',''),
iif(parameters.build_e31x,'fpga.usrp3.e31x',''),
iif(parameters.build_e32x,'fpga.usrp3.e32x',''),
iif(parameters.build_x410,'fpga.usrp3.x410',''),
iif(parameters.build_x440,'fpga.usrp3.x440','')
iif(parameters.build_x440,'fpga.usrp3.x440',''),
iif(parameters.build_x4xx_cplds,'fpga.usrp3.cpld.x4xx','')
)
}}
skip_rule_checking: true

View File

@ -229,6 +229,7 @@
add:
- fpga.usrp3.all
- uhd.rfnoc_modtool.all
- fpga.usrp3.cpld.x4xx
# image builder changes
- re: host/utils/rfnoc_image_builder.py
@ -287,6 +288,17 @@
add:
- fpga.usrp3.n3xx
# CPLD related changes
- re: fpga/usrp3/top/x400/cpld
add:
- fpga.usrp3.cpld.x4xx
- re: fpga/usrp3/top/x400/dboards
add:
- fpga.usrp3.cpld.x4xx
- re: fpga/usrp3/top/x400/constraints/timing/shared_constants.sdc
add:
- fpga.usrp3.cpld.x4xx
###############################################################################
# CI CHANGES
###############################################################################
@ -329,9 +341,16 @@
- uhd.rfnoc_modtool.all
- re: fpga/.ci/templates*
- re: fpga/.ci/templates
add:
- fpga.usrp3.all
- fpga.usrp3.cpld.x4xx
- fpga.usrp3.testbenches
- re: fpga/.ci/scripts
add:
- fpga.usrp3.all
- fpga.usrp3.cpld.x4xx
- fpga.usrp3.testbenches
# Device-specific pipeline changes.
- re: .ci/fpga/devices/job-build-x400.yml
add: