mrg.build

Local synthesis and place-and-route feedback in the toolchain image. No board and no cloud: run synth for a fast utilization report, or pnr for full-SoC Fmax and timing.

manhattan_reasoning_gym.build

Local build feedback — fast synth/PnR reports, no cloud and no board.

Auto-selects its backend: runs the FPGA toolchain in-process inside the sandbox image, or transparently runs the pinned Docker image on a user's machine. So pip install + Docker is all a user needs — they never install yosys/nextpnr/LiteX. Raises SandboxUnavailableError if neither the toolchain nor Docker is available.

SandboxUnavailableError

Bases: RuntimeError

No way to run a local build: neither the toolchain nor Docker is available.

Source code in _code/src/manhattan_reasoning_gym/_local_build.py
class SandboxUnavailableError(RuntimeError):
    """No way to run a local build: neither the toolchain nor Docker is available."""

synth

synth(design: str | Path, *, top: str | None = None, work: str | Path | None = None) -> BuildReport

Synthesis report for a design.py or design.v: resource util, fast, no timing.

top is a plain-Verilog-only disambiguator (ignored for Amaranth designs) — only needed when the file has more than one module exposing the required Wishbone contract; the top module is otherwise auto-detected.

Source code in _code/src/manhattan_reasoning_gym/_local_build.py
def synth(
    design: str | Path, *, top: str | None = None, work: str | Path | None = None
) -> BuildReport:
    """Synthesis report for a design.py or design.v: resource util, fast, no timing.

    ``top`` is a plain-Verilog-only disambiguator (ignored for Amaranth
    designs) — only needed when the file has more than one module exposing
    the required Wishbone contract; the top module is otherwise auto-detected.
    """
    return _build("synth", design, top=top, work=work)

pnr

pnr(design: str | Path, *, top: str | None = None, target_mhz: float | None = None, sys_clk_mhz: float | None = None, timing_target_mhz: float | None = None, seed: int = 1, work: str | Path | None = None) -> BuildReport

Full-SoC place-and-route report: Fmax, timing-met, SoC-wide util.

top is the same optional Verilog disambiguator as synth. sys_clk_mhz re-clocks the SoC (PLL output); timing_target_mhz is the constraint PnR optimizes against and timing_met is graded on, defaulting to the sys clock. target_mhz is a legacy alias that sets both — passing it alongside either new knob is rejected by the toolchain.

Source code in _code/src/manhattan_reasoning_gym/_local_build.py
def pnr(
    design: str | Path,
    *,
    top: str | None = None,
    target_mhz: float | None = None,
    sys_clk_mhz: float | None = None,
    timing_target_mhz: float | None = None,
    seed: int = 1,
    work: str | Path | None = None,
) -> BuildReport:
    """Full-SoC place-and-route report: Fmax, timing-met, SoC-wide util.

    ``top`` is the same optional Verilog disambiguator as ``synth``.
    ``sys_clk_mhz`` re-clocks the SoC (PLL output); ``timing_target_mhz`` is the
    constraint PnR optimizes against and ``timing_met`` is graded on, defaulting
    to the sys clock. ``target_mhz`` is a legacy alias that sets both — passing it
    alongside either new knob is rejected by the toolchain.
    """
    return _build(
        "pnr", design, top=top, target_mhz=target_mhz, sys_clk_mhz=sys_clk_mhz,
        timing_target_mhz=timing_target_mhz, seed=seed, work=work,
    )