Skip to content

V80 300mhz

V80 300mhz #1791

Workflow file for this run

# Copyright © 2019-2026
#
# Licensed under the Apache License, Version 2.0 (the "License").
#
# CI 2.0 — catalog-driven (see docs/designs/continuous_integration.md). The plan job reads
# ci/testcases/*.yaml via ci/testcase.py to emit (category x driver x xlen)
# cells for this event; each cell runs `pytest ci -m "<cat> and <driver>"` in its
# build tree. Tests are data; blackbox.sh stays the untouched executor.
name: CI
on:
push:
pull_request:
schedule:
- cron: '0 6 * * 1' # Mondays 06:00 UTC — full suite
workflow_dispatch:
inputs:
drivers:
description: "comma list: simx,rtlsim,xrtsim,opaesim (blank = all)"
default: ""
tier:
description: "comma list: smoke,full,nightly (blank = all)"
default: ""
env:
CCACHE_DISABLE: 1
jobs:
# ---------------------------------------------------------------------------
# plan — read the test cases and emit the (category x driver x xlen) matrix
# for this event. No build env; just PyYAML.
# ---------------------------------------------------------------------------
plan:
runs-on: ubuntu-22.04
outputs:
cells: ${{ steps.q.outputs.cells }}
run: ${{ steps.q.outputs.run }}
profile: ${{ steps.q.outputs.profile }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: pip install --quiet pyyaml
# Read the toolchain pin so we can probe its cache below. TOOLCHAIN_REV is
# the toolchain cache key; the build job's setup-vortex caches `tools` under
# `${{ runner.os }}-toolchain-<rev>-<profile>` (profile=lite for push/PR).
- name: Read toolchain rev
id: vers
run: |
source VERSION
echo "toolchain=$TOOLCHAIN_REV" >> "$GITHUB_OUTPUT"
# Probe (lookup-only, no download) whether the toolchain cache exists. A
# MISS — deleted, expired (GitHub's 7-day eviction), key changed via a
# VERSION bump, or first run — means the build job will REBUILD the
# toolchain, which affects every driver. We force full coverage on that.
- name: Probe toolchain cache
id: tc
uses: actions/cache/restore@v4
with:
path: tools
key: ${{ runner.os }}-toolchain-${{ steps.vers.outputs.toolchain }}-lite
lookup-only: true
- name: Plan matrix
id: q
env:
EVENT: ${{ github.event_name }}
IN_DRIVERS: ${{ github.event.inputs.drivers }}
IN_TIER: ${{ github.event.inputs.tier }}
TOOLCHAIN_CACHE_HIT: ${{ steps.tc.outputs.cache-hit }}
PUSH_BEFORE: ${{ github.event.before }}
PR_BASE: ${{ github.event.pull_request.base.sha }}
run: |
set -euo pipefail
# Driver/tier policy by event (workflow_dispatch overrides).
case "$EVENT" in
schedule) DRIVERS=""; TIER="" ;; # everything
pull_request) DRIVERS="simx,rtlsim"; TIER="smoke,full" ;;
push) DRIVERS="simx"; TIER="smoke" ;;
workflow_dispatch) DRIVERS="$IN_DRIVERS"; TIER="$IN_TIER" ;;
*) DRIVERS="simx"; TIER="smoke" ;;
esac
# Toolchain (re)built -> 100% coverage. If the toolchain cache missed
# (deleted / out-of-date / evicted / key changed / first run) the build
# will rebuild the toolchain, which affects EVERY driver — so validate
# them all (drivers="" tier="" = everything) instead of the event
# default. schedule is already full; workflow_dispatch is an explicit
# manual choice, so leave those.
if [ "$EVENT" = "push" ] || [ "$EVENT" = "pull_request" ]; then
if [ "${TOOLCHAIN_CACHE_HIT:-}" != "true" ]; then
echo "toolchain cache miss -> rebuild -> forcing 100% full coverage"
DRIVERS=""; TIER=""
fi
fi
# Change-aware driver escalation: simx is a separate C++ model and cannot
# exercise the RTL, so a change under hw/rtl, hw/dpi, sim/rtlsim|xrtsim|
# opaesim, or vendored RTL must force the matching sim driver in even on a
# push (which is otherwise simx-only). An indeterminate diff (zero/missing
# base, e.g. a new branch or force-push) escalates to full coverage.
if { [ "$EVENT" = "push" ] || [ "$EVENT" = "pull_request" ]; } && [ -n "$DRIVERS" ]; then
BASE="$PUSH_BEFORE"; [ "$EVENT" = "pull_request" ] && BASE="$PR_BASE"
ESC=$(python3 ci/testcase.py drivers --changed-from="$BASE" || echo ALL)
if [ "$ESC" = "ALL" ]; then
echo "indeterminate diff -> full driver coverage"; DRIVERS=""
elif [ -n "$ESC" ]; then
DRIVERS=$(printf '%s\n' "$DRIVERS" "$ESC" | tr ',' '\n' | grep . | sort -u | paste -sd,)
echo "RTL-affecting change -> drivers=$DRIVERS"
fi
fi
F=""
[ -n "$DRIVERS" ] && F="$F --drivers=$DRIVERS"
[ -n "$TIER" ] && F="$F --tier=$TIER"
cells=$(python3 ci/testcase.py matrix $F)
echo "cells=$cells" >> "$GITHUB_OUTPUT"
[ "$cells" = "[]" ] && echo "run=false" >> "$GITHUB_OUTPUT" || echo "run=true" >> "$GITHUB_OUTPUT"
# full toolchain (SST build + gem5) only when sst/gem5 are selected
if echo "$cells" | grep -qE '"(sst|gem5)"'; then echo "profile=full" >> "$GITHUB_OUTPUT"; else echo "profile=lite" >> "$GITHUB_OUTPUT"; fi
python3 ci/testcase.py lint
# ---------------------------------------------------------------------------
# setup — warm the shared toolchain + third_party caches ONCE (prepare=true),
# so a cold cache builds the toolchain a single time instead of once per xlen.
# No-op fast path on a cache hit. build/tests depend on this and only restore.
# ---------------------------------------------------------------------------
setup:
needs: plan
if: needs.plan.outputs.run == 'true'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Vortex
uses: ./.github/actions/setup-vortex
with:
profile: ${{ needs.plan.outputs.profile }}
prepare: true
# ---------------------------------------------------------------------------
# build — one build tree per xlen, shared by all that xlen's test cells.
# Toolchain + third_party are warmed by `setup`, so this only restores them.
# ---------------------------------------------------------------------------
build:
needs: [plan, setup]
if: needs.plan.outputs.run == 'true'
strategy:
matrix:
xlen: [32, 64]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup Vortex
uses: ./.github/actions/setup-vortex
with:
profile: ${{ needs.plan.outputs.profile }}
- name: Configure + build software/tests
run: |
TOOLDIR=$PWD/tools
mkdir -p build${{ matrix.xlen }} && cd build${{ matrix.xlen }}
../configure --tooldir=$TOOLDIR --xlen=${{ matrix.xlen }}
make software -s
make tests -s
- uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.xlen }}
path: build${{ matrix.xlen }}
# ---------------------------------------------------------------------------
# tests — one cell per (category, driver, xlen); pytest selects via markers.
# ---------------------------------------------------------------------------
tests:
needs: [plan, build]
if: needs.plan.outputs.run == 'true'
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.plan.outputs.cells) }}
runs-on: ubuntu-22.04
timeout-minutes: 180
steps:
- uses: actions/checkout@v4
- name: Setup Vortex
uses: ./.github/actions/setup-vortex
with:
profile: ${{ needs.plan.outputs.profile }}
- uses: actions/download-artifact@v4
with:
name: build-${{ matrix.xlen }}
path: build${{ matrix.xlen }}
- name: Per-category deps
run: |
case "${{ matrix.category }}" in
vulkan) sudo bash ./ci/install_dependencies.sh --vulkan ;;
mpi) sudo bash ./ci/install_dependencies.sh --mpi ;;
gem5) sudo bash ./ci/install_dependencies.sh --gem5 ;;
esac
- name: Run cell
run: |
cd build${{ matrix.xlen }}
chmod -R +x .
EXPR="${{ matrix.category }}"
[ "${{ matrix.driver }}" != "host" ] && EXPR="$EXPR and ${{ matrix.driver }}"
# A cross-cutting check (model_parity, perf_gate) has its own dedicated
# cell whose `-m <check>` sweeps every such case catalog-wide; exclude
# those cases from every OTHER category's cell so each runs once, not
# twice. The check list comes from the planner, never a copy of it.
for c in $(python3 ci/testcase.py checks); do
[ "${{ matrix.category }}" = "$c" ] && continue
EXPR="$EXPR and not $c"
done
VX_XLEN=${{ matrix.xlen }} python3 -m pytest ci -m "$EXPR" --strict-markers \
-v \
--junitxml="$GITHUB_WORKSPACE/junit-${{ matrix.category }}-${{ matrix.driver }}-${{ matrix.xlen }}.xml"
- uses: actions/upload-artifact@v4
if: always()
with:
name: junit-${{ matrix.category }}-${{ matrix.driver }}-${{ matrix.xlen }}
path: junit-*.xml
complete:
runs-on: ubuntu-22.04
needs: [plan, setup, build, tests]
if: always()
steps:
- name: Gate
run: |
if ${{ contains(needs.*.result, 'failure') }}; then
echo "A required job failed."; exit 1
fi
echo "CI complete (tests: ${{ needs.tests.result }})."