Skip to content

ci: Add AHB controller tests to GitHub CI #873

ci: Add AHB controller tests to GitHub CI

ci: Add AHB controller tests to GitHub CI #873

# SPDX-License-Identifier: Apache-2.0
#
# I3C Core - Parallel Test and Documentation Workflow
#
# This workflow runs cocotb verification tests in parallel for AHB, AXI,
# AXI-Controller, and AHB-controller bus configurations, then builds and
# deploys documentation.
#
# Architecture:
# 1. generate-timing-docs: Generates timing CSR markdown documents
# 2. generate-matrix: Uses nox's JSON output to discover test sessions
# 3. tests-ahb: Runs all AHB-tagged tests in parallel (one job per test)
# 4. tests-ahb-controller-and-target: Runs all AHB-Controller tests in parallel
# 5. tests-ahb-controller-only: Runs all AHB-Controller only tests in parallel
# 6. tests-axi: Runs all AXI-tagged tests in parallel (one job per test)
# 7. tests-axi-controller-and-target: Runs all AXI-Controller tests in parallel
# 8. tests-axi-controller-only: Runs all AXI-Controller only tests in parallel
# 9. test-results: Aggregates results from all test jobs
# 10. docs-build: Builds and deploys documentation (only after tests pass)
#
# Optional: Long-running tests (i3c_ahb_verify, i3c_axi_verify) can be split
# into individual parametrized runs by enabling SPLIT_TESTS in generate-matrix.
#
# The parallel execution reduces total CI time significantly.
name: Run Tests
on:
push:
pull_request:
permissions:
contents: write
env:
DEBIAN_FRONTEND: "noninteractive"
VERILATOR_VERSION: "v5.050"
WAVES: "0"
jobs:
# ===========================================================================
# Job: Generate Timing CSR Docs
# ===========================================================================
generate-timing-docs:
name: Generate timing docs
runs-on: ubuntu-latest
env:
I3C_ROOT_DIR: ${{ github.workspace }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install system dependencies
run: |
sudo apt -qqy update
sudo apt -qqy --no-install-recommends install \
wget curl help2man libfl-dev make g++ git bison flex gperf \
libreadline-dev libbz2-dev autoconf python3-dev python3-venv \
python3-jsonschema python3-yaml python3-sphinx python3-docopt
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Python dependencies
run: |
python -m pip install uv
uv sync
- name: Generate timing docs
run: |
mkdir -p doc/source
echo "" >> doc/source/timing_csr.md
python tools/timing/timings.py --freq=200e6 --target_name="FPGA" --md >> doc/source/timing_csr.md
echo "" >> doc/source/timing_csr.md
python tools/timing/timings.py --freq=500e6 --target_name="ASIC" --md >> doc/source/timing_csr.md
- name: Upload timing docs artifact
uses: actions/upload-artifact@v4
with:
name: timing-csr-docs
path: doc/source/timing_csr.md
# ===========================================================================
# Job: Generate Test Matrix
# ===========================================================================
generate-matrix:
name: Generate test matrix
runs-on: ubuntu-latest
outputs:
ahb-matrix: ${{ steps.gen.outputs.ahb_matrix }}
ahb-controller-and-target-matrix: ${{ steps.gen.outputs.ahb_controller_and_target_matrix }}
ahb-controller-only-matrix: ${{ steps.gen.outputs.ahb_controller_only_matrix }}
axi-matrix: ${{ steps.gen.outputs.axi_matrix }}
axi-controller-and-target-matrix: ${{ steps.gen.outputs.axi_controller_and_target_matrix }}
axi-controller-only-matrix: ${{ steps.gen.outputs.axi_controller_only_matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install nox and dependencies
run: |
pip install nox==2023.4.22 pyyaml
pip install -e tools/nox_utils
- name: Query nox for test sessions
id: gen
run: |
cd verification/cocotb
python3 << 'EOF'
import json
import subprocess
import os
import sys
# Long-running tests that should be split into individual parametrized runs
SPLIT_TESTS = {"i3c_ahb_verify", "i3c_axi_verify"}
# We set DUT_CONFIG to controller_and_target to force nox to
# expose all tests, so we can route them ourselves based on tags.
result = subprocess.run(
["nox", "-l", "--json", "-f", "noxfile.py"],
capture_output=True, text=True,
env={
**os.environ,
"PYTHONDONTWRITEBYTECODE": "1",
"DUT_CONFIG": "controller_and_target"
}
)
if result.returncode != 0:
print(f"nox failed with return code {result.returncode}", file=sys.stderr)
print(f"stderr: {result.stderr}", file=sys.stderr)
sys.exit(1)
if not result.stdout.strip():
print("nox returned empty output", file=sys.stderr)
print(f"stderr: {result.stderr}", file=sys.stderr)
sys.exit(1)
try:
sessions = json.loads(result.stdout)
except json.JSONDecodeError as e:
print(f"Failed to parse JSON: {e}", file=sys.stderr)
sys.exit(1)
ahb_tests = set()
ahb_controller_and_target_tests = set()
ahb_controller_only_tests = set()
axi_tests = set()
axi_controller_and_target_tests = set()
axi_controller_only_tests = set()
for session in sessions:
tags = session.get("tags", [])
if "tests" not in tags:
continue
name = session["name"]
if name in SPLIT_TESTS:
session_id = session["session"]
else:
session_id = name
# Check for specific role/bus tags
has_ahb = "ahb" in tags
has_axi = "axi" in tags
has_controller = "controller" in tags
has_target = "target" in tags
if has_ahb:
if has_controller:
# If it has a controller tag, it always runs in the combined job
ahb_controller_and_target_tests.add(session_id)
# Exclude tests that also require a target from the controller_only job
if not has_target:
ahb_controller_only_tests.add(session_id)
else:
# Standard AHB tests (target-only, no controller tag)
ahb_tests.add(session_id)
if has_axi:
if has_controller:
# If it has a controller tag, it always runs in the combined job
axi_controller_and_target_tests.add(session_id)
# Exclude tests that also require a target from the controller_only job
if not has_target:
axi_controller_only_tests.add(session_id)
else:
# Standard AXI tests (target-only, no controller tag)
axi_tests.add(session_id)
# Sort for consistent ordering
ahb_tests = sorted(ahb_tests)
ahb_controller_and_target_tests = sorted(ahb_controller_and_target_tests)
ahb_controller_only_tests = sorted(ahb_controller_only_tests)
axi_tests = sorted(axi_tests)
axi_controller_and_target_tests = sorted(axi_controller_and_target_tests)
axi_controller_only_tests = sorted(axi_controller_only_tests)
print(f"Discovered {len(ahb_tests)} AHB tests")
print(f"Discovered {len(ahb_controller_and_target_tests)} AHB-Controller+Target tests")
print(f"Discovered {len(ahb_controller_only_tests)} AHB-Controller-Only tests")
print(f"Discovered {len(axi_tests)} AXI (Target-Only) tests")
print(f"Discovered {len(axi_controller_and_target_tests)} AXI-Controller+Target tests")
print(f"Discovered {len(axi_controller_only_tests)} AXI-Controller-Only tests")
with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
f.write(f"ahb_matrix={json.dumps(ahb_tests)}\n")
f.write(f"ahb_controller_and_target_matrix={json.dumps(ahb_controller_and_target_tests)}\n")
f.write(f"ahb_controller_only_matrix={json.dumps(ahb_controller_only_tests)}\n")
f.write(f"axi_matrix={json.dumps(axi_tests)}\n")
f.write(f"axi_controller_and_target_matrix={json.dumps(axi_controller_and_target_tests)}\n")
f.write(f"axi_controller_only_matrix={json.dumps(axi_controller_only_tests)}\n")
EOF
lint-testplans:
name: Lint Testplan Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Run Testplan Linter
run: |
export I3C_ROOT_DIR=$GITHUB_WORKSPACE
python tools/lint_testplan.py
# ===========================================================================
# Job: Run AHB Tests (Parallel)
# ===========================================================================
tests-ahb:
name: "AHB: ${{ matrix.test }}"
needs: [generate-matrix, lint-testplans]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test: ${{ fromJson(needs.generate-matrix.outputs.ahb-matrix) }}
steps:
- name: Install system dependencies
run: |
sudo apt -qqy update
sudo apt -qqy --no-install-recommends install \
help2man libfl-dev make g++ git bison flex gperf \
libreadline-dev libbz2-dev autoconf
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Cache Verilator installation
id: cache-verilator
uses: actions/cache@v4
with:
path: ~/verilator-install
key: verilator-install-${{ env.VERILATOR_VERSION }}-${{ runner.os }}
- name: Build Verilator (if not cached)
if: steps.cache-verilator.outputs.cache-hit != 'true'
run: |
git clone https://github.com/verilator/verilator -b ${{ env.VERILATOR_VERSION }}
cd verilator
autoconf
./configure --prefix=$HOME/verilator-install
make -j$(nproc)
make install
- name: Add Verilator to PATH
run: |
echo "$HOME/verilator-install/bin" >> $GITHUB_PATH
echo "VERILATOR_ROOT=$HOME/verilator-install/share/verilator" >> $GITHUB_ENV
- name: Setup Python environment (pyenv + dependencies)
run: ./install.sh
- name: Configure RTL and run test
id: run-test
env:
TEST_SESSION: ${{ matrix.test }}
run: |
source activate.sh
make config CFG_NAME=ahb_target_only
cd verification/cocotb && python -m nox -R -s "$TEST_SESSION" --no-venv --forcecolor
- name: Display test logs on failure
if: failure() && steps.run-test.outcome == 'failure'
run: |
echo "=== Test failed - displaying log files ==="
find verification/cocotb -name "*.log" -type f -exec sh -c \
'echo ""; echo "========================================"; echo "=== {} ==="; echo "========================================"; cat "{}"' \;
- name: Rename XML results to avoid collisions
if: always()
run: |
find verification/cocotb -name "*.xml" -exec sh -c 'mv "$1" "${1%.xml}_target_only_ahb.xml"' _ {} \;
- name: Sanitize artifact name
if: always()
id: sanitize
run: |
NAME='${{ matrix.test }}'
SANITIZED=$(echo "$NAME" | sed "s/[()='\" ,]/_/g" | sed 's/__*/_/g' | sed 's/_$//')
echo "name=$SANITIZED" >> $GITHUB_OUTPUT
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-ahb-${{ steps.sanitize.outputs.name }}
path: |
verification/cocotb/**/*.xml
verification/cocotb/**/*.log
# ===========================================================================
# Job: Run AHB-Controller and Target Tests (Parallel)
# ===========================================================================
tests-ahb-controller-and-target:
name: "AHB-Ctrl+Target: ${{ matrix.test }}"
needs: [generate-matrix, lint-testplans]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test: ${{ fromJson(needs.generate-matrix.outputs.ahb-controller-and-target-matrix) }}
steps:
- name: Install system dependencies
run: |
sudo apt -qqy update
sudo apt -qqy --no-install-recommends install \
help2man libfl-dev make g++ git bison flex gperf \
libreadline-dev libbz2-dev autoconf
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Cache Verilator installation
id: cache-verilator
uses: actions/cache@v4
with:
path: ~/verilator-install
key: verilator-install-${{ env.VERILATOR_VERSION }}-${{ runner.os }}
- name: Build Verilator (if not cached)
if: steps.cache-verilator.outputs.cache-hit != 'true'
run: |
git clone https://github.com/verilator/verilator -b ${{ env.VERILATOR_VERSION }}
cd verilator
autoconf
./configure --prefix=$HOME/verilator-install
make -j$(nproc)
make install
- name: Add Verilator to PATH
run: |
echo "$HOME/verilator-install/bin" >> $GITHUB_PATH
echo "VERILATOR_ROOT=$HOME/verilator-install/share/verilator" >> $GITHUB_ENV
- name: Setup Python environment (pyenv + dependencies)
run: ./install.sh
- name: Configure RTL and run test
id: run-test
env:
TEST_SESSION: ${{ matrix.test }}
CONTROLLER_SUPPORT: "1"
TARGET_SUPPORT: "1"
DUT_CONFIG: "controller_and_target"
CFG_NAME: "ahb_controller_and_target_sim"
I3C_ROOT_DIR: ${{ github.workspace }}
run: |
source activate.sh
make config CFG_NAME=ahb_controller_and_target_sim
cd verification/cocotb && python -m nox -R -s "$TEST_SESSION" --no-venv --forcecolor
- name: Display test logs on failure
if: failure() && steps.run-test.outcome == 'failure'
run: |
echo "=== Test failed - displaying log files ==="
find verification/cocotb -name "*.log" -type f -exec sh -c \
'echo ""; echo "========================================"; echo "=== {} ==="; echo "========================================"; cat "{}"' \;
- name: Sanitize artifact name
if: always()
id: sanitize
run: |
NAME='${{ matrix.test }}'
SANITIZED=$(echo "$NAME" | sed "s/[()='\" ,]/_/g" | sed 's/__*/_/g' | sed 's/_$//')
echo "name=$SANITIZED" >> $GITHUB_OUTPUT
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-ahb-controller-and-target-${{ steps.sanitize.outputs.name }}
path: |
verification/cocotb/**/*.xml
verification/cocotb/**/*.log
# ===========================================================================
# Job: Run AHB-Controller Only Tests (Parallel)
# ===========================================================================
tests-ahb-controller-only:
name: "AHB-Ctrl Only: ${{ matrix.test }}"
needs: [generate-matrix, lint-testplans]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test: ${{ fromJson(needs.generate-matrix.outputs.ahb-controller-only-matrix) }}
steps:
- name: Install system dependencies
run: |
sudo apt -qqy update
sudo apt -qqy --no-install-recommends install \
help2man libfl-dev make g++ git bison flex gperf \
libreadline-dev libbz2-dev autoconf
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Cache Verilator installation
id: cache-verilator
uses: actions/cache@v4
with:
path: ~/verilator-install
key: verilator-install-${{ env.VERILATOR_VERSION }}-${{ runner.os }}
- name: Build Verilator (if not cached)
if: steps.cache-verilator.outputs.cache-hit != 'true'
run: |
git clone https://github.com/verilator/verilator -b ${{ env.VERILATOR_VERSION }}
cd verilator
autoconf
./configure --prefix=$HOME/verilator-install
make -j$(nproc)
make install
- name: Add Verilator to PATH
run: |
echo "$HOME/verilator-install/bin" >> $GITHUB_PATH
echo "VERILATOR_ROOT=$HOME/verilator-install/share/verilator" >> $GITHUB_ENV
- name: Setup Python environment (pyenv + dependencies)
run: ./install.sh
- name: Configure RTL and run test
id: run-test
env:
TEST_SESSION: ${{ matrix.test }}
CONTROLLER_SUPPORT: "1"
TARGET_SUPPORT: "0"
DUT_CONFIG: "controller_only"
CFG_NAME: "ahb_controller_only_sim"
I3C_ROOT_DIR: ${{ github.workspace }}
run: |
source activate.sh
make config CFG_NAME=ahb_controller_only_sim
cd verification/cocotb && python -m nox -R -s "$TEST_SESSION" --no-venv --forcecolor
- name: Display test logs on failure
if: failure() && steps.run-test.outcome == 'failure'
run: |
echo "=== Test failed - displaying log files ==="
find verification/cocotb -name "*.log" -type f -exec sh -c \
'echo ""; echo "========================================"; echo "=== {} ==="; echo "========================================"; cat "{}"' \;
- name: Rename XML results to avoid collisions
if: always()
run: |
find verification/cocotb -name "*.xml" -exec sh -c 'mv "$1" "${1%.xml}_ctrl_only.xml"' _ {} \;
- name: Sanitize artifact name
if: always()
id: sanitize
run: |
NAME='${{ matrix.test }}'
SANITIZED=$(echo "$NAME" | sed "s/[()='\" ,]/_/g" | sed 's/__*/_/g' | sed 's/_$//')
echo "name=$SANITIZED" >> $GITHUB_OUTPUT
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-ahb-controller-only-${{ steps.sanitize.outputs.name }}
path: |
verification/cocotb/**/*.xml
verification/cocotb/**/*.log
# ===========================================================================
# Job: Run AXI Tests (Parallel)
# ===========================================================================
tests-axi:
name: "AXI: ${{ matrix.test }}"
needs: [generate-matrix, lint-testplans]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test: ${{ fromJson(needs.generate-matrix.outputs.axi-matrix) }}
steps:
- name: Install system dependencies
run: |
sudo apt -qqy update
sudo apt -qqy --no-install-recommends install \
help2man libfl-dev make g++ git bison flex gperf \
libreadline-dev libbz2-dev autoconf
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Cache Verilator installation
id: cache-verilator
uses: actions/cache@v4
with:
path: ~/verilator-install
key: verilator-install-${{ env.VERILATOR_VERSION }}-${{ runner.os }}
- name: Build Verilator (if not cached)
if: steps.cache-verilator.outputs.cache-hit != 'true'
run: |
git clone https://github.com/verilator/verilator -b ${{ env.VERILATOR_VERSION }}
cd verilator
autoconf
./configure --prefix=$HOME/verilator-install
make -j$(nproc)
make install
- name: Add Verilator to PATH
run: |
echo "$HOME/verilator-install/bin" >> $GITHUB_PATH
echo "VERILATOR_ROOT=$HOME/verilator-install/share/verilator" >> $GITHUB_ENV
- name: Setup Python environment (pyenv + dependencies)
run: ./install.sh
- name: Configure RTL and run test
id: run-test
env:
TEST_SESSION: ${{ matrix.test }}
run: |
source activate.sh
make config CFG_NAME=axi_target_only
cd verification/cocotb && python -m nox -R -s "$TEST_SESSION" --no-venv --forcecolor
- name: Display test logs on failure
if: failure() && steps.run-test.outcome == 'failure'
run: |
echo "=== Test failed - displaying log files ==="
find verification/cocotb -name "*.log" -type f -exec sh -c \
'echo ""; echo "========================================"; echo "=== {} ==="; echo "========================================"; cat "{}"' \;
- name: Sanitize artifact name
if: always()
id: sanitize
run: |
NAME='${{ matrix.test }}'
SANITIZED=$(echo "$NAME" | sed "s/[()='\" ,]/_/g" | sed 's/__*/_/g' | sed 's/_$//')
echo "name=$SANITIZED" >> $GITHUB_OUTPUT
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-axi-${{ steps.sanitize.outputs.name }}
path: |
verification/cocotb/**/*.xml
verification/cocotb/**/*.log
# ===========================================================================
# Job: Run AXI-Controller and Target Tests (Parallel)
# ===========================================================================
tests-axi-controller-and-target:
name: "AXI-Ctrl+Target: ${{ matrix.test }}"
needs: [generate-matrix, lint-testplans]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test: ${{ fromJson(needs.generate-matrix.outputs.axi-controller-and-target-matrix) }}
steps:
- name: Install system dependencies
run: |
sudo apt -qqy update
sudo apt -qqy --no-install-recommends install \
help2man libfl-dev make g++ git bison flex gperf \
libreadline-dev libbz2-dev autoconf
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Cache Verilator installation
id: cache-verilator
uses: actions/cache@v4
with:
path: ~/verilator-install
key: verilator-install-${{ env.VERILATOR_VERSION }}-${{ runner.os }}
- name: Build Verilator (if not cached)
if: steps.cache-verilator.outputs.cache-hit != 'true'
run: |
git clone https://github.com/verilator/verilator -b ${{ env.VERILATOR_VERSION }}
cd verilator
autoconf
./configure --prefix=$HOME/verilator-install
make -j$(nproc)
make install
- name: Add Verilator to PATH
run: |
echo "$HOME/verilator-install/bin" >> $GITHUB_PATH
echo "VERILATOR_ROOT=$HOME/verilator-install/share/verilator" >> $GITHUB_ENV
- name: Setup Python environment (pyenv + dependencies)
run: ./install.sh
- name: Configure RTL and run test
id: run-test
env:
TEST_SESSION: ${{ matrix.test }}
CONTROLLER_SUPPORT: "1"
TARGET_SUPPORT: "1"
DUT_CONFIG: "controller_and_target"
CFG_NAME: "axi_controller_and_target_sim"
I3C_ROOT_DIR: ${{ github.workspace }}
run: |
source activate.sh
make config CFG_NAME=axi_controller_and_target_sim
cd verification/cocotb && python -m nox -R -s "$TEST_SESSION" --no-venv --forcecolor
- name: Display test logs on failure
if: failure() && steps.run-test.outcome == 'failure'
run: |
echo "=== Test failed - displaying log files ==="
find verification/cocotb -name "*.log" -type f -exec sh -c \
'echo ""; echo "========================================"; echo "=== {} ==="; echo "========================================"; cat "{}"' \;
- name: Sanitize artifact name
if: always()
id: sanitize
run: |
NAME='${{ matrix.test }}'
SANITIZED=$(echo "$NAME" | sed "s/[()='\" ,]/_/g" | sed 's/__*/_/g' | sed 's/_$//')
echo "name=$SANITIZED" >> $GITHUB_OUTPUT
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-axi-controller-and-target-${{ steps.sanitize.outputs.name }}
path: |
verification/cocotb/**/*.xml
verification/cocotb/**/*.log
# ===========================================================================
# Job: Run AXI-Controller Only Tests (Parallel)
# ===========================================================================
tests-axi-controller-only:
name: "AXI-Ctrl Only: ${{ matrix.test }}"
needs: [generate-matrix, lint-testplans]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
test: ${{ fromJson(needs.generate-matrix.outputs.axi-controller-only-matrix) }}
steps:
- name: Install system dependencies
run: |
sudo apt -qqy update
sudo apt -qqy --no-install-recommends install \
help2man libfl-dev make g++ git bison flex gperf \
libreadline-dev libbz2-dev autoconf
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Cache Verilator installation
id: cache-verilator
uses: actions/cache@v4
with:
path: ~/verilator-install
key: verilator-install-${{ env.VERILATOR_VERSION }}-${{ runner.os }}
- name: Build Verilator (if not cached)
if: steps.cache-verilator.outputs.cache-hit != 'true'
run: |
git clone https://github.com/verilator/verilator -b ${{ env.VERILATOR_VERSION }}
cd verilator
autoconf
./configure --prefix=$HOME/verilator-install
make -j$(nproc)
make install
- name: Add Verilator to PATH
run: |
echo "$HOME/verilator-install/bin" >> $GITHUB_PATH
echo "VERILATOR_ROOT=$HOME/verilator-install/share/verilator" >> $GITHUB_ENV
- name: Setup Python environment (pyenv + dependencies)
run: ./install.sh
- name: Configure RTL and run test
id: run-test
env:
TEST_SESSION: ${{ matrix.test }}
CONTROLLER_SUPPORT: "1"
TARGET_SUPPORT: "0"
DUT_CONFIG: "controller_only"
CFG_NAME: "axi_controller_only_sim"
I3C_ROOT_DIR: ${{ github.workspace }}
run: |
source activate.sh
make config CFG_NAME=axi_controller_only_sim
cd verification/cocotb && python -m nox -R -s "$TEST_SESSION" --no-venv --forcecolor
- name: Display test logs on failure
if: failure() && steps.run-test.outcome == 'failure'
run: |
echo "=== Test failed - displaying log files ==="
find verification/cocotb -name "*.log" -type f -exec sh -c \
'echo ""; echo "========================================"; echo "=== {} ==="; echo "========================================"; cat "{}"' \;
- name: Rename XML results to avoid collisions
if: always()
run: |
find verification/cocotb -name "*.xml" -exec sh -c 'mv "$1" "${1%.xml}_ctrl_only.xml"' _ {} \;
- name: Sanitize artifact name
if: always()
id: sanitize
run: |
NAME='${{ matrix.test }}'
SANITIZED=$(echo "$NAME" | sed "s/[()='\" ,]/_/g" | sed 's/__*/_/g' | sed 's/_$//')
echo "name=$SANITIZED" >> $GITHUB_OUTPUT
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-axi-controller-only-${{ steps.sanitize.outputs.name }}
path: |
verification/cocotb/**/*.xml
verification/cocotb/**/*.log
# ===========================================================================
# Job: Aggregate Test Results
# ===========================================================================
test-results:
name: Aggregate test results
needs: [tests-ahb, tests-ahb-controller-and-target, tests-ahb-controller-only, tests-axi, tests-axi-controller-and-target, tests-axi-controller-only]
if: always()
runs-on: ubuntu-latest
steps:
- name: Download all test artifacts
uses: actions/download-artifact@v4
with:
pattern: test-results-*
path: test-results
merge-multiple: true
- name: Debug downloaded artifacts
run: |
echo "=== Files downloaded from test jobs ==="
find test-results -type f 2>/dev/null | head -30 || echo "No files found"
echo ""
echo "=== XML files specifically ==="
find test-results -name "*.xml" -type f 2>/dev/null | head -20 || echo "No XML files"
- name: Upload combined test results
uses: actions/upload-artifact@v4
with:
name: tests-results
path: test-results
- name: Verify all tests passed
run: |
if [ "${{ needs.tests-ahb.result }}" != "success" ] || \
[ "${{ needs.tests-ahb-controller-and-target.result }}" != "success" ] || \
[ "${{ needs.tests-ahb-controller-only.result }}" != "success" ] || \
[ "${{ needs.tests-axi.result }}" != "success" ] || \
[ "${{ needs.tests-axi-controller-and-target.result }}" != "success" ] || \
[ "${{ needs.tests-axi-controller-only.result }}" != "success" ]; then
echo "❌ Some tests failed!"
echo " AHB tests: ${{ needs.tests-ahb.result }}"
echo " AHB-Ctrl and Target tests: ${{ needs.tests-ahb-controller-and-target.result }}"
echo " AHB-Ctrl only tests: ${{ needs.tests-ahb-controller-only.result }}"
echo " AXI tests: ${{ needs.tests-axi.result }}"
echo " AXI-Ctrl and Target tests: ${{ needs.tests-axi-controller-and-target.result }}"
echo " AXI-Ctrl only tests: ${{ needs.tests-axi-controller-only.result }}"
exit 1
fi
echo "✅ All tests passed!"
# ===========================================================================
# Job: Build and Deploy Documentation
# ===========================================================================
docs-build:
name: Build documentation
runs-on: ubuntu-latest
needs: [test-results, generate-timing-docs]
if: always() && needs.test-results.result == 'success' && needs.generate-timing-docs.result == 'success'
steps:
- name: Install system dependencies
run: |
sudo apt -qqy update
sudo apt -qqy --no-install-recommends install \
python3 python3-pip python3-venv git
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize submodules
run: git submodule update --init --recursive
- name: Download test results
uses: actions/download-artifact@v4
with:
name: tests-results
path: tests-results
- name: Download timing docs artifact
uses: actions/download-artifact@v4
with:
name: timing-csr-docs
path: doc/source
- name: Debug downloaded artifacts
run: |
echo "=== Full structure of tests-results ==="
find tests-results -type f 2>/dev/null | head -30 || echo "No files found or directory doesn't exist"
echo ""
echo "=== Directory listing ==="
ls -laR tests-results 2>/dev/null | head -50 || echo "tests-results directory not found"
- name: Setup Python environment (uv)
run: |
python3 -m pip install uv
uv sync
uv pip install -r doc/requirements.txt
- name: Generate verification documentation
run: |
source .venv/bin/activate
if [ -d "tests-results/verification/cocotb" ]; then
echo "Found nested structure, copying from tests-results/verification/cocotb/"
cp -r tests-results/verification/cocotb/* verification/cocotb/
elif [ -d "tests-results" ] && [ "$(ls -A tests-results 2>/dev/null)" ]; then
echo "Found flat structure, copying from tests-results/"
cp -r tests-results/* verification/cocotb/
else
echo "WARNING: No test results found to copy!"
fi
echo "Filtering out controller_only test results from documentation generation..."
find verification/cocotb -name "*_ctrl_only.xml" -type f -delete
find verification/cocotb -name "*_ctrl_only.log" -type f -delete
echo "=== Surviving XML files in verification/cocotb ==="
find verification/cocotb -name "*.xml" -type f | head -10
XML_COUNT=$(find verification/cocotb -name "*.xml" -type f | wc -l)
if [ "$XML_COUNT" -gt 0 ]; then
echo "Found $XML_COUNT XML files, generating verification docs..."
REPO_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/tree/$GITHUB_REF_NAME/" \
make verification-docs-with-sim
else
echo "WARNING: No XML files found, skipping verification-docs-with-sim"
echo "Running verification-docs without sim results instead..."
REPO_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/tree/$GITHUB_REF_NAME/" \
make verification-docs || true
fi
- name: Build Sphinx documentation
run: |
source .venv/bin/activate
pushd doc
TZ=UTC make html
popd
git clone https://github.com/antmicro/i3c-core-coverage-results || true
cp i3c-core-coverage-results/*html doc/build/html 2>/dev/null || true
- name: Upload documentation artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: docs
path: ./doc/build
- name: Deploy to GitHub Pages
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./doc/build/html