33# I3C Core - Parallel Test and Documentation Workflow
44#
55# This workflow runs cocotb verification tests in parallel for AHB, AXI,
6- # and AXI-Controller bus configurations, then builds and deploys documentation.
6+ # AXI-Controller, and AHB-controller bus configurations, then builds and
7+ # deploys documentation.
78#
89# Architecture:
910# 1. generate-timing-docs: Generates timing CSR markdown documents
1011# 2. generate-matrix: Uses nox's JSON output to discover test sessions
1112# 3. tests-ahb: Runs all AHB-tagged tests in parallel (one job per test)
12- # 4. tests-axi: Runs all AXI-tagged tests in parallel (one job per test)
13- # 5. tests-axi-controller-and-target: Runs all AXI-Controller tests in parallel
14- # 6. tests-axi-controller-only: Runs all AXI-Controller only tests in parallel
15- # 7. test-results: Aggregates results from all test jobs
16- # 8. docs-build: Builds and deploys documentation (only after tests pass)
13+ # 4. tests-ahb-controller-and-target: Runs all AHB-Controller tests in parallel
14+ # 5. tests-ahb-controller-only: Runs all AHB-Controller only tests in parallel
15+ # 6. tests-axi: Runs all AXI-tagged tests in parallel (one job per test)
16+ # 7. tests-axi-controller-and-target: Runs all AXI-Controller tests in parallel
17+ # 8. tests-axi-controller-only: Runs all AXI-Controller only tests in parallel
18+ # 9. test-results: Aggregates results from all test jobs
19+ # 10. docs-build: Builds and deploys documentation (only after tests pass)
1720#
1821# Optional: Long-running tests (i3c_ahb_verify, i3c_axi_verify) can be split
1922# into individual parametrized runs by enabling SPLIT_TESTS in generate-matrix.
8992 runs-on : ubuntu-latest
9093 outputs :
9194 ahb-matrix : ${{ steps.gen.outputs.ahb_matrix }}
95+ ahb-controller-and-target-matrix : ${{ steps.gen.outputs.ahb_controller_and_target_matrix }}
96+ ahb-controller-only-matrix : ${{ steps.gen.outputs.ahb_controller_only_matrix }}
9297 axi-matrix : ${{ steps.gen.outputs.axi_matrix }}
9398 axi-controller-and-target-matrix : ${{ steps.gen.outputs.axi_controller_and_target_matrix }}
9499 axi-controller-only-matrix : ${{ steps.gen.outputs.axi_controller_only_matrix }}
@@ -148,6 +153,8 @@ jobs:
148153 sys.exit(1)
149154
150155 ahb_tests = set()
156+ ahb_controller_and_target_tests = set()
157+ ahb_controller_only_tests = set()
151158 axi_tests = set()
152159 axi_controller_and_target_tests = set()
153160 axi_controller_only_tests = set()
@@ -172,7 +179,16 @@ jobs:
172179 has_target = "target" in tags
173180
174181 if has_ahb:
175- ahb_tests.add(session_id)
182+ if has_controller:
183+ # If it has a controller tag, it always runs in the combined job
184+ ahb_controller_and_target_tests.add(session_id)
185+
186+ # Exclude tests that also require a target from the controller_only job
187+ if not has_target:
188+ ahb_controller_only_tests.add(session_id)
189+ else:
190+ # Standard AHB tests (target-only, no controller tag)
191+ ahb_tests.add(session_id)
176192
177193 if has_axi:
178194 if has_controller:
@@ -188,17 +204,23 @@ jobs:
188204
189205 # Sort for consistent ordering
190206 ahb_tests = sorted(ahb_tests)
207+ ahb_controller_and_target_tests = sorted(ahb_controller_and_target_tests)
208+ ahb_controller_only_tests = sorted(ahb_controller_only_tests)
191209 axi_tests = sorted(axi_tests)
192210 axi_controller_and_target_tests = sorted(axi_controller_and_target_tests)
193211 axi_controller_only_tests = sorted(axi_controller_only_tests)
194212
195213 print(f"Discovered {len(ahb_tests)} AHB tests")
214+ print(f"Discovered {len(ahb_controller_and_target_tests)} AHB-Controller+Target tests")
215+ print(f"Discovered {len(ahb_controller_only_tests)} AHB-Controller-Only tests")
196216 print(f"Discovered {len(axi_tests)} AXI (Target-Only) tests")
197217 print(f"Discovered {len(axi_controller_and_target_tests)} AXI-Controller+Target tests")
198218 print(f"Discovered {len(axi_controller_only_tests)} AXI-Controller-Only tests")
199219
200220 with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
201221 f.write(f"ahb_matrix={json.dumps(ahb_tests)}\n")
222+ f.write(f"ahb_controller_and_target_matrix={json.dumps(ahb_controller_and_target_tests)}\n")
223+ f.write(f"ahb_controller_only_matrix={json.dumps(ahb_controller_only_tests)}\n")
202224 f.write(f"axi_matrix={json.dumps(axi_tests)}\n")
203225 f.write(f"axi_controller_and_target_matrix={json.dumps(axi_controller_and_target_tests)}\n")
204226 f.write(f"axi_controller_only_matrix={json.dumps(axi_controller_only_tests)}\n")
@@ -309,6 +331,187 @@ jobs:
309331 verification/cocotb/**/*.xml
310332 verification/cocotb/**/*.log
311333
334+ # ===========================================================================
335+ # Job: Run AHB-Controller and Target Tests (Parallel)
336+ # ===========================================================================
337+ tests-ahb-controller-and-target :
338+ name : " AHB-Ctrl+Target: ${{ matrix.test }}"
339+ needs : [generate-matrix, lint-testplans]
340+ runs-on : ubuntu-latest
341+ strategy :
342+ fail-fast : false
343+ matrix :
344+ test : ${{ fromJson(needs.generate-matrix.outputs.ahb-controller-and-target-matrix) }}
345+ steps :
346+ - name : Install system dependencies
347+ run : |
348+ sudo apt -qqy update
349+ sudo apt -qqy --no-install-recommends install \
350+ help2man libfl-dev make g++ git bison flex gperf \
351+ libreadline-dev libbz2-dev autoconf
352+
353+ - name : Checkout repository
354+ uses : actions/checkout@v4
355+
356+ - name : Initialize submodules
357+ run : git submodule update --init --recursive
358+
359+ - name : Cache Verilator installation
360+ id : cache-verilator
361+ uses : actions/cache@v4
362+ with :
363+ path : ~/verilator-install
364+ key : verilator-install-${{ env.VERILATOR_VERSION }}-${{ runner.os }}
365+
366+ - name : Build Verilator (if not cached)
367+ if : steps.cache-verilator.outputs.cache-hit != 'true'
368+ run : |
369+ git clone https://github.com/verilator/verilator -b ${{ env.VERILATOR_VERSION }}
370+ cd verilator
371+ autoconf
372+ ./configure --prefix=$HOME/verilator-install
373+ make -j$(nproc)
374+ make install
375+
376+ - name : Add Verilator to PATH
377+ run : |
378+ echo "$HOME/verilator-install/bin" >> $GITHUB_PATH
379+ echo "VERILATOR_ROOT=$HOME/verilator-install/share/verilator" >> $GITHUB_ENV
380+
381+ - name : Setup Python environment (pyenv + dependencies)
382+ run : ./install.sh
383+
384+ - name : Configure RTL and run test
385+ id : run-test
386+ env :
387+ TEST_SESSION : ${{ matrix.test }}
388+ CONTROLLER_SUPPORT : " 1"
389+ TARGET_SUPPORT : " 1"
390+ DUT_CONFIG : " controller_and_target"
391+ CFG_NAME : " ahb_controller_and_target_sim"
392+ I3C_ROOT_DIR : ${{ github.workspace }}
393+ run : |
394+ source activate.sh
395+ make config CFG_NAME=ahb_controller_and_target_sim
396+ cd verification/cocotb && python -m nox -R -s "$TEST_SESSION" --no-venv --forcecolor
397+
398+ - name : Display test logs on failure
399+ if : failure() && steps.run-test.outcome == 'failure'
400+ run : |
401+ echo "=== Test failed - displaying log files ==="
402+ find verification/cocotb -name "*.log" -type f -exec sh -c \
403+ 'echo ""; echo "========================================"; echo "=== {} ==="; echo "========================================"; cat "{}"' \;
404+
405+ - name : Sanitize artifact name
406+ if : always()
407+ id : sanitize
408+ run : |
409+ NAME='${{ matrix.test }}'
410+ SANITIZED=$(echo "$NAME" | sed "s/[()='\" ,]/_/g" | sed 's/__*/_/g' | sed 's/_$//')
411+ echo "name=$SANITIZED" >> $GITHUB_OUTPUT
412+
413+ - name : Upload test artifacts
414+ if : always()
415+ uses : actions/upload-artifact@v4
416+ with :
417+ name : test-results-ahb-controller-and-target-${{ steps.sanitize.outputs.name }}
418+ path : |
419+ verification/cocotb/**/*.xml
420+ verification/cocotb/**/*.log
421+
422+ # ===========================================================================
423+ # Job: Run AHB-Controller Only Tests (Parallel)
424+ # ===========================================================================
425+ tests-ahb-controller-only :
426+ name : " AHB-Ctrl Only: ${{ matrix.test }}"
427+ needs : [generate-matrix, lint-testplans]
428+ runs-on : ubuntu-latest
429+ strategy :
430+ fail-fast : false
431+ matrix :
432+ test : ${{ fromJson(needs.generate-matrix.outputs.ahb-controller-only-matrix) }}
433+ steps :
434+ - name : Install system dependencies
435+ run : |
436+ sudo apt -qqy update
437+ sudo apt -qqy --no-install-recommends install \
438+ help2man libfl-dev make g++ git bison flex gperf \
439+ libreadline-dev libbz2-dev autoconf
440+
441+ - name : Checkout repository
442+ uses : actions/checkout@v4
443+
444+ - name : Initialize submodules
445+ run : git submodule update --init --recursive
446+
447+ - name : Cache Verilator installation
448+ id : cache-verilator
449+ uses : actions/cache@v4
450+ with :
451+ path : ~/verilator-install
452+ key : verilator-install-${{ env.VERILATOR_VERSION }}-${{ runner.os }}
453+
454+ - name : Build Verilator (if not cached)
455+ if : steps.cache-verilator.outputs.cache-hit != 'true'
456+ run : |
457+ git clone https://github.com/verilator/verilator -b ${{ env.VERILATOR_VERSION }}
458+ cd verilator
459+ autoconf
460+ ./configure --prefix=$HOME/verilator-install
461+ make -j$(nproc)
462+ make install
463+
464+ - name : Add Verilator to PATH
465+ run : |
466+ echo "$HOME/verilator-install/bin" >> $GITHUB_PATH
467+ echo "VERILATOR_ROOT=$HOME/verilator-install/share/verilator" >> $GITHUB_ENV
468+
469+ - name : Setup Python environment (pyenv + dependencies)
470+ run : ./install.sh
471+
472+ - name : Configure RTL and run test
473+ id : run-test
474+ env :
475+ TEST_SESSION : ${{ matrix.test }}
476+ CONTROLLER_SUPPORT : " 1"
477+ TARGET_SUPPORT : " 0"
478+ DUT_CONFIG : " controller_only"
479+ CFG_NAME : " ahb_controller_only_sim"
480+ I3C_ROOT_DIR : ${{ github.workspace }}
481+ run : |
482+ source activate.sh
483+ make config CFG_NAME=ahb_controller_only_sim
484+ cd verification/cocotb && python -m nox -R -s "$TEST_SESSION" --no-venv --forcecolor
485+
486+ - name : Display test logs on failure
487+ if : failure() && steps.run-test.outcome == 'failure'
488+ run : |
489+ echo "=== Test failed - displaying log files ==="
490+ find verification/cocotb -name "*.log" -type f -exec sh -c \
491+ 'echo ""; echo "========================================"; echo "=== {} ==="; echo "========================================"; cat "{}"' \;
492+
493+ - name : Rename XML results to avoid collisions
494+ if : always()
495+ run : |
496+ find verification/cocotb -name "*.xml" -exec sh -c 'mv "$1" "${1%.xml}_ctrl_only.xml"' _ {} \;
497+
498+ - name : Sanitize artifact name
499+ if : always()
500+ id : sanitize
501+ run : |
502+ NAME='${{ matrix.test }}'
503+ SANITIZED=$(echo "$NAME" | sed "s/[()='\" ,]/_/g" | sed 's/__*/_/g' | sed 's/_$//')
504+ echo "name=$SANITIZED" >> $GITHUB_OUTPUT
505+
506+ - name : Upload test artifacts
507+ if : always()
508+ uses : actions/upload-artifact@v4
509+ with :
510+ name : test-results-ahb-controller-only-${{ steps.sanitize.outputs.name }}
511+ path : |
512+ verification/cocotb/**/*.xml
513+ verification/cocotb/**/*.log
514+
312515 # ===========================================================================
313516 # Job: Run AXI Tests (Parallel)
314517 # ===========================================================================
@@ -578,7 +781,7 @@ jobs:
578781 # ===========================================================================
579782 test-results :
580783 name : Aggregate test results
581- needs : [tests-ahb, tests-axi, tests-axi-controller-and-target, tests-axi-controller-only]
784+ needs : [tests-ahb, tests-ahb-controller-and-target, tests-ahb-controller-only, tests- axi, tests-axi-controller-and-target, tests-axi-controller-only]
582785 if : always()
583786 runs-on : ubuntu-latest
584787 steps :
@@ -606,11 +809,15 @@ jobs:
606809 - name : Verify all tests passed
607810 run : |
608811 if [ "${{ needs.tests-ahb.result }}" != "success" ] || \
812+ [ "${{ needs.tests-ahb-controller-and-target.result }}" != "success" ] || \
813+ [ "${{ needs.tests-ahb-controller-only.result }}" != "success" ] || \
609814 [ "${{ needs.tests-axi.result }}" != "success" ] || \
610815 [ "${{ needs.tests-axi-controller-and-target.result }}" != "success" ] || \
611816 [ "${{ needs.tests-axi-controller-only.result }}" != "success" ]; then
612817 echo "❌ Some tests failed!"
613818 echo " AHB tests: ${{ needs.tests-ahb.result }}"
819+ echo " AHB-Ctrl and Target tests: ${{ needs.tests-ahb-controller-and-target.result }}"
820+ echo " AHB-Ctrl only tests: ${{ needs.tests-ahb-controller-only.result }}"
614821 echo " AXI tests: ${{ needs.tests-axi.result }}"
615822 echo " AXI-Ctrl and Target tests: ${{ needs.tests-axi-controller-and-target.result }}"
616823 echo " AXI-Ctrl only tests: ${{ needs.tests-axi-controller-only.result }}"
0 commit comments