feat(data): split skippable steps into SkippableStepEnum - #286
Merged
Merged
Conversation
25 tasks
…rs into step Pure file reorganization with zero behavior change: - new data/types.py holds StepEnum, StateEnum, FINISHED_STEP_STATES, is_finished_step_state (enum vocabulary + pure predicates, no IO) - data/step.py keeps StepMetrics/load_metrics/save_metrics and absorbs STEP_DIRECTORIES from data/step_dirs.py (docstring included); data/step_dirs.py is deleted - data/__init__.py re-exports from .types; direct importers repointed
Three-layer step enum: memberless StepBaseEnum carries shared behavior; StepEnum keeps the core chain members; SkippableStepEnum owns the optional LEC, postRouteLec and Timing optimization steps (persisted values unchanged). step_from_value resolves a persisted step value across both enums; reverse lookups in tools/ecc service and subflow use it. All former StepEnum.LEC/POST_ROUTE_LEC/TIMING_OPT references are migrated to SkippableStepEnum
One authoritative resolver owns skip-policy semantics: resolve_skip_steps reads the skip_steps key from a flow config with presence semantics (absent key -> code default (lec,); explicit [] -> run everything), normalizes aliases, validates membership against the skippable step set in canonical chain order, and rejects invalid values. build_rtl2gds_flow gains a skip filter and restores the synthesis LEC into the canonical chain (reverting the #280 comment-out); build_flow_range filters before slicing so a skipped step cannot bound a range. Ledger creation paths (dynamic flow data, preset seeding, ledger-less rebuild) resolve the policy through the same resolver, keeping default behavior identical
project.json workspaces[].skip_steps and ecc.toml [flow] skip_steps are both parsed and validated (invalid values fail the manifest load / config validation before any mutation). The declared spelling is preserved verbatim on round-trip; only the persisted workspace policy is normalized. Precedence for this one key is skip-specific: project.json outranks ecc.toml (including an explicit empty list); every other field keeps the ecc.toml-wins contract. Workspace [flow] sections accept a normalized skip_steps (three states distinct: absent / [] / list) and policy-only sections are valid. ecc init materializes the default skip_steps = ["lec"] with an explanatory comment into generated ecc.toml; legacy-run migration carries a workspace's persisted policy into its manifest entry
data.create_workspace resolves the skip policy before touching the filesystem, so an invalid policy is a clean configuration error instead of a partial workspace tree. The runtime API validates it before materializing sidecar artifacts (temp filelist, inline PDK). Creation path equivalence is pinned by a test: preset, ranged, and sidecar paths build identical ledgers for one policy, and a policy-only flow config never yields a ledger
Reconcile targets now apply the [flow] section's skip policy, so post-revert ledgers reconcile naturally under the default policy and the legacy_missing_synthesis_lec hack is deleted. A ledger holding steps the effective policy skips stays runnable: those entries are inert for comparison and are never removed or re-inserted (append skips entries the ledger already holds). Selecting the synthesis_lec preset while the effective policy skips lec is a creation-time configuration error naming skip_steps = [] as the fix; resume/rerun on existing ledgers is unaffected
… on filtered steps The signoff collector and the ECC checklist require postRouteLec only when the workspace ledger actually contains it: a workspace created with postRouteLec skipped never false-fails, while genuine truncated-signoff failures are preserved. SIGNOFF_REQUIRED_QOR_STEPS is pinned by a test to contain no skippable step. Run preflight resolves its probe set from the policy-filtered step list, so skipping TimingOpt drops the sizer probe and the default policy never probes the synthesis LEC
Workspace-creation behavior tests pin the input-chaining contract under each skip policy: the default keeps the synthesis LEC out of the ledger so preFloorplan directly consumes synthesis outputs; an explicit empty skip list restores the LEC entry; skipping Timing optimization chains routing after legalization and skipping postRouteLec chains DRC after LVS. Ledgers drive step-directory creation and step inputs, so a skipped step owns neither
Document the skip mechanism on both development guides: the skippable set (lec, postRouteLec, Timing optimization), the skip-specific precedence (project.json over ecc.toml over the code default), explicit empty list as the only LEC enable, the synthesis_lec preset conflict, and ledger immutability under policy changes. Stale claims that the rtl2gds preset runs an active synthesis LEC by default are corrected to the default-skipped behavior. Forward compatibility is pinned: unknown flow_config keys never become ledger steps
- a skipped step can no longer bound a [flow] range: validate_flow_config rejects it, and create_workspace validates the resolved selection before any filesystem mutation - a policy-only flow config (skip_steps without a range) persists its normalized policy into _flow so runtime ledger-less rebuilds honor an explicit skip_steps = [] instead of silently falling back to the default - the preset-path _flow persistence normalizes skip_steps through validate_flow_config instead of copying raw aliases - run_existing carries the declared skip policy on the preset target so existing workspaces classify against the same policy fresh creation uses - ecc config shows the effective flow.skip_steps with its winning layer (or the code default) - EngineFlow.add_step accepts StepBaseEnum like init_flow_step - docs: corrected remaining stale claims that the synthesis LEC runs by default (cli-design, config ref, user guide, tutorial, development)
- extract post-route LEC gating into tools/ecc/lec_gates.py so signoff_checklist.py stays under the module size guideline - move the synthesis_lec preset / skip-policy run tests into test/cli/commands/test_run_skip_policy.py - render_workspace_config persists the validated (normalized) [flow] section, so a declared policy lands canonical in params.toml no matter which path saves it - run_existing preset target carries the declared skip policy so existing workspaces classify against the creation-time policy - correct remaining Chinese user-guide/tutorial claims that the synthesis LEC runs by default
- fresh manifest registration materializes the workspace's declared
skip policy onto the project.json entry (declared spelling preserved)
- the existing-workspace run path classifies against the effective
declared policy (flow_config's resolved skip_steps, falling back to
ecc.toml), so a per-workspace project.json policy wins over ecc.toml
as with fresh creation
- preset-shaped flow configs now build the preset's ledger and persist
{preset, skip_steps} through the data/runtime creation path instead of
being silently dropped
- docs: the synthesis_lec examples in both user guides note the required
skip_steps = [], and both tutorials show clearing the list before the
captured run
…icy on existing runs - create_workspace fully resolves the ledger (including a preset target whose endpoint the effective policy skips) before any filesystem mutation, so the conflict surfaces as a clean error with a pristine target instead of a partially created workspace - manifest-mode existing runs now apply the effective declared skip policy (project.json workspaces[].skip_steps over ecc.toml) over the workspace's own [flow] range, so classification, extension, and no-op/resume decisions match fresh creation while the seeded range contract is preserved
- validate_flow_config rejects a preset whose endpoint the declared skip policy excludes, at config-validation time; manifest entries reject a skipped range boundary at load time - reconcile's skip-tolerant comparison only ignores ledger entries whose (name, tool) pair matches the canonical chain, so a corrupted entry is never treated as an inert skipped step - EngineFlow.build_default_steps delegates to the canonical rtl2gds builder instead of maintaining a second hand-written chain - flow-config-to-ledger construction (build_dynamic_flow_data and helpers) extracted into data/workspace/flow_data.py, keeping workspace/__init__.py's size in check; skip-policy workspace and migration tests moved into focused modules - migration blocks (instead of silently defaulting) when a workspace's persisted skip_steps is invalid, naming the offending config - ecc config reports the winning skip_steps layer recorded by effective-config resolution - shared preset-test helpers moved to test/cli/commands/conftest.py - user guides show the generated skip_steps line and the exact edit before the synthesis_lec example
- manifest loading now rejects a workspace range boundary the declared skip policy excludes (display name mapped to the canonical step), with regression coverage for boundary and inside-range cases - migration reads a workspace's params.toml strictly: only a missing config reads as 'no policy'; malformed, undecodable, or unreadable configs block that workspace's migration with a config-specific reason, covered by new tests - the flow_config selects-steps check lives once in effective_config and is imported by run_prepare instead of being duplicated - ProjectConfig declares _skip_steps_source as a typed field
…states - migration validates ledger contiguity against the canonical chain as filtered by the workspace's resolved skip policy, so ledgers legitimately omitting postRouteLec or Timing optimization migrate instead of being blocked as gapped - reconcile evaluates target-prefix states by matching target step names in the ledger rather than positional slicing, so a skipped entry before the boundary can no longer hide an unfinished in-range step; both behaviors carry regression tests
…ontiguity _is_contiguous_flow now distinguishes an undeclared policy (None: the full chain and the legacy lec-less chain both migrate) from an explicit declaration (authoritative: only the full chain and its policy-filtered form are accepted), so skip_steps = [] with a LEC-less ledger is blocked instead of producing a manifest entry the next run cannot reconcile
Emin017
force-pushed
the
emin/support-skippable-steps
branch
from
September 15, 2026 10:03
0d2ce74 to
1c483bf
Compare
…solidation Adaptations for the latest main (9081182) that have no counterpart in the branch history: repoint STEP_DIRECTORIES imports in analysis/qor/loader.py and engine/analysis.py to data.step (data.step_dirs was merged into step.py), and reference SkippableStepEnum.TIMING_OPT in the sizer and step-storage-name tests.
Emin017
force-pushed
the
emin/support-skippable-steps
branch
from
September 15, 2026 10:12
1c483bf to
efd39cd
Compare
Yell-walkalone
approved these changes
Sep 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What Changed
Add a configuration-driven skip mechanism for optional RTL-to-GDS flow steps (synthesis LEC, postRouteLec, Timing optimization), preceded by a preparatory file reorganization:
chipcompiler/data/types.pyholds the step/state enums and pure predicates;step_dirs.pyis merged intodata/step.py(with its naming-convention docstring);data/__init__.pyre-exports keepfrom chipcompiler.data import StepEnumworking.StepBaseEnum(shared behavior) with siblingStepEnum(core chain) andSkippableStepEnum(LEC,POST_ROUTE_LEC,TIMING_OPT); persisted string values are unchanged. Newstep_from_value()resolves step values across both enums; all 133 former references migrated.resolve_skip_steps()— presence-keyed (absent key → code default("lec",); explicit[]→ run everything, the only way to enable the synthesis LEC), alias normalization to canonical order, strict validation against the skippable set.project.json workspaces[].skip_steps(wins for this key only, including explicit[]) >ecc.toml [flow] skip_steps> code default. Raw declared spelling is preserved verbatim on manifest round-trip; only the persisted workspace policy is normalized.ecc initmaterializes the commented default (skip_steps = ["lec"]) into generated ecc.toml; legacy-run migration carries the persisted policy into the manifest entry.workspace.flow.json— all creation paths (CLI preset, CLI range, sidecar/GUI flow_config, preset-shaped configs) build identical ledgers through one resolver, fully validated before any filesystem mutation. Input chaining falls through to the previous retained step; the state machine, run loop, and resume/rerun are unchanged.legacy_missing_synthesis_lechack is deleted. Ledgers holding steps the policy skips stay runnable (those entries are inert — never removed or re-inserted); changing the policy can never insert/remove steps in an existing ledger.synthesis_lecconflict: selecting the preset while the effective policy skipslecis a creation-time configuration error namingskip_steps = []as the fix; existing-ledger resume/rerun is unaffected.SIGNOFF_REQUIRED_QOR_STEPSpinned by test to contain no skippable step.[]as the LEC enable, preset conflict, ledger immutability, and the skippable set.Scope
Select the areas touched by this PR:
uv.lock, or release artifacts.Runtime And Packaging Impact
ecc-toolsorecc-dreamplacedependency changedNotes:
project.jsongains an optionalworkspaces[].skip_stepslist; unknown fields/keys stay forward-compatible (old GUI reads preserve it, new ECC tolerates unknown flow_config keys). Existing projects without the key keep the code default("lec",)and are never re-filtered.home/params.toml [flow]sections accept a normalizedskip_steps(absent /[]/ list round-trip distinctly);ecc configshows the effective policy and its winning layer.Validation
List the commands you ran. Mark checks that are not applicable as N/A.
uv run pytest test/uv run ruff check chipcompiler testuv run ruff format --check chipcompiler testecc --help,ecc --version,ecc version --json— N/A (no packaging change)nix run .#cli -- --help— N/A (no packaging change)test/data/test_workspace_skip_policy.py,test/formal/test_file_chaining.py)Skipped checks and reason:
Checklist