Files
mxpic_EDA/docs/superpowers/specs/2026-05-31-required-mxpic-router-stack-design.md
T

5.8 KiB

Required mxpic_router Stack Design

Date: 2026-05-31

Goal

Unify layout preview and GDS generation behind the same Nazca/mxpic_router pipeline. mxpic_router is no longer an optional routed-only helper. It is a required runtime package for mxpic_EDA, and both repositories should be released together as a matched pair.

Current Problem

Build Layout currently has two backend preview paths:

  • No bundles.*.links: server.py calls create_layout_svg_from_gds, which directly places PDK GDS with gdstk.
  • With bundles.*.links: server.py calls create_routed_layout_svg, which delegates to mxpic_router, builds Nazca GDS, then converts that GDS to SVG.

This duplicates layout semantics. Placement-only cells and routed cells can drift because they are built by different engines. Maintenance is harder because every future layout feature must be considered in two paths.

Decision

Use one canonical build path for both preview SVG and project GDS:

saved YAML -> mxpic_router -> Nazca GDS -> gdstk SVG conversion when needed

mxpic_router and its required build stack are hard dependencies. The Flask server should verify the whole stack before startup, fail early if anything is missing, and give an actionable message.

Dependency Gate

Add backend/router_dependency.py as the single backend module responsible for router dependency validation.

Responsibilities:

  • Add the sibling checkout path ../mxpic_router to sys.path when it exists, preserving the current local-development pattern.
  • Import mxpic_router.build_project_gds.
  • Import nazca, because router output is built as Nazca cells.
  • Import gdstk, because preview SVG still converts router-generated GDS with gdstk.read_gds(...).top_level()[0].write_svg(...).
  • Probe the route backend by importing mxpic_router.builder._import_mxpic_forge_route and calling it. This uses the same mxpic_forge/mxpic.Route lookup that actual router builds use.
  • Return a small structured result for startup logging and tests.
  • Raise a clear RuntimeError when the stack is incomplete.

Server startup should call this check before app.run. In script mode, startup should exit before Flask launches if the dependency gate fails.

Build Layout Flow

Build Layout should always use the router-backed preview path:

frontend/canvas.html handleBuildLayout -> POST /api/save-layout -> backend/server.py save_layout writes <cell>.yml and route sidecar -> create_routed_layout_svg(...) -> mxpic_router.build_project_gds(...) with target_cell_name=<cell> -> temporary .gds -> gdstk.write_svg(...) -> saved <cell>.svg.

There should be no layout_has_links branch in save_layout. A no-link layout is still a valid router input; the router builds placed instances and exports the requested top cell without drawing routes.

layout_preview.py can remain in the tree only if it is still useful as a manual diagnostic module. It should not be used by production preview requests.

Build GDS Flow

Build GDS should always delegate to mxpic_router.

backend/gds_builder.py build_project_gds should:

  • Load saved project YAML files only if needed for validation/error messages.
  • Call _build_with_mxpic_router(...) as the canonical builder.
  • Remove silent fallback to _build_with_gdstk and _build_with_nazca.
  • Raise a clear error if the required router stack is unavailable, though this should normally be caught at server startup.

The old fallback functions may be removed if tests and imports no longer need them. If kept temporarily, they must be clearly marked as unused diagnostics and not reachable from the production API.

Error Handling

Dependency failures should be early and explicit:

  • Missing mxpic_router: tell the operator to install or place the matched sibling checkout.
  • Missing nazca: tell the operator the router runtime cannot build GDS.
  • Missing gdstk: tell the operator previews cannot convert GDS to SVG.
  • Missing route backend: tell the operator routing primitives are unavailable.

Request-time failures should remain JSON API errors, but normal deployment should fail at startup before users can reach these routes.

Testing

Update static/backend tests to assert the new contract:

  • server.py imports and calls the router dependency gate before startup.
  • /api/save-layout calls create_routed_layout_svg unconditionally for previews.
  • /api/save-layout no longer branches on layout_has_links to choose between gdstk and router preview builders.
  • gds_builder.py delegates to _build_with_mxpic_router without gdstk/Nazca production fallback.
  • The router dependency module checks mxpic_router, nazca, gdstk, and the route backend.
  • GDS_SVG_GENERATION_LOGIC.md documents the unified path.

Add a runtime smoke test for the local development environment when the required router stack is installed: a no-link saved YAML cell should generate SVG through create_routed_layout_svg. If CI does not install Nazca/router dependencies, keep that test explicitly skipped unless the dependency gate passes.

Release Policy

mxpic_EDA and mxpic_router should be released simultaneously.

Recommended lightweight policy:

  • Update deployment notes to state that both repositories must be deployed as a matched pair.
  • Keep a visible compatibility note in README.md or deployment docs.
  • Version compatibility checks are out of scope until both repositories expose explicit version constants; until then, deployment docs carry the matched-pair release requirement.

Non-Goals

  • Do not redesign the frontend YAML format in this change.
  • Do not vendor/copy mxpic_router source into mxpic_EDA.
  • Do not replace gdstk SVG conversion in this change; it remains the converter after router-generated GDS.
  • Do not add fallback behavior that hides a missing or incompatible router stack.