Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
3412252
[Add] Support multi-module repository orchestration
ErickOF Sep 9, 2026
356c0cd
Merge pull request #11 from ECASLab/feature-multimodule_repo_orchestr…
ErickOF Sep 9, 2026
ccfc047
[Add] Qualify parameter profiles across shared flows
ErickOF Sep 9, 2026
3103459
Merge pull request #12 from ECASLab/feature-parameter_profile_matrix_…
ErickOF Sep 9, 2026
8c0feca
[Add] Standardize release qualification evidence
ErickOF Sep 10, 2026
0186f91
Merge pull request #13 from ECASLab/feature-standardized_release_evid…
ErickOF Sep 10, 2026
20d3bf2
[Update] Complete release manifest acceptance coverage
ErickOF Sep 10, 2026
c794012
Merge pull request #14 from ECASLab/feature-standardized_release_evid…
ErickOF Sep 10, 2026
992c7b5
[Add] Qualify assertion and RTL coverage
ErickOF Sep 10, 2026
019b743
Merge pull request #15 from ECASLab/feature-configurable_assertion_an…
ErickOF Sep 10, 2026
d8bf6f7
[Add] Qualify negative tests and four-state controls
ErickOF Sep 10, 2026
4e26c12
[Fix] Align parameter-profile qualification evidence
ErickOF Sep 10, 2026
a95ccaf
Merge pull request #16 from ECASLab/feature-negative_test_and_four_st…
ErickOF Sep 10, 2026
70605d5
[Add] Validate portable SDC and UPF intent
ErickOF Sep 10, 2026
44892f8
Merge pull request #17 from ECASLab/feature-static_intent_validation_…
ErickOF Sep 10, 2026
54237dd
[Add] Containerize reproducible OpenROAD execution
ErickOF Sep 11, 2026
9d2852a
Merge pull request #18 from ECASLab/feature-containerized_openroad_flow
ErickOF Sep 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 152 additions & 1 deletion .github/workflows/flow-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,164 @@ jobs:
- name: Validate PyUVM fixture evidence
run: tests/check_fixture_pyuvm_evidence.sh

- name: Verify reusable and dedicated coverage sources
run: |
make -C tests/fixture-module \
FLOW_ROOT="${GITHUB_WORKSPACE}" \
COVERAGE_QUALIFICATION_SOURCE=pyuvm_open_source \
FLOW_DEPENDENCIES_coverage_qualification=pyuvm_open_source \
open-coverage
grep -Fq '"source": "pyuvm_open_source"' \
tests/fixture-module/reports/coverage_qualification/summary.json
make -C tests/fixture-module \
FLOW_ROOT="${GITHUB_WORKSPACE}" \
COVERAGE_QUALIFICATION_SOURCE=dedicated \
FLOW_DEPENDENCIES_coverage_qualification= \
open-coverage
grep -Fq '"source": "dedicated"' \
tests/fixture-module/reports/coverage_qualification/summary.json

- name: Verify SystemVerilog assertion failure propagation
run: tests/test_pyuvm_assertion_failure.sh

- name: Verify unreachable formal cover failure propagation
run: tests/test_coverage_unreachable_formal.sh

- name: Run complete multi-module fixture flow
run: |
make -C tests/fixture-multi-module \
FLOW_ROOT="${GITHUB_WORKSPACE}" clean all-modules MODULE_JOBS=2

- name: Run complete parameter-profile fixture flow
run: |
make -C tests/fixture-parameter-profiles \
FLOW_ROOT="${GITHUB_WORKSPACE}" clean all-profiles PROFILE_JOBS=4

- name: Validate parameter-profile fixture evidence
run: tests/check_fixture_parameter_profile_evidence.sh

- name: Generate release evidence for the complete fixture
run: |
make -C tests/fixture-module \
FLOW_ROOT="${GITHUB_WORKSPACE}" \
DISABLED_FLOWS="openroad vcs_sim pyuvm_commercial vc_lint vc_cdc sg_cdc sg_dft vc_lp synopsys_synthesis synopsys_primetime synopsys_primepower" \
MODULE_REVISION="${GITHUB_SHA}" \
METHODOLOGY_REVISION="${GITHUB_SHA}" \
release-manifest release-manifest-validate

