From f4a3fd60b73adc6be98b16ecf6672a7ca9f16e14 Mon Sep 17 00:00:00 2001 From: cscaff Date: Wed, 15 Jul 2026 09:53:20 -0400 Subject: [PATCH] Update docs for 0.1.6: board-less submit, mrg jobs, decoupled job status CLI/SDK guides still described client-side board picking (find_idle_fpga, --fpga-id as a board request) and the old job/logs/cancel [job_id] signature -- both replaced by the board-less build-slot pipeline. Rewrote run/status/jobs/job/logs/cancel in cli.md, App(fpga_id=...)'s real meaning (--no-program reconnect only) in sdk.md, and quickstart's "picks an idle board" line to match. Added a 0.1.6 changelog entry. Also fixed reference/cloud.md's mkdocstrings member list: NoFPGAAvailableError no longer exists in mrg.cloud (removed with find_idle_fpga), and Stream was missing despite being a real, current export. Co-Authored-By: Claude Sonnet 5 --- docs/changelog.md | 27 ++++++++++++++++++++ docs/guides/cli.md | 53 +++++++++++++++++++++++++++------------ docs/guides/quickstart.md | 10 +++++--- docs/guides/sdk.md | 13 +++++++++- docs/reference/cloud.md | 2 +- 5 files changed, 83 insertions(+), 22 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index fb4bc93..d198095 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,6 +7,33 @@ description: Release notes for the manhattan-reasoning-gym SDK and CLI. Notable changes to the `manhattan-reasoning-gym` SDK and CLI. The project is in private beta, so surfaces may still change between `0.1.x` releases. +## 0.1.6 (private beta) + +### Changed +- **Board-less submit.** `App`/`mrg run` no longer picks a board before + building — the server claims a build slot (a network identity baked into + the bitstream, decoupled from any physical board) and dispatches the build + immediately, so many builds now run concurrently regardless of how many + physical boards are live. `app.fpga_id` is filled in once some board's + worker claims the finished bitstream and flashes it, not chosen up front. + `App(fpga_id=...)` / `mrg run --fpga-id` now only matter for the + `--no-program` reconnect case (skip rebuilding, talk to a board you already + have a live session on). +- `mrg job`, `mrg logs`, and `mrg cancel` now take a `job_id` directly instead + of ` [job_id]` — jobs are looked up by their own id, not scoped + under a board, since a job with no board assigned yet has no board to look + it up by. +- FPGA states are now `idle`, `programming`, `reserved`, `error` — `queued` + and `building` were board states describing a build in progress on that + board; a build never touches a board anymore, so those states no longer + apply to one. + +### Added +- `mrg jobs [--status STATUS]`: list every job the caller's API key has + submitted, newest first — the only way to find a board-less build's + `job_id` while it's still in flight, since it has no board to check + instead. + ## 0.1.5 (private beta) ### Added diff --git a/docs/guides/cli.md b/docs/guides/cli.md index 17d8626..99c184e 100644 --- a/docs/guides/cli.md +++ b/docs/guides/cli.md @@ -45,27 +45,37 @@ Docker image. mrg run [--fpga-id N] [--no-program] [--sys-clk HZ] [--timing-target-mhz MHZ] ``` -Loads the [`mrg.cloud.App`](sdk.md#app) from `file.py`, programs the FPGA -(picking an idle board automatically unless `--fpga-id` or the app pins one), -then calls its [`@local_entrypoint`](sdk.md#applocal_entrypoint). +Loads the [`mrg.cloud.App`](sdk.md#app) from `file.py`, submits the design and +blocks until it's built and flashed, then calls its +[`@local_entrypoint`](sdk.md#applocal_entrypoint). No board is chosen up +front: the server claims a build slot (a network identity baked into the +bitstream, decoupled from any physical board) and dispatches the build +immediately, and whichever board frees up first claims the finished bitstream +and flashes it — `app.fpga_id` is filled in from that completed job, not +picked by the CLI or the app. `--fpga-id` overrides `App(fpga_id=...)`, which +only matters for the `--no-program` reconnect case below; it is not a way to +request a specific board for a fresh build. ```bash mrg run examples/app.py -mrg run my_design.py --fpga-id 3 --sys-clk 90e6 +mrg run my_design.py --fpga-id 3 --no-program # reconnect, skip rebuilding ``` -## `status`, `job`, `logs`: read-only, no login required +## `status`, `jobs`, `job`, `logs`: read-only, no login required ```bash mrg status [fpga_id] [--json] -mrg job [job_id] [--json] -mrg logs [job_id] +mrg jobs [--status STATUS] [--json] +mrg job [--json] +mrg logs ``` `status` with no argument prints the full board table; with an `fpga_id`, -that board's detail (state, owner, current job). `job_id` is optional on -`job`/`logs`, omit it and the CLI resolves whatever job is currently running -on that board. +that board's detail (state, owner, current job). `jobs` lists every job the +caller's API key has submitted, newest first — the only way to find a +build's `job_id` while it's still in flight, since a board-less build has no +board to look it up by. `job`/`logs` take a `job_id` directly (jobs are +looked up by their own id now, not scoped under a board). ```text ID STATE OWNER CURRENT JOB @@ -74,20 +84,31 @@ on that board. 3 reserved alice a1b2c3d4… ``` -States: `idle`, `queued`, `building`, `programming`, `reserved`, `error`. +States: `idle`, `programming`, `reserved`, `error`. -When a build fails, `mrg logs ` prints the toolchain output (Yosys / +```text + JOB_ID TYPE STATUS FPGA CREATED + ────────────────────────────────────────────────────────── + 8bf0de40… reset complete 2 2026-07-15T12:48:23Z + a4c92b62… run failed 2 2026-07-15T12:48:19Z + 8d4fa7d8… build_and_program complete 2 2026-07-15T12:45:27Z +``` + +`FPGA` is blank until a board claims the job (still building, or waiting to +flash) — poll `mrg jobs`/`mrg job ` rather than assuming a board is +assigned right after submit. + +When a build fails, `mrg logs ` prints the toolchain output (Yosys / nextpnr) so you can see what was rejected. ## `cancel`: stop a job ```bash -mrg cancel [job_id] +mrg cancel ``` -Cancels a queued job, or stops an in-flight build. `job_id` is optional here -too, omit it to cancel whatever's currently running on that board. Requires -a real, board-owning API key. +Cancels a queued job, or stops an in-flight build. Requires a real API key +(the caller must be the job's owner). ## `reset`: return a board to idle diff --git a/docs/guides/quickstart.md b/docs/guides/quickstart.md index 227763a..2e50e7b 100644 --- a/docs/guides/quickstart.md +++ b/docs/guides/quickstart.md @@ -60,10 +60,12 @@ mrg run examples/app.py 0 idle - - ``` -`mrg run` picks an idle board automatically (unless the app pins one), builds -and programs it (~2-3 min the first time), then runs the app's entrypoint. The -board stays reserved to you afterward, reuse it with `mrg run --no-program`, -or free it for someone else: +`mrg run` submits the design, builds it (~2-3 min the first time), and flashes +whichever board frees up first — no board is chosen up front, so which one +you land on isn't known until the build finishes. The board stays reserved to +you afterward; if the build is still in flight and you want to check on it +from elsewhere, `mrg jobs` lists your jobs (a build with no board yet has +nowhere else to be found). Free the board for someone else with: ```bash mrg reset 0 diff --git a/docs/guides/sdk.md b/docs/guides/sdk.md index 562b911..8e109f5 100644 --- a/docs/guides/sdk.md +++ b/docs/guides/sdk.md @@ -49,7 +49,7 @@ mrg.cloud.App( name, *, design, # path to the Amaranth .py design - fpga_id=None, # pin a board, or let the SDK pick an idle one + fpga_id=None, # for --no-program reconnect only, see below registers=None, # a RegisterMap subclass (optional) api_key=None, # explicit arg > $MRG_API_KEY > `mrg login` api_url=DEFAULT_API_URL, @@ -61,6 +61,17 @@ mrg.cloud.App( Creating an `App` registers it so the CLI can discover it, you don't export anything. If a file defines several, `mrg run` uses the last one. +**`fpga_id` is normally left unset.** A fresh build never picks a board +itself — the server claims a build slot (a network identity baked into the +bitstream, independent of any physical board) and dispatches the build +immediately; whichever board frees up first claims the finished bitstream and +flashes it. `app.fpga_id` is filled in from that completed job once +[`_program()`](#apprelease) finishes, not chosen up front. Pass `fpga_id` +explicitly only to reconnect to a board you already have a live session on +without rebuilding (`mrg run --no-program --fpga-id N` / `App(..., +fpga_id=N)` with programming skipped) — on any run that does build, whatever +you pass here is overwritten with the real assigned board. + !!! info "Sys clock vs. timing target" A build carries two independent frequencies. **Sys clock** is what the SoC actually runs at (produced by the ECP5 PLL from a fixed 12 MHz input, diff --git a/docs/reference/cloud.md b/docs/reference/cloud.md index 02fcc13..94df1b3 100644 --- a/docs/reference/cloud.md +++ b/docs/reference/cloud.md @@ -8,7 +8,7 @@ a real board, and drive it over MMIO. members: - App - RegisterMap + - Stream - get_session - release_session - - NoFPGAAvailableError - secret