Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
76 changes: 76 additions & 0 deletions .github/workflows/flow-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,79 @@ jobs:

- 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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ methodology without copying flow scripts or changing module RTL.
- 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
Expand All @@ -40,6 +41,7 @@ reference, and links to:
- 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 Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.7.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
10 changes: 10 additions & 0 deletions ci/check_flow_quality.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ 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 @@ -46,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 @@ -55,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 Down Expand Up @@ -85,4 +94,5 @@ 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"
Loading
Loading