A multi-module repository can qualify related RTL blocks independently while
sharing one pinned mosaic-flow checkout. Each registered module owns its design
configuration and flow policy. The methodology owns registry validation,
selection, concurrent dispatch, and output isolation.
Single-module repositories do not need a manifest and may retain the original import sequence. Adopt this interface only when one repository contains more than one independently selectable design top.
Use the project bootstrap instead of loading config/design.mk directly:
SHELL := /usr/bin/env bash
export MODULE_ROOT := $(CURDIR)
export FLOW_ROOT ?= $(abspath $(MODULE_ROOT)/mosaic-flow)
include $(FLOW_ROOT)/mk/project.mkmk/project.mk detects MODULE_MANIFEST, loads the selected module profile,
then imports the normal tool and target APIs. Its default manifest path is
config/modules.json.
The mosaic-modules-v1 schema uses a nonempty include array. Every entry
requires a unique lowercase name. Additional JSON fields are preserved in the
generated CI matrix.
{
"schema": "mosaic-modules-v1",
"include": [
{
"name": "counter",
"artifact_suffix": "native"
},
{
"name": "clock_gate",
"artifact_suffix": "native"
}
]
}For each name, the validator requires:
config/modules/<name>.mk
config/modules/<name>-flows.mk
Names accept lowercase letters, digits, and underscores, must begin with a letter, and cannot contain path separators. Duplicate names, malformed JSON, unknown selections, and missing configuration fail before a tool starts.
The design profile exports the same variables as a single-module
config/design.mk. REPORT_DIR and WORK_DIR default to isolated paths and do
not need to be repeated.
export DESIGN_TOP := counter
export TB_TOP := $(DESIGN_TOP)_tb
export FORMAL_TOP := $(DESIGN_TOP)_formal
export DUT_INSTANCE := $(TB_TOP)/dut
export RTL_FILELIST := $(call mosaic_resolve_filelist,rtl.f)
export TB_FILELIST := $(call mosaic_resolve_filelist,tb.f)
export FORMAL_CONFIG := $(call mosaic_resolve_flow_config,symbiyosys,formal.sby)
export CONSTRAINT_DIR := $(MODULE_ROOT)/flows/synthesisThe resolver functions implement these searches:
filelists/<DESIGN_TOP>.<filename>
filelists/<filename>
flows/<flow>/<DESIGN_TOP>.<filename>
flows/<flow>/<filename>
The first existing named input wins. The fallback path is returned when neither path exists so the consuming adapter reports the missing required input.
The matching <name>-flows.mk file declares the complete FLOW_<id> policy and
dependency overrides for that module.
Validate and query the registry with:
make module-manifest-check
make module-list
make module-matrix
make module-profile-matrixRun one module with any normal target:
make MODULE=counter flow-config-check
make MODULE=counter clean open-sourceA flow target without MODULE fails in a multi-module project. Administrative
targets do not require a selection.
Run one target for every module with:
make all-modules
make all-modules TARGET=open-formal MODULE_JOBS=4TARGET defaults to open-source. MODULE_JOBS=0 allows GNU xargs to use all
available processors. A positive value bounds concurrency. The aggregate waits
for every invocation and returns nonzero if any module fails. Results from
modules that completed successfully remain available.
Each selected module defaults to:
reports/<module>/<flow-id>/
work/<module>/<flow-id>/
If a selected module declares parameter profiles, the profile name is inserted
before the flow ID. module-profile-matrix emits the Cartesian registry defined
by each module's own manifest, while a module with no profile manifest emits one
default entry. See Parameter-profile qualification.
make MODULE=<name> clean removes only that module's generated state. Running
make clean without a selection removes the complete project work and report
trees.
Profiles can set formatting policy without a wrapper command:
export VERIBLE_FORMAT_ARGS := --indentation_spaces=4
export VERIBLE_FORMAT_PATHS := rtl/counter.sv verif/counterBoth variables are whitespace-separated. Paths are relative to MODULE_ROOT
and may name files or directories. Narrow VERIBLE_FORMAT_PATHS in flat
multi-module repositories so one module job does not recheck unrelated sources.
Generate the matrix from the validated methodology API:
jobs:
module-matrix:
runs-on: ubuntu-24.04
outputs:
matrix: ${{ steps.modules.outputs.matrix }}
flow_revision: ${{ steps.flow.outputs.revision }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Read pinned mosaic-flow revision
id: flow
run: |
revision="$(git ls-files --stage mosaic-flow | awk '$1 == "160000" {print $2}')"
test "${#revision}" -eq 40
echo "revision=${revision}" >> "${GITHUB_OUTPUT}"
- uses: actions/checkout@v4
with:
repository: ECASLab/mosaic-flow
ref: ${{ steps.flow.outputs.revision }}
path: mosaic-flow
persist-credentials: false
- name: Generate matrix
id: modules
run: echo "matrix=$(make module-profile-matrix)" >> "${GITHUB_OUTPUT}"
rtl-checks:
name: ${{ matrix.job_name }} / native
needs: module-matrix
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.module-matrix.outputs.matrix) }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/checkout@v4
with:
repository: ECASLab/mosaic-flow
ref: ${{ needs.module-matrix.outputs.flow_revision }}
path: mosaic-flow
persist-credentials: false
- name: Verify pinned mosaic-flow revision
run: |
actual="$(git -C mosaic-flow rev-parse HEAD)"
test "${actual}" = "${{ needs.module-matrix.outputs.flow_revision }}"
- uses: actions/cache@v4
with:
path: ~/.cache/mosaic
key: mosaic-${{ runner.os }}-${{ matrix.module }}-${{ matrix.profile }}-${{ needs.module-matrix.outputs.flow_revision }}
- run: make MODULE="${{ matrix.module }}" PROFILE="${{ matrix.profile }}" clean open-source
- uses: actions/upload-artifact@v4
if: always()
with:
name: ${{ matrix.job_name }}-reports
path: reports/${{ matrix.module }}/
if-no-files-found: errorContainer jobs use the same matrix and pass MODULE=${{ matrix.module }} and
PROFILE=${{ matrix.profile }} to the container command. Give every job a
module/profile-qualified cache scope, image tag, artifact name, report path, and
diagnostic log. In both native and container jobs, read the expected methodology
revision from the parent gitlink and verify the checked-out or embedded revision
before running the flow.
For a repository with consumer-owned orchestration such as mosaic-common:
- Move the module list to
config/modules.jsonand add themosaic-modules-v1schema field. - Replace the custom root imports and
all-modulesrecipe withinclude $(FLOW_ROOT)/mk/project.mk. - Keep module profiles under
config/modules/and remove duplicated profile existence checks. - Replace local resolver functions with
mosaic_resolve_filelistandmosaic_resolve_flow_config. - Remove explicit
REPORT_DIRandWORK_DIRassignments when the standard isolated paths are sufficient. - Replace formatter wrapper scripts with
VERIBLE_FORMAT_ARGSandVERIBLE_FORMAT_PATHSwhere possible. - Generate the CI matrix through
make module-profile-matrixwhen any module declares profiles, and retain exact gitlink verification in every job.
Run make module-manifest-check before removing the old orchestration, then
compare one native and one containerized result per module.