feat: add smoke regression suite for IHP130 and enhance regression workflows

This commit is contained in:
maksyuki committed 2026-07-25 07:58:43 +08:00
1 parent 659a6acfdf
commit 65d974395d
10 files changed
+167 -37

No files matched your search

+3 -3
View File
@@ -4,9 +4,9 @@ This directory owns repository automation metadata: pull-request templates,
CODEOWNERS, Dependabot configuration, reusable actions, and CI/release
workflows.
`workflows/quality.yml` runs the fast quality gate. `workflows/regression.yml`,
`workflows/regression-gf180.yml`, `workflows/regression-sky130.yml`, and
`workflows/nightly.yml` call the reusable regression workflow;
`workflows/quality.yml` runs the fast quality gate. `workflows/regression-smoke.yml`,
`workflows/regression-ihp130.yml`, `workflows/regression-gf180.yml`,
`workflows/regression-sky130.yml`, and `workflows/nightly.yml` call the reusable regression workflow;
`workflows/release.yml` packages tagged releases. `actions/locked-tools/`
installs the locked open-source tools used by CI.
+28 -7
View File
@@ -20,6 +20,21 @@ on:
required: false
default: 30
type: number
timeout_minutes:
description: Maximum job duration
required: false
default: 240
type: number
toolset:
description: Space-separated locked tools required by this suite
required: false
default: verilator sv2v iverilog yosys opensta riscv_gnu
type: string
full_flow_checks:
description: Check Yosys and OpenSTA environments before running the suite
required: false
default: true
type: boolean
permissions:
contents: read
@@ -27,7 +42,7 @@ permissions:
jobs:
regression:
runs-on: ubuntu-22.04
timeout-minutes: 240
timeout-minutes: ${{ inputs.timeout_minutes }}
env:
PIP_DISABLE_PIP_VERSION_CHECK: "1"
steps:
@@ -87,19 +102,25 @@ jobs:
- name: Set up locked EDA and compiler tools
uses: ./.github/actions/locked-tools
with:
tools: verilator sv2v iverilog yosys opensta riscv_gnu
tools: ${{ inputs.toolset }}
- name: Set up locked source dependencies
run: make CONFIG=${{ inputs.profile }} setup
- name: Check environment
- name: Check behavioral environments
run: |
make CONFIG=${{ inputs.profile }} \
SIMU=IVERILOG SYNTH=NONE STA=NONE doctor
make CONFIG=${{ inputs.profile }} \
SIMU=VERILATOR SYNTH=NONE STA=NONE doctor
- name: Check synthesis and timing environments
if: inputs.full_flow_checks
run: |
make CONFIG=${{ inputs.profile }} \
SIMU=IVERILOG SYNTH=YOSYS STA=NONE doctor
make CONFIG=${{ inputs.profile }} SIMU=VERILATOR doctor
- name: Check timing environment
run: make CONFIG=${{ inputs.profile }} SIMU=IVERILOG STA=OPENSTA doctor
make CONFIG=${{ inputs.profile }} \
SIMU=IVERILOG SYNTH=NONE STA=OPENSTA doctor
- name: Run ${{ inputs.suite }} regression
run: python3 scripts/regress.py --root . --suite "${{ inputs.suite }}" --pdk "${{ inputs.pdk }}"
+1
View File
@@ -81,3 +81,4 @@ jobs:
python3 scripts/regress.py --root . --suite pr --pdk GF180 --dry-run
python3 scripts/regress.py --root . --suite pr --pdk SKY130 --dry-run
python3 scripts/regress.py --root . --suite nightly --pdk IHP130 --dry-run
python3 scripts/regress.py --root . --suite smoke --pdk IHP130 --dry-run
File renamed without changes.
+27
View File
@@ -0,0 +1,27 @@
name: regression-smoke
on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: regression-smoke-${{ github.ref }}
cancel-in-progress: true
jobs:
ihp130-smoke:
uses: ./.github/workflows/_regression.yml
with:
suite: smoke
pdk: IHP130
profile: configs/ci/hazard3-rv32im-ihp130.mk
retention_days: 14
timeout_minutes: 60
toolset: verilator sv2v iverilog riscv_gnu
full_flow_checks: false
+6 -2
View File
@@ -168,7 +168,7 @@ endif
.PHONY: help config doctor setup setup-mpw setup-core setup-clusterip setup-ip setup-pdk setup-app \
clean-all purge-cache manifest check-warnings metrics check-metrics package \
regress-pr regress-nightly sim-asm format format-check sw-format sw-format-check mk-format \
regress-smoke regress-pr regress-nightly sim-asm format format-check sw-format sw-format-check mk-format \
mk-format-check rtl-format rtl-format-check sw-policy-check sw-host-test \
pin-map check-pin-map soc-topology check-soc-topology user-extensions check-user-extensions \
check-clock-reset-domains tech-cell-test
@@ -206,7 +206,8 @@ help:
' rtl-format | rtl-format-check apply/check self-owned RTL formatting' \
' sw-policy-check check embedded C API and naming policy' \
' sw-host-test run host tests for deterministic SDK utilities' \
' regress-pr | regress-nightly run supported regression suites' \
' regress-smoke run the IHP130 fast regression suite' \
' regress-pr | regress-nightly run supported full regression suites' \
' package create checksummed source deliverables' \
' clean | clean-all clean current flow or all build output' \
' purge-cache remove dependency and compiler caches' \
@@ -317,6 +318,9 @@ package: $(MPW_VARIANT_STAMP) $(FILELIST_STAMP) manifest
python3 $(ROOT_PATH)/scripts/package.py --root $(ROOT_PATH) --lock $(LOCK_FILE) \
--variant-root $(VARIANT_ROOT) --output-dir $(ROOT_PATH)/dist/$(VARIANT_ID)
regress-smoke:
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite smoke --pdk IHP130
regress-pr:
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite pr --pdk IHP130
python3 $(ROOT_PATH)/scripts/regress.py --root $(ROOT_PATH) --suite pr --pdk GF180
+8 -3
View File
@@ -1,7 +1,7 @@
# retroSoC
[![quality](https://github.com/retroSoC/retroSoC/actions/workflows/quality.yml/badge.svg)](https://github.com/retroSoC/retroSoC/actions/workflows/quality.yml)
[![IHP130 regression](https://github.com/retroSoC/retroSoC/actions/workflows/regression.yml/badge.svg)](https://github.com/retroSoC/retroSoC/actions/workflows/regression.yml)
[![IHP130 regression](https://github.com/retroSoC/retroSoC/actions/workflows/regression-ihp130.yml/badge.svg)](https://github.com/retroSoC/retroSoC/actions/workflows/regression-ihp130.yml)
[![GF180 regression](https://github.com/retroSoC/retroSoC/actions/workflows/regression-gf180.yml/badge.svg)](https://github.com/retroSoC/retroSoC/actions/workflows/regression-gf180.yml)
[![SKY130 regression](https://github.com/retroSoC/retroSoC/actions/workflows/regression-sky130.yml/badge.svg)](https://github.com/retroSoC/retroSoC/actions/workflows/regression-sky130.yml)
[![nightly](https://github.com/retroSoC/retroSoC/actions/workflows/nightly.yml/badge.svg)](https://github.com/retroSoC/retroSoC/actions/workflows/nightly.yml)
@@ -123,14 +123,19 @@ make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk SIMU=IVERILOG \
| Yosys synthesis | `make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk SYNTH=YOSYS synth` |
| Icarus netlist simulation after synthesis | `make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk SIMU=IVERILOG netsim` |
| OpenSTA core timing analysis after synthesis | `make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk STA=OPENSTA sta` |
`make regress-pr` runs the supported IHP130, GF180, and SKY130 PR matrices in
sequence, including slow-corner OpenSTA core timing analysis for each PDK.
| IHP130 fast smoke suite | `make regress-smoke` |
| Pull-request regression suite | `make regress-pr` |
| Nightly regression suite | `make regress-nightly` |
| Format C, Makefile, and RTL sources | `make format` |
| Check C, Makefile, and RTL formatting | `make format-check` |
| Script and policy checks | `make sw-policy-check sw-host-test` |
`make regress-smoke` builds the IHP130 firmware, compiles the Verilator SVA
configuration, and runs the Icarus assembly self-test. It omits synthesis,
timing, and netlist simulation for fast feedback. `make regress-pr` runs the
supported IHP130, GF180, and SKY130 PR matrices in sequence, including
slow-corner OpenSTA core timing analysis for each PDK.
Build outputs are isolated below `build/<profile>-<YYYY-MM-DD-HH-MM>-<config-hash>/`. Each variant keeps its
firmware, generated sources, simulator output, synthesis and timing reports, manifest, warning
analysis, and metrics separate from other configurations. Use `make clean` to remove the
+5 -3
View File
@@ -4,6 +4,7 @@
| Tier | Profile | Automated coverage |
| --- | --- | --- |
| Smoke | `configs/ci/hazard3-rv32im-ihp130.mk` | firmware, Verilator SVA compilation, Icarus assembly self-test |
| Pull request | `configs/ci/hazard3-rv32im-ihp130.mk` | firmware, Verilator, Icarus, Yosys, netlist Icarus, OpenSTA |
| Pull request | `configs/ci/hazard3-rv32im-gf180.mk` | firmware, Verilator, Icarus, Yosys, netlist Icarus, OpenSTA |
| Pull request | `configs/ci/hazard3-rv32im-sky130.mk` | firmware, Verilator, Icarus, Yosys, netlist Icarus, OpenSTA |
@@ -136,9 +137,10 @@ for diagnosis but is initially non-blocking.
## CI And Releases
`quality.yml` validates C, Makefile, and self-owned RTL formatting as well as Python, YAML, GitHub
Actions, the dependency lock, and script tests. `regression.yml` runs verified configurations on pull
requests and main branches without repeating the format checks. `nightly.yml` adds PICORV32. Source
dependencies, locked tool archives, and Verilator `ccache` use separate cache keys.
Actions, the dependency lock, and script tests. `regression-smoke.yml` provides fast IHP130 feedback;
the three full PDK regression workflows remain required PR coverage and do not repeat the format checks.
`nightly.yml` adds PICORV32. Source dependencies, locked tool archives, and Verilator `ccache` use
separate cache keys.
Tags matching `v*` run `release.yml`. The release contains a flattened SystemVerilog export, a source
tarball, build manifest, dependency lock, CycloneDX SBOM, and `SHA256SUMS`. `make package` creates the
+39 -18
View File
@@ -48,6 +48,17 @@ PR_COMMANDS = (
),
("configs/ci/hazard3-rv32im-ihp130.mk", ("STA=OPENSTA", "sta")),
)
SMOKE_COMMANDS = (
("configs/ci/hazard3-rv32im-ihp130.mk", ("firmware",)),
(
"configs/ci/hazard3-rv32im-ihp130.mk",
("SIMU=VERILATOR", "HAVE_SVA=YES", "comp"),
),
(
"configs/ci/hazard3-rv32im-ihp130.mk",
("SIMU=IVERILOG", "RTL_SIM_TIMEOUT=5200000", "sim-asm"),
),
)
NIGHTLY_COMMANDS = PR_COMMANDS + (
(
"configs/nightly/picorv32-rv32im-ihp130.mk",
@@ -63,6 +74,7 @@ PR_PROFILES = (
"configs/ci/hazard3-rv32im-ihp130-ip-mdd.mk",
"configs/ci/mdd-rv32im-ihp130.mk",
)
SMOKE_PROFILES: tuple[str, ...] = ()
NIGHTLY_PROFILES = PR_PROFILES + ("configs/nightly/picorv32-rv32im-ihp130.mk",)
PDK_PR_PROFILES = {
@@ -92,6 +104,27 @@ def pdk_pr_commands(profile: str) -> tuple[tuple[str, tuple[str, ...]], ...]:
)
def select_regression(
suite: str, pdk: str | None
) -> tuple[tuple[tuple[str, tuple[str, ...]], ...], tuple[str, ...]]:
if suite == "smoke":
if pdk is not None and pdk != "IHP130":
raise ValueError("smoke regression supports only --pdk IHP130")
return SMOKE_COMMANDS, SMOKE_PROFILES
if pdk:
if suite == "nightly":
if pdk != "IHP130":
raise ValueError("nightly regression supports only --pdk IHP130")
return NIGHTLY_COMMANDS, NIGHTLY_PROFILES
if pdk == "IHP130":
return PR_COMMANDS, PR_PROFILES
profile = PDK_PR_PROFILES[pdk]
return pdk_pr_commands(profile), (profile,)
if suite == "pr":
return PR_COMMANDS, PR_PROFILES
return NIGHTLY_COMMANDS, NIGHTLY_PROFILES
def regression_environment() -> dict[str, str]:
environment = os.environ.copy()
environment.setdefault(
@@ -124,26 +157,14 @@ def run_command(
def main() -> int:
parser = argparse.ArgumentParser(description="Run a supported retroSoC regression suite")
parser.add_argument("--root", type=Path, required=True)
parser.add_argument("--suite", choices=("pr", "nightly"), required=True)
parser.add_argument("--pdk", choices=tuple(PDK_PR_PROFILES), help="run one PR PDK matrix")
parser.add_argument("--suite", choices=("smoke", "pr", "nightly"), required=True)
parser.add_argument("--pdk", choices=tuple(PDK_PR_PROFILES), help="run one PDK matrix")
parser.add_argument("--dry-run", action="store_true")
args = parser.parse_args()
if args.pdk:
if args.suite == "nightly":
if args.pdk != "IHP130":
parser.error("nightly regression supports only --pdk IHP130")
commands = NIGHTLY_COMMANDS
profiles = NIGHTLY_PROFILES
elif args.pdk == "IHP130":
commands = PR_COMMANDS
profiles = PR_PROFILES
else:
profile = PDK_PR_PROFILES[args.pdk]
commands = pdk_pr_commands(profile)
profiles = (profile,)
else:
commands = PR_COMMANDS if args.suite == "pr" else NIGHTLY_COMMANDS
profiles = PR_PROFILES if args.suite == "pr" else NIGHTLY_PROFILES
try:
commands, profiles = select_regression(args.suite, args.pdk)
except ValueError as error:
parser.error(str(error))
environment = regression_environment()
for profile, values in commands:
command = ["make", f"CONFIG={profile}", *values]
+50 -1
View File
@@ -31,8 +31,10 @@ from scripts.regress import ( # noqa: E402
NIGHTLY_COMMANDS,
PDK_PR_PROFILES,
PR_COMMANDS,
SMOKE_COMMANDS,
pdk_pr_commands,
regression_environment,
select_regression,
)
from scripts import setup_helpers # noqa: E402
from scripts.setup_helpers import download_file, ensure_git_repo # noqa: E402
@@ -360,13 +362,60 @@ def test_verilator_simulations_use_uniform_timeout() -> None:
verilator_makefile = ROOT / "rtl/mini/mk/verilator.mk"
assert "SOC_SIM_TIME ?= 180" in verilator_makefile.read_text(encoding="utf-8")
regression_commands = (*PR_COMMANDS, *NIGHTLY_COMMANDS)
regression_commands = (*SMOKE_COMMANDS, *PR_COMMANDS, *NIGHTLY_COMMANDS)
for _, values in regression_commands:
if "SIMU=VERILATOR" in values:
assert not any(value.startswith("SOC_SIM_TIME=") for value in values)
assert "HAVE_SVA=YES" in values
def test_smoke_regression_uses_ihp130_behavioral_coverage_only() -> None:
commands, profiles = select_regression("smoke", "IHP130")
assert commands == SMOKE_COMMANDS
assert profiles == ()
command_values = [values for _, values in commands]
assert ("firmware",) in command_values
assert ("SIMU=VERILATOR", "HAVE_SVA=YES", "comp") in command_values
assert ("SIMU=IVERILOG", "RTL_SIM_TIMEOUT=5200000", "sim-asm") in command_values
assert not any(
"synth" in values or "sta" in values or "netsim" in values
for values in command_values
)
dry_run = run(
sys.executable,
str(ROOT / "scripts/regress.py"),
"--root",
str(ROOT),
"--suite",
"smoke",
"--pdk",
"IHP130",
"--dry-run",
)
assert "+ make CONFIG=configs/ci/hazard3-rv32im-ihp130.mk firmware" in dry_run.stdout
assert "netsim" not in dry_run.stdout
invalid = subprocess.run(
[
sys.executable,
str(ROOT / "scripts/regress.py"),
"--root",
str(ROOT),
"--suite",
"smoke",
"--pdk",
"GF180",
"--dry-run",
],
text=True,
capture_output=True,
)
assert invalid.returncode != 0
assert "smoke regression supports only --pdk IHP130" in invalid.stderr
def test_pdk_pr_regressions_cover_firmware_rtl_and_netlist() -> None:
assert set(PDK_PR_PROFILES) == {"GF180", "IHP130", "SKY130"}
for profile in PDK_PR_PROFILES.values():