Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<fpga_id> [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
Expand Down
53 changes: 37 additions & 16 deletions docs/guides/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,37 @@ Docker image.
mrg run <file.py> [--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 <fpga_id> [job_id] [--json]
mrg logs <fpga_id> [job_id]
mrg jobs [--status STATUS] [--json]
mrg job <job_id> [--json]
mrg logs <job_id>
```

`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
Expand All @@ -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 <fpga_id>` 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 <job_id>` rather than assuming a board is
assigned right after submit.

When a build fails, `mrg logs <job_id>` prints the toolchain output (Yosys /
nextpnr) so you can see what was rejected.

## `cancel`: stop a job

```bash
mrg cancel <fpga_id> [job_id]
mrg cancel <job_id>
```

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

Expand Down
10 changes: 6 additions & 4 deletions docs/guides/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 12 additions & 1 deletion docs/guides/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/cloud.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ a real board, and drive it over MMIO.
members:
- App
- RegisterMap
- Stream
- get_session
- release_session
- NoFPGAAvailableError
- secret
Loading