fwm 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fwm-0.1.1/LICENSE +33 -0
- fwm-0.1.1/PKG-INFO +353 -0
- fwm-0.1.1/README.md +325 -0
- fwm-0.1.1/fwm/__init__.py +0 -0
- fwm-0.1.1/fwm/__main__.py +3 -0
- fwm-0.1.1/fwm/cli/__init__.py +0 -0
- fwm-0.1.1/fwm/cli/completion.py +191 -0
- fwm-0.1.1/fwm/cli/fwm.py +174 -0
- fwm-0.1.1/fwm/cli/output.py +72 -0
- fwm-0.1.1/fwm/cli/subcmds/__init__.py +0 -0
- fwm-0.1.1/fwm/cli/subcmds/bootstrap.py +166 -0
- fwm-0.1.1/fwm/cli/subcmds/completion.py +32 -0
- fwm-0.1.1/fwm/cli/subcmds/compose.py +280 -0
- fwm-0.1.1/fwm/cli/subcmds/list.py +96 -0
- fwm-0.1.1/fwm/cli/subcmds/mkgen.py +141 -0
- fwm-0.1.1/fwm/cli/subcmds/repo.py +263 -0
- fwm-0.1.1/fwm/cli/subcmds/show.py +56 -0
- fwm-0.1.1/fwm/cli/subcmds/spawn.py +39 -0
- fwm-0.1.1/fwm/data_loader/__init__.py +0 -0
- fwm-0.1.1/fwm/data_loader/checkpoint.py +192 -0
- fwm-0.1.1/fwm/data_loader/ckpt_desc.py +69 -0
- fwm-0.1.1/fwm/data_loader/entry_point.py +52 -0
- fwm-0.1.1/fwm/data_loader/file_catalog.py +76 -0
- fwm-0.1.1/fwm/data_loader/final_state.py +114 -0
- fwm-0.1.1/fwm/data_loader/provenance.py +125 -0
- fwm-0.1.1/fwm/data_loader/recording.py +266 -0
- fwm-0.1.1/fwm/data_loader/sim_version.py +67 -0
- fwm-0.1.1/fwm/data_loader/simpoint_info.py +43 -0
- fwm-0.1.1/fwm/database/__init__.py +0 -0
- fwm-0.1.1/fwm/database/catalog_store.py +69 -0
- fwm-0.1.1/fwm/database/custom_field.py +24 -0
- fwm-0.1.1/fwm/database/db.py +80 -0
- fwm-0.1.1/fwm/database/schema.py +335 -0
- fwm-0.1.1/fwm/mkgen/__init__.py +0 -0
- fwm-0.1.1/fwm/mkgen/makefile.py +304 -0
- fwm-0.1.1/fwm/mkgen/run_json.py +45 -0
- fwm-0.1.1/fwm/mkgen/templates/create-checkpoints.mk +15 -0
- fwm-0.1.1/fwm/mkgen/templates/from-checkpoint.mk +16 -0
- fwm-0.1.1/fwm/mkgen/templates/from-fesvr-trace.mk +13 -0
- fwm-0.1.1/fwm/mkgen/templates/from-simpoint.mk +18 -0
- fwm-0.1.1/fwm/mkgen/templates/from-sysroot.mk +28 -0
- fwm-0.1.1/fwm/mkgen/templates/header.mk +27 -0
- fwm-0.1.1/fwm/mkgen/templates/record.mk +28 -0
- fwm-0.1.1/fwm/py.typed +0 -0
- fwm-0.1.1/fwm/repo/__init__.py +0 -0
- fwm-0.1.1/fwm/repo/checkpoint.py +220 -0
- fwm-0.1.1/fwm/repo/entry.py +139 -0
- fwm-0.1.1/fwm/repo/errors.py +24 -0
- fwm-0.1.1/fwm/repo/gc.py +134 -0
- fwm-0.1.1/fwm/repo/listing.py +133 -0
- fwm-0.1.1/fwm/repo/lookup.py +102 -0
- fwm-0.1.1/fwm/repo/query.py +136 -0
- fwm-0.1.1/fwm/repo/remove.py +81 -0
- fwm-0.1.1/fwm/repo/repo.py +218 -0
- fwm-0.1.1/fwm/repo/spawn.py +118 -0
- fwm-0.1.1/fwm/repo/subrepo.py +63 -0
- fwm-0.1.1/fwm/repo/sysroot.py +80 -0
- fwm-0.1.1/fwm/repo/trace.py +218 -0
- fwm-0.1.1/fwm/repo/transfer.py +567 -0
- fwm-0.1.1/fwm/repo/validation.py +73 -0
- fwm-0.1.1/fwm/utils/__init__.py +0 -0
- fwm-0.1.1/fwm/utils/digest.py +44 -0
- fwm-0.1.1/fwm/utils/file_catalog.py +213 -0
- fwm-0.1.1/fwm/utils/fs.py +149 -0
- fwm-0.1.1/fwm/utils/log.py +77 -0
- fwm-0.1.1/fwm/utils/target_path.py +38 -0
- fwm-0.1.1/fwm/version.py +46 -0
- fwm-0.1.1/pyproject.toml +81 -0
- fwm-0.1.1/pyproject.toml.orig +68 -0
fwm-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**********************************************************************************
|
|
2
|
+
Copyright (c) 2026, North Carolina State University (NCSU).
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
8
|
+
are permitted provided that the following conditions are met:
|
|
9
|
+
|
|
10
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
11
|
+
list of conditions and the following disclaimer.
|
|
12
|
+
|
|
13
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this
|
|
14
|
+
list of conditions and the following disclaimer in the documentation and/or other
|
|
15
|
+
materials provided with the distribution.
|
|
16
|
+
|
|
17
|
+
3. The names “North Carolina State University”, “NCSU” and any trade‐name, personal
|
|
18
|
+
name, trademark, trade device, service mark, symbol, image, icon, or any abbreviation,
|
|
19
|
+
contraction or simulation thereof owned by North Carolina State University must not
|
|
20
|
+
be used to endorse or promote products derived from this software without prior
|
|
21
|
+
written permission.
|
|
22
|
+
|
|
23
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
24
|
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
25
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
26
|
+
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
27
|
+
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
28
|
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
29
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
30
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
31
|
+
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
32
|
+
DAMAGE.
|
|
33
|
+
**************************************************************************************/
|
fwm-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fwm
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: RISC-V FESVR Workload Manager: traces, checkpoints and SimPoint runs for a record/replay spike.
|
|
5
|
+
Keywords: riscv,spike,fesvr,simulation,checkpoint,simpoint,anycore
|
|
6
|
+
Author: Jiayang Li
|
|
7
|
+
Author-email: Jiayang Li <jli95@ncsu.edu>
|
|
8
|
+
License-Expression: LicenseRef-NCSU
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
15
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: System :: Emulators
|
|
20
|
+
Requires-Dist: colorama>=0.4.6
|
|
21
|
+
Requires-Dist: click>=8.4.0
|
|
22
|
+
Requires-Dist: peewee>=4.5.0
|
|
23
|
+
Requires-Dist: pydantic>=2.9.0
|
|
24
|
+
Requires-Python: >=3.12
|
|
25
|
+
Project-URL: Homepage, https://github.com/s117/fesvr-workload-manager
|
|
26
|
+
Project-URL: Repository, https://github.com/s117/fesvr-workload-manager.git
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# fwm: the RISC-V FESVR Workload Manager
|
|
30
|
+
|
|
31
|
+
fwm manages RISC-V simulation workloads for the custom spike in [riscv-isa-sim](https://github.com/s117/riscv-isa-sim/tree/anycore-gcc_16.1.0-llvm_22.1.8), and replaces riscv-simenv.
|
|
32
|
+
|
|
33
|
+
That spike's front-end server (FESVR) can **record** the device traffic of a run: every proxied system call, with the memory it read and wrote. It can then **replay** that recording without the original environment, and create and load **checkpoints** on top of a replay (see [docs/fesvr-checkpoint-and-traffic-replay.md](https://github.com/s117/riscv-isa-sim/blob/anycore-gcc_16.1.0-llvm_22.1.8/docs/fesvr-checkpoint-and-traffic-replay.md) in riscv-isa-sim). fwm keeps the pieces of that workflow in a repository and generates the Makefiles that run them.
|
|
34
|
+
|
|
35
|
+
**The repository's creator** builds its content with `fwm repo`: `fwm repo bootstrap` generates the runs that record traces and create checkpoints, and `fwm repo compose` imports them:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
sysroot ──(entry point)──> record-fesvr-trace ──> trace ──> create-checkpoints ──> checkpoints
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Its users,** who may have read access only, begin simulations with `fwm mkgen`: from a sysroot, from a FESVR trace, from a checkpoint, or for one SimPoint interval.
|
|
42
|
+
|
|
43
|
+
## How it differs from riscv-simenv
|
|
44
|
+
|
|
45
|
+
- **The sysroot is needed once.** Only the recording run (and `mkgen from-sysroot`, which runs the program for real) executes system calls on the host. A replay, or a run from a checkpoint, needs only the trace (which keeps a copy of the boot ELF as `boot.elf`), the checkpoint and the same `-m`/`-p`. There is no simenv to spawn and verify before every run.
|
|
46
|
+
- **A replay prints nothing and writes no file.** Console output and output files exist only in the recording run. A replay checks that the program computes the same data, byte for byte, and stops at the first difference.
|
|
47
|
+
- **Restore cost doesn't grow with the syscall history.** Loading a checkpoint seeks in the recording instead of re-executing it.
|
|
48
|
+
- **Traces and checkpoints are portable.** They replay and load on any little-endian host (x86-64 or ARM64 Linux, macOS). Recording must be done on Linux.
|
|
49
|
+
|
|
50
|
+
## Concepts
|
|
51
|
+
|
|
52
|
+
| Term | Meaning |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| **sysroot** | A directory tree the program sees as `/`, imported read-only into the repository with a catalog (every file's permissions and SHA-256). |
|
|
55
|
+
| **workload** | A name grouping the entry points that run the same program. |
|
|
56
|
+
| **entry point** | How to launch a workload in a sysroot: the command, working directory, boot ELF (usually pk), stdin file, memory size and processor count, with optional free-form metadata. A workload can have entry points on several sysroots, and a sysroot can serve several workloads. |
|
|
57
|
+
| **trace** | A recording (`+dev-traffic-record`) of a run of an entry point, identified by a UUID. It is *complete* if the program exited, or *truncated* if the run was stopped first (e.g. by spike's `-e<n>` instruction limit). |
|
|
58
|
+
| **checkpoint** | A snapshot taken while replaying a trace. It loads only with that trace. A SimPoint checkpoint carries its SimPoint index, interval, weight and the analysis's maxK. |
|
|
59
|
+
| **HART** | A hardware thread: a simulated processor. fwm's workloads run on one. |
|
|
60
|
+
| **BBV, SimPoint** | spike's `-s<interval>` writes the program's basic block vectors (BBVs), one per interval of instructions. SimPoint picks a few intervals that represent the whole run, each with a weight: simulating only those (from a checkpoint at the start of each) estimates the whole run. |
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
fwm needs Python 3.12 or later. Install the `fwm` command from PyPI:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
uv tool install fwm # or: pipx install fwm, or pip install fwm in a virtual environment
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Or from a checkout of its source:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
git clone https://github.com/s117/fesvr-workload-manager.git fwm && cd fwm
|
|
74
|
+
uv sync # creates .venv with fwm
|
|
75
|
+
uv run fwm --help
|
|
76
|
+
# or install the command: uv tool install .
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
To run simulations, fwm also needs the spike built from [riscv-isa-sim](https://github.com/s117/riscv-isa-sim/tree/anycore-gcc_16.1.0-llvm_22.1.8) (see [Generated Makefiles](#generated-makefiles) for the versions it requires), or a simulator compatible with it.
|
|
80
|
+
|
|
81
|
+
`fwm --version` says which fwm you have: its version, and the git commit it was installed from when installed from git, or the source tree and its commit for an editable install (`uv sync` here).
|
|
82
|
+
|
|
83
|
+
## Shell completion
|
|
84
|
+
|
|
85
|
+
fwm completes its commands and options on Tab, like riscv-simenv. It also completes the names in the repository: sysroots, workloads, entry points, traces and checkpoints. The names come from the repository given by `--repo-path` or `FWM_REPO_PATH`; without one, nothing is offered. Enable it in your shell's startup file:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
eval "$(fwm completion zsh)" # ~/.zshrc
|
|
89
|
+
eval "$(fwm completion bash)" # ~/.bashrc
|
|
90
|
+
fwm completion fish | source # ~/.config/fish/config.fish
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- **`fwm` must be on `PATH`**, e.g. with `uv tool install .`, or with this repository's `.venv/bin` on `PATH`. `uv run fwm` alone is not enough: the shell calls `fwm` to complete.
|
|
94
|
+
- **Faster shell start-up:** `eval` runs fwm each time a shell starts. To avoid that, write the script once to a file and source it, e.g. for zsh `fwm completion zsh > ~/.zfunc/_fwm` with `~/.zfunc` in `fpath` before `compinit`. Write it again after updating fwm.
|
|
95
|
+
- **Checkpoints** are completed by name when the name is unique, and otherwise as `<trace UUID>:<name>`. Typing a trace prefix and `:` narrows the list to that trace's checkpoints.
|
|
96
|
+
- bash splits words at `:`, so it can't complete that form. zsh and fish can.
|
|
97
|
+
- zsh and fish also show a short description with each name.
|
|
98
|
+
|
|
99
|
+
## Quick start
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
export FWM_REPO_PATH=~/fwm-repo # or pass --repo-path to every command
|
|
103
|
+
export FWM_SIM_CMD=/path/to/spike # default: spike on PATH
|
|
104
|
+
|
|
105
|
+
fwm repo init $FWM_REPO_PATH
|
|
106
|
+
fwm repo compose add sysroot ./sysroots/gapbs-road road.sg
|
|
107
|
+
fwm repo compose add entry road.sg bfs bfs-road-n64 bfs-road-n64.json
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`bfs-road-n64.json` holds the launch fields of the entry point. In paths, `/` is the sysroot's root and `.` the working directory:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{ "command": "bfs -f road.sg -n64", "working_directory": "/app",
|
|
114
|
+
"envs": null, "stdin_file": null, "boot_elf": "/boot/pk", "mem_mb": 2048, "nprocs": 1, "copy_spawn": false,
|
|
115
|
+
"metadata": { "suite": "GAPBS", "description": "Breadth-First Search on 'road'", "language": ["C++"] } }
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
- `envs` must be `null` or `{}`: FESVR passes no environment to the program.
|
|
119
|
+
- `nprocs` must be 1: checkpoints can be created for a single HART only.
|
|
120
|
+
- `boot_elf` and `stdin_file` must be regular files of the sysroot, not symlinks.
|
|
121
|
+
- `copy_spawn` (optional, default `true`) is how a run of the program gets its sysroot (see `fwm spawn`): a copy, or, when `false`, links to the repository's read-only files. Linking takes no time or space, even for gigabytes of input, but the program can't open its files for writing, `stat` reports them read-only, and `lstat` and `readlink` see links into the repository. Use `false` only for a program that just reads the files it finds.
|
|
122
|
+
- `metadata` is optional and free-form: any JSON object, such as a riscv-simenv suite's `index.yaml` metadata. fwm shows it and copies it into each run's `run.json`. Change it later with `fwm repo compose set-metadata`.
|
|
123
|
+
|
|
124
|
+
Record a run, and import the recording as a trace. The recording says how it was made (`recording_provenance.json`: when, on what machine, the command line, and the spike's and FESVR's builds), which the trace keeps:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
fwm repo bootstrap mkgen record-fesvr-trace bfs-road-n64 -o run1 && make -C run1 run SIM_FLAGS_EXTRA=-s100000000 # with BBVs
|
|
128
|
+
fwm repo compose add trace bfs-road-n64 run1/trace --final-state run1/final-state.json
|
|
129
|
+
# prints the trace UUID
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Without `--final-state`, the trace has no instruction counts, and its checkpoints can't be validated. While an entry point has one trace, commands that take a trace also take the entry point's name, as below.
|
|
133
|
+
|
|
134
|
+
Checkpoint files don't say how they were made, so their import takes the `spike --version` output for provenance:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
"${FWM_SIM_CMD:-spike}" --version > sim-version.txt
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Create checkpoints from a description file, and import them in one transaction. The description names each checkpoint and the instruction count where it is taken, e.g. `ckpts.txt` for two SimPoints:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
bfs-road-n64.3.0.25: 300000005
|
|
144
|
+
bfs-road-n64.7.0.75: 700000012
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
fwm repo bootstrap mkgen create-checkpoints bfs-road-n64 ckpts.txt -o run2 && make -C run2 run
|
|
149
|
+
fwm repo compose add checkpoint bfs-road-n64 run2/ckpt.desc run2/checkpoints --simpoint-info simpoints.json \
|
|
150
|
+
--sim-version sim-version.txt
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- **A SimPoint's count is the sum of the sizes of the BBV intervals before it, not index × interval:** spike's intervals are a little longer than `-s` says. fwm-bootstrap writes the description and `simpoints.json` from SimPoint's output; see [docs/fwm-bootstrap-interface.md](https://github.com/s117/fesvr-workload-manager/blob/main/docs/fwm-bootstrap-interface.md), step 5.
|
|
154
|
+
- **Names are just names.** `<entry>.<SimPoint index>.<weight>`, as here, is a readable convention; fwm reads nothing from a name.
|
|
155
|
+
- **The run directory keeps a copy of the description,** `run2/ckpt.desc`, which the import reads.
|
|
156
|
+
- **Every checkpoint of the description must be in `run2/checkpoints`,** which catches one spike didn't create: it creates none at or after the program's exit, without a word. Other files there are ignored.
|
|
157
|
+
- **`--simpoint-info`** gives the SimPoint analysis, naming exactly the checkpoints of the description:
|
|
158
|
+
```json
|
|
159
|
+
{"interval": 100000000, "maxK": 10,
|
|
160
|
+
"checkpoints": {"bfs-road-n64.3.0.25": {"index": 3, "weight": 0.2531}, "bfs-road-n64.7.0.75": {"index": 7, "weight": 0.7469}}}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Validate a checkpoint by running it to the end:
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
fwm mkgen from-checkpoint bfs-road-n64.3.0.25 -o run3
|
|
167
|
+
make -C run3 run; fwm repo compose set-checkpoint-validation bfs-road-n64.3.0.25 run3 # passed or failed, recorded
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Running workloads
|
|
171
|
+
|
|
172
|
+
`fwm mkgen` generates a run directory that begins a simulation; run it with `make -C <dir> run`:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
fwm mkgen from-sysroot bfs-road-n64 -o a # the real program in a fresh copy of its sysroot (Linux only)
|
|
176
|
+
fwm mkgen from-fesvr-trace bfs-road-n64 -o b # replay its trace from the start: any host, no output
|
|
177
|
+
fwm mkgen from-checkpoint bfs-road-n64.3.0.25 -o c # from a checkpoint to the end of the program
|
|
178
|
+
fwm mkgen from-simpoint bfs-road-n64.3.0.25 -o d # one SimPoint interval from a SimPoint checkpoint
|
|
179
|
+
make -C d run SIM=/path/to/721sim # make reports "Error 1": spike exits 1 when -e stops it
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- **`from-sysroot`** does the program's real system calls, so it prints its console (also saved to `console.stdout` and `console.stderr`) and writes its files in `sysroot/`. Their answers come from the host, so its instruction count can differ from the trace's. For example, the program's stdout going to `/dev/null` rather than a file changed it by about 200 out of 1.5 million.
|
|
183
|
+
- **`from-fesvr-trace`, `from-checkpoint` and `from-simpoint`** replay the trace: the program prints nothing and writes no file, and every run repeats the recorded one exactly, instruction counts included.
|
|
184
|
+
- **`from-simpoint`** stops after the checkpoint's SimPoint interval (`-e$(INTERVAL)`, overridable with `INTERVAL=<n>`); weigh its results by the checkpoint's `simpoint_weight`.
|
|
185
|
+
|
|
186
|
+
### An AI skill for fwm's users
|
|
187
|
+
|
|
188
|
+
[skills/use-fwm/SKILL.md](https://github.com/s117/fesvr-workload-manager/blob/main/skills/use-fwm/SKILL.md) teaches an AI coding agent (Claude Code) how to use a repository: search it with `fwm list`, read metadata with `fwm show` and `run.json`, run simulations, judge them by `final-state.json`, and sweep SimPoint checkpoints. Install it once, from a checkout of fwm's source (see [Install](#install)):
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
ln -s "$PWD/skills/use-fwm" ~/.claude/skills/use-fwm
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The link follows the checkout, so the skill stays in step with the fwm you pull.
|
|
195
|
+
|
|
196
|
+
## Commands
|
|
197
|
+
|
|
198
|
+
**Daily**, for every user of a repository (they work without write permission):
|
|
199
|
+
|
|
200
|
+
| Command | Purpose |
|
|
201
|
+
| --- | --- |
|
|
202
|
+
| `fwm list [<kind>] [--workload\|--sysroot\|--entry\|--trace\|--checkpoint GLOB]... [--simpoint] [--json]` | List the names of a kind: workloads, sysroots, entries (the default), traces or checkpoints, filtered by the entities they are related to (see [Listing](#listing)). |
|
|
203
|
+
| `fwm show <kind> <name> [--json]` | Show the details of one workload, sysroot, entry, trace or checkpoint. |
|
|
204
|
+
| `fwm mkgen {from-sysroot <entry> \| from-fesvr-trace <trace> \| from-checkpoint <ckpt> \| from-simpoint <ckpt>} [-o dir]` | Generate a run directory that begins a simulation. |
|
|
205
|
+
| `fwm spawn [--force] [--mode auto\|copy\|link] <entry> <dest>` | Make a working copy of an entry point's sysroot: copied, or linked to the repository's files; `auto`, the default, follows its `copy_spawn` (the `from-sysroot` and record Makefiles do it). |
|
|
206
|
+
|
|
207
|
+
**Setup:** `fwm completion {bash|zsh|fish}` prints the shell completion script (see [Shell completion](#shell-completion)). It isn't offered on TAB.
|
|
208
|
+
|
|
209
|
+
**`fwm repo`**, for the repository's creator. The repository as a whole:
|
|
210
|
+
|
|
211
|
+
| Command | Purpose |
|
|
212
|
+
| --- | --- |
|
|
213
|
+
| `fwm repo init <dir>` | Create a repository. |
|
|
214
|
+
| `fwm repo verify [<kind> <name>]` | Check the repository content against its catalogs (all, or one sysroot, trace or checkpoint), and for leftovers. |
|
|
215
|
+
| `fwm repo gc [--dry-run]` | Remove the leftovers of interrupted commands. |
|
|
216
|
+
| `fwm repo pull <source> {<entry>... \| --all} [--no-traces] [--no-checkpoints]` | Copy entry points of another repository into this one, with their sysroots, traces and checkpoints. |
|
|
217
|
+
| `fwm repo push <dest> {<entry>... \| --all} [--no-traces] [--no-checkpoints]` | Copy entry points of this repository into another one. |
|
|
218
|
+
| `fwm repo subrepo <new-repo> <entry>... [--no-traces] [--no-checkpoints]` | Create a repository with some entry points of this one: `repo init`, then `repo push`. |
|
|
219
|
+
|
|
220
|
+
**`fwm repo compose`** changes the repository's content; each command needs write access:
|
|
221
|
+
|
|
222
|
+
| Command | Purpose |
|
|
223
|
+
| --- | --- |
|
|
224
|
+
| `fwm repo compose add sysroot <dir> <name>` | Import a sysroot. |
|
|
225
|
+
| `fwm repo compose add entry <sysroot> <workload> <name> <json_file>` | Add an entry point. |
|
|
226
|
+
| `fwm repo compose add trace <entry> <recording-dir> [--final-state f.json]` | Import a recording, with its provenance; prints its UUID. |
|
|
227
|
+
| `fwm repo compose add checkpoint <trace> <desc> <checkpoint-dir> [--simpoint-info j] [--sim-version f]` | Import the checkpoints of a description in one transaction; prints `<uuid>:<name>` for each. |
|
|
228
|
+
| `fwm repo compose remove <kind> <name> [--recursive]` | Remove a sysroot, entry, trace or checkpoint, with what depends on it when `--recursive`. |
|
|
229
|
+
| `fwm repo compose set-metadata <entry> <json_file>` | Replace an entry point's metadata (`null` removes it), keeping its traces. |
|
|
230
|
+
| `fwm repo compose set-checkpoint-validation <checkpoint> <run-dir>` | Judge a `mkgen from-checkpoint` run to the end, and set the checkpoint's validation: passed or failed. |
|
|
231
|
+
|
|
232
|
+
**`fwm repo bootstrap`** makes the repository's traces and checkpoints, in the pipeline's order; its commands only read the repository:
|
|
233
|
+
|
|
234
|
+
| Command | Purpose |
|
|
235
|
+
| --- | --- |
|
|
236
|
+
| `fwm repo bootstrap mkgen record-fesvr-trace <entry> [-o dir]` | Generate a run directory that records a run of an entry point: its FESVR trace. |
|
|
237
|
+
| `fwm repo bootstrap check-fesvr-trace <recording-dir> [--final-state f.json] [--json]` | Check a recording as `repo compose add trace` would, without a repository: complete, well formed, agreeing with its final state. |
|
|
238
|
+
| `fwm repo bootstrap mkgen create-checkpoints <trace> <desc> [-o dir]` | Generate a run directory that creates the checkpoints of a description. |
|
|
239
|
+
|
|
240
|
+
## Listing
|
|
241
|
+
|
|
242
|
+
`fwm list <kind>` prints the names of the workloads, sysroots, entries (the default), traces or checkpoints, one per line, or with `--json` as a JSON array. `fwm show <kind> <name>` gives the details of each. Traces are listed by UUID, and checkpoints as `fwm show checkpoint` takes them (below).
|
|
243
|
+
|
|
244
|
+
Its filters `--workload`, `--sysroot`, `--entry`, `--trace` and `--checkpoint` keep what is related to an entity they match, directly or through others:
|
|
245
|
+
|
|
246
|
+
| Kind | Is related to |
|
|
247
|
+
| --- | --- |
|
|
248
|
+
| workload | its entry points, their sysroots, traces and checkpoints |
|
|
249
|
+
| sysroot | its entry points, their workloads, traces and checkpoints |
|
|
250
|
+
| entry point | its workload, sysroot, traces and their checkpoints |
|
|
251
|
+
| trace | its entry point (and that one's workload and sysroot), and its checkpoints |
|
|
252
|
+
| checkpoint | its trace, and that trace's entry point, workload and sysroot |
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
fwm list checkpoints --workload bfs # the checkpoints of bfs's entry points
|
|
256
|
+
fwm list sysroots --checkpoint 'bfs-road*' # the sysroots where those checkpoints were made
|
|
257
|
+
fwm list entries --entry 'bfs-*' # a filter of the listed kind selects by name
|
|
258
|
+
fwm list traces --sysroot s1 --sysroot s2 # a filter given twice: either
|
|
259
|
+
fwm list entries --workload bfs --sysroot road.sg # different filters: both
|
|
260
|
+
fwm list checkpoints --checkpoint '8f25*:bfs*' # a checkpoint as <trace UUID glob>:<name glob>
|
|
261
|
+
fwm list checkpoints --entry bfs-road-n64 --simpoint # those `fwm mkgen from-simpoint` can simulate
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
- **Several filters:** each keeps its own set, and the result is their intersection. `fwm list workloads --sysroot s1 --entry c` lists the workloads related to `s1` and to `c`, even through different entry points.
|
|
265
|
+
- **Patterns** are shell-style globs (`*`, `?`, `[...]`, case-sensitive; quote them in the shell); a plain name matches exactly. `--trace` matches the UUID as `fwm show` prints it.
|
|
266
|
+
- **`--simpoint`** keeps what is related to a checkpoint with SimPoint information: exactly the checkpoints `fwm mkgen from-simpoint` accepts. Listing other kinds, it keeps those with at least one such checkpoint.
|
|
267
|
+
- **A pattern that matches nothing of its kind** prints a warning (likely a typo); the command still succeeds, with nothing listed.
|
|
268
|
+
- **A sysroot without entry points** is related to nothing else: it is listed without filters, or with a matching `--sysroot`.
|
|
269
|
+
|
|
270
|
+
How to name things:
|
|
271
|
+
- **A trace** is its UUID (a unique prefix is enough), or the name of an entry point that has one trace.
|
|
272
|
+
- **A checkpoint** is `<trace>:<name>`, or just its name when no other trace has a checkpoint of that name.
|
|
273
|
+
- **A checkpoint's name** is just a name: its SimPoint data comes only from `--simpoint-info`.
|
|
274
|
+
|
|
275
|
+
Every `repo compose add` takes `--exist-ok`: if the same item is already in the repository, it prints it and succeeds. An entry point that differs only in its description or metadata is the same; it keeps its own. Without it, adding what exists fails with status 5. A recording that already is a trace of the entry point counts as existing, so a rerun never creates a second trace.
|
|
276
|
+
|
|
277
|
+
Exit status: 0 success, 1 unexpected error, 2 usage error or unusable repository, 3 not found, 4 failed check, 5 already exists: an item of the repository, or a destination (`spawn` into an existing directory without `--force`, `repo init` or `subrepo` into a non-empty one).
|
|
278
|
+
|
|
279
|
+
## Merging and subsets
|
|
280
|
+
|
|
281
|
+
`repo pull`, `repo push` and `repo subrepo` copy entry points from one repository to another. Each entry point brings its workload and sysroot, and its traces with their checkpoints, unless `--no-traces` or `--no-checkpoints` leave them out:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
fwm repo subrepo ~/small bfs-road-n64 pr-road # a new repository with two entry points
|
|
285
|
+
fwm --repo-path ~/small repo pull /shared/repo cc-road # add a third one to it
|
|
286
|
+
fwm --repo-path /shared/repo repo push ~/merged --all # merge everything into another, existing repository
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
- **Rows are copied as they are:** names, trace UUIDs, provenance, metadata, SimPoint data and validation results.
|
|
290
|
+
- **What the receiving repository has is kept,** under the rules of `--exist-ok`:
|
|
291
|
+
- a sysroot of the same name and content;
|
|
292
|
+
- an entry point of the same name, sysroot, workload and launch fields, with its own metadata;
|
|
293
|
+
- a trace made of the same recording, with its own UUID, to which the copied checkpoints attach;
|
|
294
|
+
- a checkpoint of the same name and content, with its own validation result.
|
|
295
|
+
|
|
296
|
+
Copying again adds nothing, and its rows never change.
|
|
297
|
+
- **Conflicts:** the same name with something else is a conflict. Every entry point is checked before anything is copied, and then nothing is: the command fails with status 5. If another command changes the receiving repository during the copy, a conflict found then stops it, keeping the entry points already committed.
|
|
298
|
+
- **Interruptions:** each entry point is committed on its own, like an import. An interrupted copy can be run again to complete it. `subrepo` removes its new repository if the copy fails (an empty directory it was created in is left empty, as it was).
|
|
299
|
+
- **Read access is enough** to copy from a repository. Completion offers the entry points of the repository copied from: for `pull`, those of its `<source>`.
|
|
300
|
+
- **Output:** each item prints as `added|present <kind> <id>` (`subrepo` prints the new repository's path), and a summary goes to stderr.
|
|
301
|
+
|
|
302
|
+
## Generated Makefiles
|
|
303
|
+
|
|
304
|
+
Every Makefile has a single target, `run`. It first removes that run's previous outputs, so it can be run again. A run directory can be generated again for the same kind of run, but not for another kind, whose Makefile wouldn't remove the former outputs.
|
|
305
|
+
|
|
306
|
+
Next to it, `run.json` describes what the run uses: the sysroot, workload, entry point (with its metadata), trace and checkpoint, as `fwm show --json` shows them when the Makefile is generated. Its `kind` says which command generated it, e.g. `from-simpoint`, or `record` for `repo bootstrap mkgen record-fesvr-trace`. A create-checkpoints run also lists the checkpoints it requests. See [docs/fwm-bootstrap-interface.md](https://github.com/s117/fesvr-workload-manager/blob/main/docs/fwm-bootstrap-interface.md#runjson).
|
|
307
|
+
|
|
308
|
+
Override variables on the make command line:
|
|
309
|
+
|
|
310
|
+
| Variable | Use |
|
|
311
|
+
| --- | --- |
|
|
312
|
+
| `SIM` | The simulator (default: `FWM_SIM_CMD` when generated, else `spike`). |
|
|
313
|
+
| `SIM_FLAGS_EXTRA` | spike options such as `-e<n>` or `-s<interval>`. They come before the FESVR options. |
|
|
314
|
+
| `FESVR_FLAGS_EXTRA` | FESVR options such as `+verbose`. |
|
|
315
|
+
| `BOOT_ELF_FLAGS_EXTRA`, `APP_CMD_EXTRA` | (from-sysroot, record) Options of the boot ELF (pk), and extra program arguments. |
|
|
316
|
+
| `FWM` | (from-sysroot, record) How to run fwm for `spawn` (default: the Python that generated the Makefile, so fwm needn't be on `PATH`). |
|
|
317
|
+
| `INTERVAL` | (from-simpoint) The instructions to simulate (default: the checkpoint's SimPoint interval). |
|
|
318
|
+
|
|
319
|
+
spike's exit status:
|
|
320
|
+
- **Without `-e`:** the program's exit status, or 0 after creating the last checkpoint.
|
|
321
|
+
- **With `-e<n>`:** 1 when the run was stopped after `n` instructions, and 0 when the program ended first.
|
|
322
|
+
|
|
323
|
+
**Don't judge a run by make's exit status; let fwm judge it.** A program that legitimately exits non-zero makes `make` fail, while spike stopped by SIGTERM (e.g. a job's time limit) exits 0. `fwm repo compose add trace --final-state` judges a record run, `fwm repo compose add checkpoint` a checkpoint creation, and `fwm repo compose set-checkpoint-validation` a run from a checkpoint.
|
|
324
|
+
|
|
325
|
+
`final-state.json` says why the run finished, and each hart's instruction count there: `target_exit` (with `exit_code`), `checkpoints_created`, `instret_limit` (`-e`), `debug_quit`, `interrupted` (with `signal`), `error` (with the simulator's message, and no count) or `unfinished` (spike died). fwm needs a spike that writes `finish_reason` (riscv-isa-sim eb87256 / riscv-fesvr 6f2d3b8 or later): older ones wrote counts at the program's exit that depended on where the run started, and their dumps are refused. fwm also needs the recording's provenance (`recording_provenance.json`), written from riscv-isa-sim fd01c25 / riscv-fesvr 8472993 on, and refuses a recording without it. Those versions also include the fixes of riscv-isa-sim 872d191 / riscv-fesvr ecc3df3, needed in batch jobs: before them, a run that got SIGTERM twice (from a job's time limit, under make) could leave an empty or broken dump.
|
|
326
|
+
|
|
327
|
+
The Makefiles leave other simulator outputs, such as `bbv_proc_0.bb.gz` from `-s`, to the caller: use a fresh run directory, or remove them.
|
|
328
|
+
|
|
329
|
+
## Clusters and shared repositories
|
|
330
|
+
|
|
331
|
+
- **Commands that change the repository** (`repo init`, `gc`, `pull`, every `repo compose` command, and `push` / `subrepo` for the repository they write) should run on one host, e.g. a Snakemake controller. The database uses SQLite's rollback journal, which works on a shared filesystem, and they wait for each other.
|
|
332
|
+
- **Compute jobs** run the generated Makefiles. Only the `from-sysroot` and record runs open the database, read-only, when `fwm spawn` checks the sysroot out.
|
|
333
|
+
- **Read-only use:** `list`, `show`, `mkgen`, `spawn`, `repo verify`, every `repo bootstrap` command, `repo push` / `subrepo` (copying from it) and completion work in a repository you can't write to, e.g. one shared with your group.
|
|
334
|
+
- **Interrupted commands:** a command killed by its scheduler (SIGTERM) cleans up after itself. A harder kill can leave staging or files that no row refers to. `fwm repo verify` reports them and `fwm repo gc` removes them; it never leaves rows whose files are missing. A command committing at the moment `verify` runs can show as leftovers too: run it again.
|
|
335
|
+
|
|
336
|
+
## Development
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
uv run pytest # unit tests
|
|
340
|
+
uv run mypy fwm tests
|
|
341
|
+
uv run ruff check fwm tests
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
The end-to-end test needs a spike built from `riscv-isa-sim` and a small workload:
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
FWM_TEST_SPIKE=/path/to/spike FWM_TEST_SYSROOT=/path/to/sysroot FWM_TEST_ENTRY_POINT=/path/to/entry_point.json \
|
|
348
|
+
FWM_TEST_SPIKE_SRC=/path/to/riscv-isa-sim uv run pytest tests/integration
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
The bootstrap pipeline's interface to fwm is described in [docs/fwm-bootstrap-interface.md](https://github.com/s117/fesvr-workload-manager/blob/main/docs/fwm-bootstrap-interface.md).
|
|
352
|
+
|
|
353
|
+
Notes for coding agents (how fwm is built, the spike behaviour it relies on, decisions, conventions) are in [docs/agent-guide.md](https://github.com/s117/fesvr-workload-manager/blob/main/docs/agent-guide.md).
|