Fix AD9681 output format to two's complement and update tests accordi… #3443
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ---------------------------------------------------------------------------- | |
| # Title : SURF GitHub Actions CI Script | |
| # ---------------------------------------------------------------------------- | |
| # This file is part of the 'SLAC firmware standard library'. It is subject to | |
| # the license terms in the LICENSE.txt file found in the top-level directory | |
| # of this distribution and at: | |
| # https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. | |
| # No part of the 'SLAC firmware standard library', including this file, may be | |
| # copied, modified, propagated, or distributed except according to the terms | |
| # contained in the LICENSE.txt file. | |
| # ---------------------------------------------------------------------------- | |
| # The following environment variables are required for this process: | |
| # secrets.GH_TOKEN | |
| # secrets.CONDA_UPLOAD_TOKEN_TAG | |
| name: CI | |
| # Triggers: every push runs the workflow (directory-scoped regression on | |
| # feature branches, full on pre-release/main/tags); PRs into main additionally | |
| # run it in full. | |
| # A feature branch with an open PR into main therefore runs the regression | |
| # job twice per push -- once selective (push ref) and once full (PR merge | |
| # ref). Distinct event/ref concurrency groups prevent push, PR, and manual | |
| # validation runs from cancelling one another. This is intentional: the push | |
| # run gives fast per-commit feedback and the PR run is the full pre-merge | |
| # release gate. In this repo feature branches normally target pre-release, so | |
| # the double run is confined to release PRs. The post-merge push to pre-release | |
| # is also full so the integration branch is checked after every feature merge. | |
| # Manual dispatch can simulate a changed-path list to exercise selective | |
| # execution on a runner; it does not alter the path source used by push or | |
| # pull-request events. | |
| on: | |
| push: | |
| pull_request: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| inputs: | |
| changed_files_override: | |
| description: Comma-separated paths used to exercise selective CI without changing push/PR policy | |
| required: false | |
| type: string | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # ---------------------------------------------------------------------------- | |
| lint: | |
| name: Linting | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: 3.12 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y make python3 python3-pip tclsh ghdl | |
| python -m pip install --upgrade pip | |
| python -m pip install -r pip_requirements.txt | |
| if [ -L ruckus ] && [ ! -d ruckus ]; then | |
| echo "Removing broken ruckus symlink from checkout" | |
| rm ruckus | |
| fi | |
| if [ ! -d ruckus ]; then | |
| git clone https://github.com/slaclab/ruckus.git ruckus | |
| fi | |
| python -m pip install -r ruckus/scripts/pip_requirements.txt | |
| - name: Check for trailing whitespace and tabs | |
| run: | | |
| if grep -rnI '[[:blank:]]$' --include=\*.{vhd,tcl,py} .; then | |
| echo "Error: Trailing whitespace found in the repository!" | |
| exit 1 | |
| fi | |
| if grep -rnI $'\t' --include=\*.{vhd,tcl,py} .; then | |
| echo "Error: Tab characters found in the repository! Please use spaces for indentation." | |
| exit 1 | |
| fi | |
| - name: Check for non-ASCII characters in VHDL | |
| run: | | |
| if LC_ALL=C grep -rnP '[^\x00-\x7F]' --include=\*.vhd .; then | |
| echo "Error: Non-ASCII characters found in VHDL source! Some tools (e.g. Cadence Genus) read VHDL with an ASCII codec and will fail. Please use plain ASCII (e.g. '-' instead of en/em dashes)." | |
| exit 1 | |
| fi | |
| - name: Python Linter Checking | |
| run: | | |
| python -m compileall -f python/ scripts/ tests/ | |
| flake8 --count python/ scripts/ tests/ | |
| - name: C/C++ Linter Checking | |
| run: | | |
| find . -name '*.h' -o -name '*.cpp' -o -name '*.c' | xargs cpplint | |
| - name: VHDL Linter Checking | |
| run: | | |
| source scripts/vsg_linter.sh | |
| - name: VHDL Syntax Checking | |
| run: | | |
| make MODULES=$PWD analysis | |
| # ---------------------------------------------------------------------------- | |
| test: | |
| name: Regression Tests | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: 3.12 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y make python3 python3-pip tclsh ghdl libzmq3-dev valgrind | |
| python -m pip install --upgrade pip | |
| python -m pip install -r pip_requirements.txt | |
| if [ -L ruckus ] && [ ! -d ruckus ]; then | |
| echo "Removing broken ruckus symlink from checkout" | |
| rm ruckus | |
| fi | |
| if [ ! -d ruckus ]; then | |
| git clone https://github.com/slaclab/ruckus.git ruckus | |
| fi | |
| python -m pip install -r ruckus/scripts/pip_requirements.txt | |
| - name: Determine run mode | |
| id: mode | |
| run: | | |
| if [[ "${{ github.event_name }}" == "pull_request" ]] \ | |
| || [[ "${{ github.ref }}" == "refs/heads/main" ]] \ | |
| || [[ "${{ github.ref }}" == "refs/heads/pre-release" ]] \ | |
| || [[ "${{ github.ref }}" == refs/tags/* ]]; then | |
| echo "value=full" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "value=selective" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Parallel Regression Tests | |
| env: | |
| CHANGED_FILES_OVERRIDE: ${{ inputs.changed_files_override }} | |
| run: | | |
| # Define the full regression universe once so integration runs and | |
| # selective-mode fallbacks cannot drift apart as suites are added. | |
| full_targets=( | |
| tests | |
| ) | |
| # tests/simlink is owned by the dedicated step below, which runs it | |
| # on every push with a bounded worker count. Exclude it here so the | |
| # unbounded -n auto never starves its multi-instance peer handshake | |
| # and so the suite is not run twice. | |
| full_ignores=( | |
| --ignore=tests/simlink | |
| ) | |
| # Import once before either run mode. The compliance check consumes | |
| # the same ruckus source inventory as the cocotb runner and fails | |
| # fast on new structural violations before expensive simulations. | |
| make MODULES=$PWD import | |
| python -m tests.common.compliance_audit check tests | |
| # Full integration/release runs build and simulate on apt mcode GHDL | |
| # and collect the coverage consumed by Codecov. | |
| if [[ "${{ steps.mode.outputs.value }}" == "full" ]]; then | |
| python -m pytest --cov -v -n auto --dist=worksteal "${full_ignores[@]}" "${full_targets[@]}" | |
| exit 0 | |
| fi | |
| # Feature-branch pushes compare with origin/pre-release and map | |
| # localized protocol/DSP/Ethernet paths to matching pytest | |
| # directories. Any foundational, build-control, deleted/renamed, | |
| # unknown, or otherwise indeterminate change emits FORCE_FULL. | |
| selector_args=() | |
| selection_source="git diff against origin/pre-release" | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]] \ | |
| && [[ -n "${CHANGED_FILES_OVERRIDE}" ]]; then | |
| selector_args+=(--changed-files-override "${CHANGED_FILES_OVERRIDE}") | |
| selection_source="manual changed-path simulation" | |
| fi | |
| if selector_output="$(python -m tests.common "${selector_args[@]}")"; then | |
| selector_rc=0 | |
| else | |
| selector_rc=$? | |
| fi | |
| echo "${selector_output}" | |
| if [[ "${selector_rc}" -ne 0 ]] || grep -qx "FORCE_FULL" <<< "${selector_output}"; then | |
| echo "Directory selector forced a full run (rc=${selector_rc})" | |
| { | |
| echo "### Regression selection" | |
| echo | |
| echo "- Source: ${selection_source}" | |
| echo "- Result: full regression" | |
| } >> "${GITHUB_STEP_SUMMARY}" | |
| python -m pytest -v -n auto --dist=worksteal "${full_ignores[@]}" "${full_targets[@]}" | |
| else | |
| # tests/common contains the selector's policy tests and always runs | |
| # alongside any directory-owned cocotb targets. | |
| targets=(tests/common) | |
| if [[ -n "${selector_output}" ]]; then | |
| mapfile -t selected < <(printf '%s\n' "${selector_output}") | |
| targets+=("${selected[@]}") | |
| else | |
| echo "No directory-owned cocotb tests for this change set -- running tests/common only." | |
| fi | |
| { | |
| echo "### Regression selection" | |
| echo | |
| echo "- Source: ${selection_source}" | |
| echo "- Result: selective regression" | |
| echo "- Pytest targets: \`${targets[*]}\`" | |
| } >> "${GITHUB_STEP_SUMMARY}" | |
| python -m pytest -v -n auto --dist=worksteal "${targets[@]}" | |
| fi | |
| - name: SimLink Regression Tests | |
| # SimLink runs in its own step with a bounded worker count, and is | |
| # excluded from the step above in both full and selective mode. Its | |
| # native ctypes libraries and the multi-instance ZeroMQ traffic test are | |
| # timing-sensitive, and an unbounded -n auto on a many-core runner | |
| # over-subscribes badly enough to starve the multi-instance peer | |
| # handshake. Cap workers at min(nproc, 8): still ~2x faster than serial | |
| # on the hosted 4-core runner, without the high-concurrency starvation. | |
| # Unconditional: the path selector maps no path to tests/simlink, so a | |
| # selective feature-branch push would otherwise never exercise it. | |
| run: | | |
| python -m pytest --cov --cov-append -v \ | |
| -n "$(python -c 'import os; print(min(os.cpu_count() or 1, 8))')" \ | |
| --dist=worksteal tests/simlink | |
| - name: Code Coverage | |
| if: steps.mode.outputs.value == 'full' | |
| run: | | |
| codecov | |
| coverage report -m | |
| # ---------------------------------------------------------------------------- | |
| simlink_rogue: | |
| name: SimLink Rogue Contract | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 30 | |
| defaults: | |
| run: | |
| shell: bash -el {0} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Setup Miniforge | |
| uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1 | |
| with: | |
| miniforge-variant: Miniforge3 | |
| miniforge-version: latest | |
| activate-environment: surf-simlink-rogue | |
| environment-file: tests/simlink/rogue/conda.yml | |
| auto-activate: false | |
| conda-remove-defaults: true | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y make tclsh ghdl pkg-config libzmq3-dev | |
| python -m pip install --upgrade pip | |
| python -m pip install -r pip_requirements.txt | |
| if [ -L ruckus ] && [ ! -d ruckus ]; then | |
| echo "Removing broken ruckus symlink from checkout" | |
| rm ruckus | |
| fi | |
| if [ ! -d ruckus ]; then | |
| git clone https://github.com/slaclab/ruckus.git ruckus | |
| fi | |
| python -m pip install -r ruckus/scripts/pip_requirements.txt | |
| - name: Run production Rogue SimLink contract | |
| run: | | |
| python -c "import rogue, pyrogue; print(rogue.Version.current())" | |
| make MODULES="$PWD" import | |
| SIMLINK_ROGUE_PYTHON="$(command -v python)" \ | |
| python -m pytest -q -n 0 tests/simlink/rogue/test_RogueTcpMemoryRogue.py | |
| # ---------------------------------------------------------------------------- | |
| adc_ddr_rogue: | |
| name: ADC DDR Rogue Tests | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| defaults: | |
| run: | |
| shell: bash -el {0} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Setup Miniforge | |
| uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1 | |
| with: | |
| miniforge-variant: Miniforge3 | |
| miniforge-version: latest | |
| activate-environment: surf-rogue-test | |
| environment-file: conda-rogue.yml | |
| auto-activate: false | |
| conda-remove-defaults: true | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -r pip_requirements.txt | |
| - name: Run ADC DDR Rogue tests | |
| run: | | |
| python -c "import rogue, pyrogue; print(rogue.Version.current())" | |
| PYTHONPATH="$PWD/python" python -m pytest -q -n 0 \ | |
| tests/devices/analog_devices/test_AdcDdrCalibration.py \ | |
| tests/devices/analog_devices/test_AdcDdrModel.py | |
| # ---------------------------------------------------------------------------- | |
| docs: | |
| name: Documentation | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - name: Install documentation tools | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y doxygen doxygen-doc doxygen-latex doxygen-gui graphviz | |
| - name: Generate Documentation | |
| run: | | |
| doxygen Doxyfile | |
| - name: Deploy Documentation | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4.1.0 | |
| with: | |
| github_token: ${{ secrets.GH_TOKEN }} | |
| publish_dir: doxygen/html | |
| # ---------------------------------------------------------------------------- | |
| gen_release: | |
| needs: [lint, test, simlink_rogue, adc_ddr_rogue, docs] | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: slaclab/ruckus/.github/workflows/gen_release.yml@main | |
| with: | |
| version: '1.0.0' | |
| secrets: | |
| GH_TOKEN: ${{ secrets.GH_TOKEN }} | |
| # ---------------------------------------------------------------------------- | |
| conda_build_lib: | |
| needs: [lint, test, simlink_rogue, adc_ddr_rogue, docs] | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: slaclab/ruckus/.github/workflows/conda_build_lib.yml@main | |
| with: | |
| version: '1.0.0' | |
| secrets: | |
| CONDA_UPLOAD_TOKEN_TAG: ${{ secrets.CONDA_UPLOAD_TOKEN_TAG }} | |
| # ---------------------------------------------------------------------------- |