- name: Validate complete fixture release evidence contents
run: EXPECT_CLEAN_RELEASE=true tests/check_fixture_release_manifest.sh

- name: Upload fixture reports
if: always()
uses: actions/upload-artifact@v4
with:
name: mosaic-flow-fixture-reports
path: tests/fixture-module/reports/
path: |
tests/fixture-module/reports/
tests/fixture-multi-module/reports/
tests/fixture-parameter-profiles/reports/
if-no-files-found: error

multi-module-container:
name: Containerized multi-module orchestration
runs-on: ubuntu-24.04
timeout-minutes: 10
container: python:3.12-slim-bookworm@sha256:782412e85d0f0984994c290652577d4018aff08145c85b262bb63dc0c7522254

steps:
- name: Install container test dependencies
run: |
apt-get update
apt-get install --yes --no-install-recommends findutils git make
rm -rf /var/lib/apt/lists/*

- name: Check out mosaic-flow
uses: actions/checkout@v4

- name: Run multi-module orchestration tests
run: |
tests/test_multi_module.sh
tests/test_parameter_profiles.sh
tests/test_coverage_qualification.sh
tests/test_qualification_campaigns.sh
tests/test_static_intent.sh

- name: Run containerized release-manifest fixture
run: FIXTURE_CONTEXT=container tests/test_release_manifest.sh

openroad-container:
name: Containerized Nangate45 physical fixture
runs-on: ubuntu-24.04
timeout-minutes: 45

steps:
- name: Check out mosaic-flow
uses: actions/checkout@v4

- name: Cache pinned OpenROAD image layers
uses: actions/cache@v4
with:
path: ~/.cache/mosaic/openroad-images
key: openroad-image-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('config/tool-versions.env') }}

- name: Prepare pinned OpenROAD image
run: ci/cache_openroad_image.sh

- name: Run Nangate45 fixture
run: |
make -C tests/fixture-module \
FLOW_ROOT="${GITHUB_WORKSPACE}" \
OPENROAD_EXECUTION_MODE=container \
open-physical

- name: Validate physical evidence and ownership
run: |
python3 - <<'PY'
import json
import pathlib

evidence = json.loads(
pathlib.Path("tests/fixture-module/reports/openroad/evidence.json").read_text()
)
assert evidence["status"] == "PASS"
assert evidence["design"]["platform"] == "nangate45"
assert evidence["execution"]["mode"] == "container"
assert evidence["execution"]["image"]["reference"].endswith(
"@" + evidence["execution"]["image"]["digest"]
)
assert {item["name"] for item in evidence["artifacts"]} == {
"final_def", "final_gds", "final_netlist", "final_odb", "final_sdc"
}
assert all(item["passed"] for item in evidence["metrics"])
PY
if find tests/fixture-module/work/openroad -not -user "$(id -un)" -print -quit | grep -q .; then
echo "Containerized OpenROAD produced files owned by another user" >&2
exit 1
fi

- name: Index physical evidence in release manifest
run: |
make -C tests/fixture-module \
FLOW_ROOT="${GITHUB_WORKSPACE}" \
DISABLED_FLOWS="verible_lint verible_format slang_elaboration verilator_lint yosys_synthesis symbiyosys_formal eqy_equivalence verilator_sim pyuvm_open_source coverage_qualification negative_qualification four_state_qualification static_intent vcs_sim pyuvm_commercial vc_lint vc_cdc sg_cdc sg_dft vc_lp synopsys_synthesis synopsys_primetime synopsys_primepower" \
MODULE_REVISION="${GITHUB_SHA}" \
METHODOLOGY_REVISION="${GITHUB_SHA}" \
RELEASE_EXECUTION_CONTEXT=container \
RELEASE_TECHNOLOGY=nangate45 \
release-manifest release-manifest-validate
grep -Fq 'reports/openroad/evidence.json' \
tests/fixture-module/reports/release_manifest/container/manifest.json

- name: Upload physical fixture evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: mosaic-flow-openroad-nangate45
path: |
tests/fixture-module/reports/openroad/
tests/fixture-module/reports/release_manifest/container/
tests/fixture-module/work/openroad/results/
tests/fixture-module/work/openroad/reports/
tests/fixture-module/work/openroad/logs/
if-no-files-found: error
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
tests/fixture-module/work/
tests/fixture-module/reports/*
!tests/fixture-module/reports/.gitkeep
tests/fixture-multi-module/work/
tests/fixture-multi-module/reports/
tests/fixture-parameter-profiles/work/
tests/fixture-parameter-profiles/reports/
__pycache__/
*.py[cod]
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ methodology without copying flow scripts or changing module RTL.
- Make targets and flow dependency orchestration
- Open-source and Synopsys tool adapters
- Optional PyUVM verification with open-source, VCS, and Xcelium backends
- Single-module and manifest-based multi-module project orchestration
- Named parameter-profile qualification across elaboration and implementation
- Declarative HDL and formal coverage qualification with reviewed exclusions
- Declarative negative-test and four-state qualification with explicit controls
- Declarative, license-independent SDC and UPF intent validation
- Reproducible local or pinned-container ORFS implementation with declarative physical evidence
- Flow selection, statuses, reports, and quality gates
- Schema-validated release evidence with input hashes and tool identities
- Pinned open-source tool installers and versions
- Methodology CI and its independent fixture module

Expand All @@ -33,6 +40,8 @@ reference, and links to:
- PyUVM, SVA, and coverage reuse across verification environments
- Every open-source and commercial flow
- Results, quality gates, waivers, and release evidence
- Portable SDC and UPF intent checks and their signoff boundary
- Containerized OpenROAD execution and physical evidence policy
- Methodology development, qualification, and release procedures

## Consumer quick start
Expand All @@ -56,9 +65,18 @@ include $(FLOW_ROOT)/config/tools.mk
include $(FLOW_ROOT)/mk/module.mk
```

A repository containing multiple independently qualified modules instead uses
the project bootstrap and a validated module manifest:

```make
include $(FLOW_ROOT)/mk/project.mk
```

See [Getting started](docs/getting-started.md) for the complete module contract
and [Configuration](docs/configuration.md) for flow selection, dependencies,
tool overrides, and technology setup.
and [Multi-module projects](docs/multi-module-projects.md) for registry,
selection, concurrent execution, and CI matrix guidance. Parameterizable RTL
can use [Parameter profiles](docs/parameter-profiles.md) to qualify independent
elaborations without duplicating flow scripts.

## Methodology validation

Expand All @@ -69,6 +87,9 @@ complete portable fixture flow:
ci/install_ci_tools.sh "$HOME/.local"
PATH="$HOME/.local/bin:$PATH" ci/check_flow_quality.sh
make -C tests/fixture-module FLOW_ROOT="$PWD" clean open-source
make -C tests/fixture-multi-module FLOW_ROOT="$PWD" clean all-modules MODULE_JOBS=2
make -C tests/fixture-parameter-profiles FLOW_ROOT="$PWD" clean all-profiles PROFILE_JOBS=4
tests/test_release_manifest.sh
```

GitHub Actions runs the same validation on pushes and pull requests. Commercial
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0
0.8.0
42 changes: 42 additions & 0 deletions ci/cache_openroad_image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
set -euo pipefail

flow_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=../config/tool-versions.env
source "${flow_root}/config/tool-versions.env"

runtime="${OPENROAD_CONTAINER_RUNTIME:-docker}"
image="${OPENROAD_ORFS_IMAGE:-${ORFS_IMAGE_REPOSITORY}@${ORFS_IMAGE_DIGEST}}"
cache_root="${OPENROAD_IMAGE_CACHE_ROOT:-${HOME}/.cache/mosaic/openroad-images}"
archive="${cache_root}/${ORFS_IMAGE_DIGEST#sha256:}.tar"

if ! command -v "${runtime}" >/dev/null 2>&1; then
echo "OpenROAD container runtime is unavailable: ${runtime}" >&2
exit 2
fi
if [[ ! "${image}" =~ @sha256:[0-9a-f]{64}$ ]]; then
echo "OpenROAD image cache requires an immutable @sha256 reference: ${image}" >&2
exit 2
fi

if ! "${runtime}" image inspect "${image}" >/dev/null 2>&1 && [[ -s "${archive}" ]]; then
echo "Loading pinned OpenROAD image from ${archive}"
"${runtime}" load --input "${archive}"
fi

if ! "${runtime}" image inspect "${image}" >/dev/null 2>&1; then
echo "Pulling pinned OpenROAD image: ${image}"
"${runtime}" pull "${image}"
else
echo "Pinned OpenROAD image is available: ${image}"
fi

if [[ ! -s "${archive}" ]]; then
mkdir -p "${cache_root}"
temporary_archive="${archive}.tmp.$$"
trap 'rm -f "${temporary_archive:-}"' EXIT
echo "Saving pinned OpenROAD image layers to ${archive}"
"${runtime}" save --output "${temporary_archive}" "${image}"
mv "${temporary_archive}" "${archive}"
trap - EXIT
fi
28 changes: 27 additions & 1 deletion ci/check_flow_quality.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ flow_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${flow_root}"

mapfile -d '' shell_files < <(
find ci flows tests -path 'tests/fixture-module/work' -prune -o \
find ci flows tests -type d \( -name work -o -name reports \) -prune -o \
-type f -name '*.sh' -print0 | sort -z
)
mapfile -d '' workflow_files < <(find .github/workflows -type f \( -name '*.yml' -o -name '*.yaml' \) -print0 | sort -z)
Expand All @@ -16,6 +16,18 @@ done

shellcheck --external-sources "${shell_files[@]}"
actionlint "${workflow_files[@]}"
python3 -m py_compile ci/module_manifest.py
python3 -m py_compile ci/parameter_profiles.py
python3 -m py_compile ci/release_manifest.py
python3 -m py_compile ci/coverage_qualification.py
python3 -m py_compile ci/qualification_campaign.py
python3 -m py_compile ci/static_intent.py
python3 -m py_compile ci/openroad_evidence.py
python3 -m json.tool schemas/release-evidence-v1.schema.json >/dev/null
python3 -m json.tool schemas/coverage-policy-v1.schema.json >/dev/null
python3 -m json.tool schemas/qualification-campaigns-v1.schema.json >/dev/null
python3 -m json.tool schemas/static-intent-v1.schema.json >/dev/null
python3 -m json.tool schemas/openroad-evidence-policy-v1.schema.json >/dev/null

if ! grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' VERSION; then
echo "VERSION must contain a semantic version such as 1.2.3" >&2
Expand All @@ -36,6 +48,8 @@ required_version_keys=(
SHELLCHECK_SHA256
ACTIONLINT_VERSION
ACTIONLINT_SHA256
ORFS_IMAGE_REPOSITORY
ORFS_IMAGE_DIGEST
)
source config/tool-versions.env
for version_key in "${required_version_keys[@]}"; do
Expand All @@ -45,6 +59,11 @@ for version_key in "${required_version_keys[@]}"; do
fi
done

if [[ ! "${ORFS_IMAGE_DIGEST}" =~ ^sha256:[0-9a-f]{64}$ ]]; then
echo "ORFS_IMAGE_DIGEST must be an immutable sha256 digest" >&2
exit 1
fi

for requirement in \
"pyuvm==${PYUVM_VERSION}" \
"cocotb==${COCOTB_VERSION}" \
Expand All @@ -69,4 +88,11 @@ while IFS= read -r -d '' data_file; do
done < <(find . -path './.git' -prune -o -type f \( -name '*.tcl' -o -name '*.mk' -o -name '*.env' \) -print0)

tests/test_quality_gate.sh
tests/test_multi_module.sh
tests/test_parameter_profiles.sh
tests/test_release_manifest.sh
tests/test_coverage_qualification.sh
tests/test_qualification_campaigns.sh
tests/test_static_intent.sh
tests/test_openroad_evidence.sh
echo "mosaic-flow static quality checks passed"
9 changes: 6 additions & 3 deletions ci/clean.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail

rm -rf -- "${MODULE_ROOT}/work"
if [[ -d "${MODULE_ROOT}/reports" ]]; then
find "${MODULE_ROOT}/reports" -mindepth 1 ! -name .gitkeep -delete
work_root="${WORK_DIR:-${MODULE_ROOT}/work}"
report_root="${REPORT_DIR:-${MODULE_ROOT}/reports}"

rm -rf -- "${work_root}"
if [[ -d "${report_root}" ]]; then
find "${report_root}" -mindepth 1 ! -name .gitkeep -delete
fi
Loading
Loading