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
252 changes: 252 additions & 0 deletions .claude/commands/untar-and-run-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
> **Repo**: Run from the openroad-demo root. `bazelisk` and `_deps` targets need MODULE.bazel.

Produce an "untar and run" reproducer archive for an OpenROAD bug, plus
paste-ready text for a GitHub issue comment.

The developer who triages this issue has dozens of bugs in their queue.
They don't want to clone your repo, install bazel, or read your analysis.
They want: untar, run, see the crash, fire up a debugger. Every second
you save them is a second closer to a fix.

ARGUMENTS: $ARGUMENTS

## What this skill produces

1. A `.tar.gz` archive (from `make <stage>_issue`) that reproduces the bug
2. Paste-ready text for the issue:

```
Untar and run (openroad <bare 40-char git hash> must be on PATH):

tar xf <stage>_<tag>.tar.gz
cd <stage>_<tag>
echo exit | ./run-me-*.sh

Reproduces in ~Ns. You'll see:

[ERROR XXX-NNNN] <exact error text>

Generated by (~Ns total, synth Ns, Tile route Ns):

git clone https://github.com/oharboe/openroad-demo
cd openroad-demo
git checkout <sha>
bazelisk run //<project>:<module>_<stage>_deps
tmp/<project>/<module>_<stage>_deps/make ISSUE_TAG=<tag> <stage>_issue
```

The human attaches the tar.gz and pastes the text. That's the whole comment.

## Important constraints

- **Never use docker.** All builds use `bazelisk` with the bazel-orfs rules.
- **Never use `/tmp/`.** Use repo-local `tmp/` (gitignored). System `/tmp/`
is shared, fills up, and commands outside the repo root trigger permission
prompts.
- **OpenROAD version**: `openroad -version` prints "bazel-nostamp" when built
with bazel. Use the git hash instead: `bin/git-read upstream/OpenROAD-flow-scripts/tools/OpenROAD rev-parse HEAD`.
Include the bare 40-char hash in the report — GitHub auto-links it to the
commit in the OpenROAD repo.
- **Run long commands in the background.** Floorplan can take minutes.
Use `run_in_background` for any command that may exceed ~30 seconds.

## Workflow

### 1. Identify the target

From arguments or conversation context, determine:
- `<project>`: bazel package (e.g. `gemmini_8x8_abutted`)
- `<module>`: top-level module name (e.g. `MeshWithDelays`)
- `<stage>`: the failing stage (e.g. `floorplan`, `place`, `cts`, `grt`, `route`)
- `<tag>`: short issue tag for the archive name (e.g. `mpl0005`)
- `<commit>`: (optional) specific commit where the bug manifests without workarounds

### 2. Set up the build environment

If a specific commit is needed (because HEAD has a workaround):

```bash
git worktree add upstream/repro-<tag> <commit>
echo "build --disk_cache=$(realpath .bazel-disk-cache)" > upstream/repro-<tag>/user.bazelrc
cd upstream/repro-<tag>
```

The `user.bazelrc` is critical — without the shared disk cache, OpenROAD
rebuilds from scratch (~30+ min). With it, cached artifacts are reused
and only the design-specific targets build.

Otherwise work from the repo root.

### 3. Build dependencies and create make environment

```bash
bazelisk run --profile=profile.json //<project>:<module>_<stage>_deps
```

This builds synth, macros, and all upstream stages, then creates a make
wrapper at `tmp/<project>/<module>_<stage>_deps/make`.

The `--profile=profile.json` captures per-target build times. Use it to
produce a one-line timing summary for the report. Don't dump raw profile
data — just total time and the 2-3 targets that account for ~80% of it.
Example: "Takes ~620s to build (synth 23s, Tile route 500s)."

### 4. Create the issue archive

If the bug is in a specific substep (e.g. macro placement, not the whole
`floorplan` stage), you must run the preceding substeps first. Within a
stage, substeps share a mutable ODB — each reads the output of the previous.

**Important**: the substep name and the script name are different. The
`_issue` target uses the **script name**, not the substep name. Check the
ORFS Makefile (`upstream/OpenROAD-flow-scripts/flow/Makefile`) to find
the mapping — look for `do-step` calls:

```
$(eval $(call do-step,2_2_floorplan_macro,...,macro_place))
^^ substep name ^^ script name
```

The issue target is `<script_name>_issue`. Don't guess — check the Makefile.

Key mappings (from ORFS Makefile `do-step` calls):

| Substep | Script | Issue target |
|---------|--------|-------------|
| `2_1_floorplan` | `floorplan` | `floorplan_issue` |
| `2_2_floorplan_macro` | `macro_place` | `macro_place_issue` |
| `2_3_floorplan_tapcell` | `tapcell` | `tapcell_issue` |
| `3_3_place_gp` | `global_place` | `global_place_issue` |
| `5_1_grt` | `global_route` | `global_route_issue` |

Example: to archive a macro placement failure (substep 2_2):

```bash
# First run substep 2_1 to produce the ODB that 2_2 reads
tmp/<project>/<module>_<stage>_deps/make do-2_1_floorplan
# Then create the issue archive using the SCRIPT name (not substep name)
tmp/<project>/<module>_<stage>_deps/make ISSUE_TAG=<tag> macro_place_issue
```

