Skip to content

Add FINC/FDEC test #2466

Add FINC/FDEC test

Add FINC/FDEC test #2466

Workflow file for this run

# SPDX-FileCopyrightText: 2022-2023 Google LLC
#
# SPDX-License-Identifier: Apache-2.0
name: CI
# XXX: What we'd really like is run on every pull request / pull request change,
# which allows GitHub to cancel runs after (force) pushes. Triggering on
# these seems to be broken since January 19th 2023 however. Note that not
# everyone likes auto-cancellation so we should probably recognize [no-skip]
# commits.
on:
schedule:
# Works out to be approx midnight (CET/CEST) accounting for UTC offset and
# GitHub scheduling. See the comment at 'branches-ignore' for more
# information on our development flow. This job will run in context of the
# branch 'staging'.
- cron: '0 19 * * *'
push:
branches-ignore:
# Developers request to merge their changes into 'staging'. In order to
# do so, relatively cheap tests should pass CI. Every night, CI runs our
# full test suite on 'staging'. If these pass, a pull request may be
# created to get 'main' up to date with 'staging'. Note that this should
# be automated in the future, but this will require some engineering.
- 'staging'
- 'main'
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
license-check:
runs-on: [self-hosted, compute]
container:
image: ubuntu:22.04
steps:
- uses: actions/checkout@v3
- name: REUSE Compliance Check
uses: fsfe/reuse-action@v1
lint:
name: Basic linting
runs-on: [self-hosted, compute]
container:
image: ubuntu:22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install dependencies
run: |
.github/scripts/set_de_mirror.sh
apt-get update
apt-get install -y pcregrep python3-yaml
- name: EOL whitespace
run: |
.github/scripts/check_eol_whitespace.sh
- name: Enforce EOF newline
run: |
.github/scripts/check_missing_eof_newline.sh
- name: Check that all self-hosted jobs run in a docker container
run: |
.github/scripts/self_hosted_docker_check.py
- name: Check that the 'all' job depends on all other jobs
run: |
.github/scripts/all_check.py
build:
name: Build dependencies
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set CI flags
run: |
cp .github/cabal.project.simulation cabal.project.local
- name: Update Cabal index info
run: |
cabal update
cabal freeze
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cabal-nix/store
key: packages-cachebust-3-${{ hashFiles('cabal.project.freeze') }}
restore-keys: packages-
- name: Build
run: |
cabal build all --only-dependencies
elastic-buffer-sim-topologies-matrix:
name: elastic-buffer-sim-topologies simulation matrix generation
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure --keep "GITHUB_OUTPUT"
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Generate matrix
run: |
if [[ "${{ github.event_name }}" == "schedule" || $(.github/scripts/force_expensive_checks.sh) == "true" ]]; then
cp .github/simulation/all.json sim.json
else
cp .github/simulation/staging.json sim.json
fi
- name: Set simulation matrix
id: set-sim-matrix
run: |
echo "sim_matrix=$(cat sim.json | jq -c)" | tee -a "$GITHUB_OUTPUT"
echo "artifact_names=$(cat sim.json | jq -c '["gen-plots-hs-" + .[].topology]')" | tee -a "$GITHUB_OUTPUT"
outputs:
sim_matrix: ${{ steps.set-sim-matrix.outputs.sim_matrix }}
artifact_names: ${{ steps.set-sim-matrix.outputs.artifact_names }}
elastic-buffer-sim-topologies:
name: Simulate network
runs-on: [self-hosted, compute]
timeout-minutes: 840
defaults:
run:
shell: git-nix-shell {0} --pure
needs: [build, lint, elastic-buffer-sim-topologies-matrix]
strategy:
matrix:
target: ${{ fromJson(needs.elastic-buffer-sim-topologies-matrix.outputs.sim_matrix) }}
fail-fast: false
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set CI flags
run: |
cp .github/cabal.project.simulation cabal.project.local
- name: Update Cabal index info
run: |
cabal update
cabal freeze
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cabal-nix/store
key: packages-cachebust-3-${{ hashFiles('cabal.project.freeze') }}
restore-keys: packages-cachebust-3-
fail-on-cache-miss: true
- name: Plot mesh grid
run: |
cabal run -- elastic-buffer-sim:sim \
+RTS -M${{ matrix.target.hmem }}M -RTS \
--output-mode pdf \
--steps ${{ matrix.target.steps }} \
--samples 1000 \
--max-startup-offset 2000 \
--stop-after-stable ${{ matrix.target.steps }} \
${{ matrix.target.topology }} ${{ matrix.target.args }}
- name: Generate report
if: always()
run: |
sed -i -e "s/n\([0-9]*\)/\1/g" _build/topology.gv
dot2tex \
-f tikz \
--figonly \
--progoptions "-K neato" \
--nodeoptions "every node/.style={fill,text=white,font=\Large\tt,minimum size=2em,inner sep=0pt}" \
--edgeoptions "line width=0.3em" \
_build/topology.gv > _build/topology.tikz
cp .github/simulation/report-template.tex _build/report.tex
export RUNREF="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
echo "$(date +'%Y-%m-%d %H:%M:%S')" > _build/datetime
echo "\\textit{\\href{$RUNREF}{$RUNREF}}" > _build/runref
cd _build
lualatex report.tex
rm -Rf report.{aux,log,out,tex} runref datetime topology.tikz
- name: Upload plots
uses: actions/upload-artifact@v3
if: always()
with:
name: gen-plots-hs-${{ matrix.target.topology }}
path: _build
retention-days: 14
generate-full-clock-control-simulation-report:
name: Generate clock control simulation report
runs-on: [self-hosted, compute]
if: always()
needs: [build, lint, elastic-buffer-sim-topologies-matrix, elastic-buffer-sim-topologies]
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Download simulation artifacts
uses: actions/download-artifact@v3
with:
# Note that all artifacts are downloaded, if no 'name' is specified.
# Unfortunately, this is the only working solution that github offers
# right at the moment. Alternative options exist, like
# https://github.com/marketplace/actions/download-multiple-workflow-artifacts,
# but this action is currently broken. Once a working solution
# is available again, 'artifact_names' from
# 'elastic-buffer-sim-topologies-matrix' can be used to only download
# the required artifacts instead.
path: artifacts
- name: Generate final report
shell: git-nix-shell {0} --pure
run: |
set +f # Enable globbing
pdfunite artifacts/*/report.pdf report.pdf
- name: Upload report
uses: actions/upload-artifact@v3
with:
name: Clock Control Simulation Report
path: report.pdf
retention-days: 14
elastic-buffer-sim-tests:
name: elastic-buffer-sim unittests
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure
needs: [build, lint]
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set CI flags
run: |
cp .github/cabal.project.simulation cabal.project.local
- name: Update Cabal index info
run: |
cabal update
cabal freeze
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cabal-nix/store
key: packages-cachebust-3-${{ hashFiles('cabal.project.freeze') }}
restore-keys: packages-cachebust-3-
fail-on-cache-miss: true
- name: Run unittests
run: |
cabal run elastic-buffer-sim:unittests
bittide-tests:
name: Bittide tests
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure
needs: [build, lint]
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set CI flags
run: |
cp .github/cabal.project.simulation cabal.project.local
- name: Update Cabal index info
run: |
cabal update
cabal freeze
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cabal-nix/store
key: packages-cachebust-3-${{ hashFiles('cabal.project.freeze') }}
restore-keys: packages-cachebust-3-
fail-on-cache-miss: true
- name: Unittests
run: |
# While Hedgehog can fill many cores with "work", it doesn't actually
# speed up the tests.
cabal run -- bittide:unittests -j 1 +RTS -N2
- name: Bittide Doctests
run: |
cabal run -- bittide:doctests
- name: Bittide.Extra Doctests
run: |
cabal run -- bittide-extra:doctests
firmware-lints:
name: Firmware Lints
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Rust formatting
run: |
cargo fmt --all -- --check
- name: Clippy check
run: |
cargo clippy --target riscv32imc-unknown-none-elf --all-features
- name: Rust formatting (firmware examples)
run: cargo fmt --all -- --check
working-directory: firmware/examples/
- name: Clippy check (firmware examples)
run: |
cargo clippy --target riscv32imc-unknown-none-elf --all-features
working-directory: firmware/examples/
firmware-unit-tests:
name: Firmware Unit Tests
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
needs: [build]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set CI flags
run: |
cp .github/cabal.project.simulation cabal.project.local
- name: Update Cabal index info
run: |
cabal update
cabal freeze
- name: Cabal Cache
uses: actions/cache@v3
with:
path: |
~/.cabal-nix/store
key: packages-cachebust-3-${{ hashFiles('cabal.project.freeze') }}
restore-keys: packages-cachebust-3-
fail-on-cache-miss: true
- uses: actions/cache@v3
name: Cargo Cache
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: cargo-cache-cachebust-2-${{ hashFiles('Cargo.lock') }}
- name: Build program-stream executable
run: |
cabal build program-stream
- name: Running Tests
run: |
cargo test --target x86_64-unknown-linux-gnu --all
firmware-build-examples:
name: Firmware Build Examples
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/cache@v3
name: Cache
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
./target/
./firmware/examples/target/
key: cargo-cache-cachebust-2-${{ hashFiles('Cargo.lock') }}
- name: Building Examples
run: cargo build --release
working-directory: firmware/examples/
firmware-limit-checks:
name: Firmware Limit Checks
runs-on: [self-hosted, compute]
needs: [firmware-build-examples]
defaults:
run:
shell: git-nix-shell {0} --pure
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/cache@v3
name: Cache
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
./target/
./firmware/examples/target/
key: cargo-cache-cachebust-2-${{ hashFiles('Cargo.lock') }}
- name: Install `elf-limits`
run: cargo install --git https://github.com/cuddlefishie/elf-limits
- name: Checking firmware example limits
run: |
~/.cargo/bin/elf-limits \
--instruction-mem-limit 64K \
--data-mem-limit 64K \
firmware/examples/target/riscv32imc-unknown-none-elf/release/hello \
firmware/examples/target/riscv32imc-unknown-none-elf/release/fdt-read
bittide-instances-doctests:
name: bittide-instances doctests
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure
needs: [build, lint]
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set CI flags
run: |
cp .github/cabal.project.formal cabal.project.local
- name: Update Cabal index info
run: |
cabal update
cabal freeze
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cabal-nix/store
key: packages-cachebust-3-${{ hashFiles('cabal.project.freeze') }}
restore-keys: packages-cachebust-3-
fail-on-cache-miss: true
- name: Doctests
run : |
cabal run -- bittide-instances:doctests
bittide-instances-unittests:
name: bittide-instances unittests
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure
needs: [build, lint]
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set CI flags
run: |
cp .github/cabal.project.formal cabal.project.local
- name: Update Cabal index info
run: |
cabal update
cabal freeze
- name: Cache
uses: actions/cache@v3
with:
path: |
~/.cabal-nix/store
key: packages-cachebust-3-${{ hashFiles('cabal.project.freeze') }}
restore-keys: packages-cachebust-3-
fail-on-cache-miss: true
- name: Unit tests
run : |
cabal run -- bittide-instances:unittests
bittide-instances-hdl-matrix:
name: bittide-instances synthesis matrix generation
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure --keep "GITHUB_OUTPUT"
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Generate matrix
run: |
if [[ "${{ github.event_name }}" == "schedule" || $(.github/scripts/force_expensive_checks.sh) == "true" ]]; then
cp .github/synthesis/all.json checks.json
else
cp .github/synthesis/staging.json checks.json
fi
- name: Set test matrix
id: set-matrix
run: |
echo "check_matrix=$(cat checks.json | tr '\n' ' ')" | tee -a "$GITHUB_OUTPUT"
outputs:
check_matrix: ${{ steps.set-matrix.outputs.check_matrix }}
bittide-instances-hardware-in-the-loop-test-matrix:
name: bittide-instances hardware-in-the-loop test matrix generation
runs-on: [self-hosted, compute]
defaults:
run:
shell: git-nix-shell {0} --pure --keep "GITHUB_OUTPUT"
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Generate matrix
run: |
if [[ "${{ github.event_name }}" == "schedule" || $(.github/scripts/force_expensive_checks.sh) == "true" ]]; then
cp .github/synthesis/all.json checks.json
else
cp .github/synthesis/staging.json checks.json
fi
jq '[.[] | select(.stage=="test")]' checks.json > checks.json.filtered
cp checks.json.filtered checks.json
- name: Set test matrix
id: set-matrix
run: |
echo "check_matrix=$(cat checks.json | tr '\n' ' ')" | tee -a "$GITHUB_OUTPUT"
outputs:
check_matrix: ${{ steps.set-matrix.outputs.check_matrix }}
bittide-instances-hdl:
name: bittide-instances synthesis
runs-on: [self-hosted, compute]
defaults:
run:
# We leave out '--pure', as 'with_vivado.sh' relies on basic Ubuntu
shell: git-nix-shell {0}
env:
SYNTHESIS_BOARD: xilinx.com:kcu105:part0:1.7
# SYNTHESIS_PART: xcku040-ffva1156-2-e
# SYNTHESIS_PART: xcku035-ffva1156-2-e
needs: [build, lint, bittide-instances-hdl-matrix]
strategy:
matrix:
target: ${{ fromJson(needs.bittide-instances-hdl-matrix.outputs.check_matrix) }}
fail-fast: false
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
volumes:
- /opt/tools:/opt/tools
options: --mac-address="6c:5a:b0:6c:13:0b"
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Extract branch name
shell: bash
run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
id: extract_branch
- name: Set CI flags
run: |
# We use the same flags as the 'build' step to reuse caches. This
# "simulation" config only sets altopts on the Risc core, which we
# don't synthesize yet.
#
# TODO: Either switch to VexRisc or update cache strategy.
#
cp .github/cabal.project.simulation cabal.project.local
- name: Update Cabal index info
run: |
cabal update
cabal freeze
- name: Cache Cabal store
uses: actions/cache@v3
with:
path: |
~/.cabal-nix/store
key: packages-cachebust-3-${{ hashFiles('cabal.project.freeze') }}
restore-keys: packages-cachebust-3-
fail-on-cache-miss: true
- name: Cache Shake build directory
uses: actions/cache@v3
with:
path: |
_build
key: shake-build-cachebust-3-${{ matrix.target.top }}-${{ steps.extract_branch.outputs.branch }}-${{ github.sha }}
restore-keys: |
shake-build-cachebust-3-${{ matrix.target.top }}-${{ steps.extract_branch.outputs.branch }}-
shake-build-cachebust-3-${{ matrix.target.top }}-
- name: HDL generation and synthesis
run : |
target="${{ matrix.target.stage }}"
if [[ "${target}" == "program" ]]; then
echo "Illegal Shake target on CI: program"
exit 1
fi
# Only the local runner connected to the bittide demonstrator (hoeve)
# should perform the jobs which need hardware access. And that runner
# should do only that, so we let other 'compute' runners do the
# bitstream generation.
if [[ "${{ matrix.target.stage }}" == "test" ]]; then
target="bitstream"
fi
.github/scripts/with_vivado.sh cabal run -- \
bittide-instances:shake \
${{ matrix.target.top }}:"${target}"
# Explicitly generate the Tcl scripts needed for programming and
# hardware testing.
if [[ "${{ matrix.target.stage }}" == "test" ]]; then
# Local machine connected to the bittide demonstrator is called
# 'hoeve'. But the docker container of the runner cannot resolve
# DNS, so we use its local IP address instead.
export HW_SERVER_URL="192.168.102.130:3121"
dir=$(ls _build/vivado | grep -E '\.${{ matrix.target.top }}$')
tcl_test=_build/vivado/"${dir}"/run_hardware_test.tcl
tcl_program=_build/vivado/"${dir}"/run_board_program.tcl
cabal run shake -- "${tcl_test}" "${tcl_program}" --hardware-targets="${{ matrix.target.targets }}"
fi
- name: Archive build artifacts
uses: actions/upload-artifact@v3
with:
name: _build-${{ matrix.target.top }}
# We don't pack `ip`, as it is generally useless for debugging while
# also taking up a lot of space.
path: |
_build
!_build/vivado/*/ip
retention-days: 14
bittide-instances-hardware-in-the-loop:
name: bittide-instances hardware-in-the-loop tests
runs-on: [self-hosted, hardware-access]
defaults:
run:
# We leave out '--pure', as 'with_vivado.sh' relies on basic Ubuntu
shell: git-nix-shell {0}
needs: [bittide-instances-hdl, bittide-instances-hardware-in-the-loop-test-matrix]
strategy:
matrix:
target: ${{ fromJson(needs.bittide-instances-hardware-in-the-loop-test-matrix.outputs.check_matrix) }}
fail-fast: false
container:
image: ghcr.io/clash-lang/nixos-bittide-hardware:2023-06-30
volumes:
- /opt/tools:/opt/tools
steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: _build-${{ matrix.target.top }}
path: _build
- name: Run tests on hardware
run : |
dir=$(ls _build/vivado | grep -E '\.${{ matrix.target.top }}$')
tcl_test=_build/vivado/"${dir}"/run_hardware_test.tcl
tcl_program=_build/vivado/"${dir}"/run_board_program.tcl
.github/scripts/with_vivado.sh \
vivado -mode batch -source "${tcl_program}"
.github/scripts/with_vivado.sh \
vivado -mode batch -source "${tcl_test}"
all:
name: All jobs finished
if: always()
needs: [
bittide-instances-doctests,
bittide-instances-hardware-in-the-loop-test-matrix,
bittide-instances-hardware-in-the-loop,
bittide-instances-hdl-matrix,
bittide-instances-hdl,
bittide-instances-unittests,
bittide-tests,
build,
elastic-buffer-sim-tests,
elastic-buffer-sim-topologies-matrix,
elastic-buffer-sim-topologies,
firmware-build-examples,
firmware-limit-checks,
firmware-lints,
firmware-unit-tests,
generate-full-clock-control-simulation-report,
license-check,
lint,
]
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Check dependencies for failures
run: |
# Test all dependencies for success/failure
set -x
success="${{ contains(needs.*.result, 'success') }}"
fail="${{ contains(needs.*.result, 'failure') }}"
set +x
# Test whether success/fail variables contain sane values
if [[ "${success}" != "true" && "${success}" != "false" ]]; then exit 1; fi
if [[ "${fail}" != "true" && "${fail}" != "false" ]]; then exit 1; fi
# We want to fail if one or more dependencies fail. For safety, we introduce
# a second check: if no dependencies succeeded something weird is going on.
if [[ "${fail}" == "true" || "${success}" == "false" ]]; then
echo "One or more dependency failed, or no dependency succeeded."
exit 1
fi