For a full-stage issue (bug is in the first substep or you want the whole stage):

```bash
tmp/<project>/<module>_<stage>_deps/make ISSUE_TAG=<tag> <stage>_issue
```

Produces the archive as `<script_name>_<tag>.tar.gz`.

### 5. Check size and reproduction time

- GitHub attachment limit: **25 MB**
- Target reproduction time: **under a few minutes**

Check the archive size:

```bash
ls -lh tmp/<project>/<module>_<stage>_deps/<stage>_<tag>.tar.gz
```

**If both OK** (< 25 MB and reproduces quickly): skip whittling, proceed to step 6.

**If archive too large or reproduction too slow**: whittle the .odb to
reduce size and runtime. Use `whittle.py` from the OpenROAD tree (see
`openroad-issue.md` step 4 for detailed usage). Then re-run
`make <stage>_issue` to produce a smaller archive.

We are optimizing the developer's time. A 2 MB archive that reproduces
in 10 seconds is ideal. A 500 MB archive that takes 45 minutes is useless —
the developer will never run it.

### 6. Build openroad at origin/master for verification

The archive must be verified with an openroad that does NOT have the fix.
Build from origin/master in the upstream OpenROAD tree:

```bash
cd upstream/OpenROAD-flow-scripts/tools/OpenROAD
git fetch origin && git checkout origin/master
bazelisk build //:openroad
```

Binary at `bazel-bin/openroad`. Record the hash for the report:

```bash
bin/git-read upstream/OpenROAD-flow-scripts/tools/OpenROAD rev-parse HEAD
```

Put it on PATH (or use the full path in the verify step):

```bash
ln -sf $(realpath upstream/OpenROAD-flow-scripts/tools/OpenROAD/bazel-bin/openroad) ~/.local/bin/openroad
```

### 7. Verify the archive reproduces the bug

```bash
mkdir -p tmp/verify-<tag>
cp tmp/<project>/<module>_<stage>_deps/<stage>_<tag>.tar.gz tmp/verify-<tag>/
cd tmp/verify-<tag>
tar xf <stage>_<tag>.tar.gz
cd <stage>_<tag>
time echo exit | ./run-me-*.sh 2>&1 | tail -50
```

Run this in the background — it may take minutes.

Note: the `run-me-*.sh` scripts generated by `make <stage>_issue` do NOT
include `-exit`, so openroad drops into the Tcl shell after running the
script. Pipe `echo exit` to avoid hanging. When writing the report
instructions, tell the developer to use `echo exit |` as well.

Confirm the exact error appears. Capture the error line(s) and the
wall-clock time from `time`.

Include the reproduction time in the report text so the developer knows
what to expect (e.g. "Reproduces in ~8 seconds on a laptop").

### 8. Generate the report text

Record:
- The OpenROAD git hash (bare 40-char): `bin/git-read upstream/OpenROAD-flow-scripts/tools/OpenROAD rev-parse HEAD`
- The openroad-demo commit: `git rev-parse HEAD`
- The exact error output from step 6
- The archive filename

Write a `.md` file with the paste-ready text (see template above).
No headers, no bold, no analysis. Just: untar, run, see crash, generated by.
Use bare 40-char hashes — GitHub auto-links them to commits.

Save to `docs/issues/<tag>.md`.

### 9. Move the archive alongside the report

Copy the archive out of the worktree/tmp before cleaning up:

```bash
cp tmp/<project>/<module>_<stage>_deps/_main/<project>/<script>_<tag>.tar.gz docs/issues/
```

Now the archive and the `.md` are side by side in `docs/issues/`.

### 10. Clean up

If a worktree was created:

```bash
cd /home/oyvind/openroad-demo
git worktree remove --force upstream/repro-<tag>
```

Report the archive path and the generated text to the user. The human
attaches the tar.gz to the issue and pastes the text.

## Formatting rules

Same as `openroad-issue.md`:
- No markdown headers in the issue text
- No bold, no italics
- Indented code blocks (4 spaces) for commands
- No hard line wrapping — let the browser wrap
- Write like you're leaving a note for a colleague
- Bare 40-char commit hashes (no backticks) — GitHub auto-links them
18 changes: 18 additions & 0 deletions docs/issues/mpl0005.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Untar and run (openroad b52897fb49d30af1a6cdfdc681809ff93585c0bc must be on PATH):

tar xf macro_place_mpl0005.tar.gz
cd macro_place_mpl0005
echo exit | ./run-me-MeshWithDelays-asap7-base.sh

Reproduces in ~33s. You'll see:

[ERROR MPL-0005] Couldn't align pin mesh/mesh_0_2/io_in_d_0[2] from the RightWayOnGridOnly layer M5 with the track-grid.

Generated by (~343s total, Tile route 300s, synth 23s):

git clone https://github.com/oharboe/openroad-demo
cd openroad-demo
git checkout 88406ec9b7b925d672335eae345e4e5a81123e64
bazelisk run //gemmini_8x8_abutted:MeshWithDelays_floorplan_deps
tmp/gemmini_8x8_abutted/MeshWithDelays_floorplan_deps/make do-2_1_floorplan
tmp/gemmini_8x8_abutted/MeshWithDelays_floorplan_deps/make ISSUE_TAG=mpl0005 macro_place_issue
Loading