hector-cli 0.2.0__tar.gz → 0.3.0__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.
Files changed (34) hide show
  1. {hector_cli-0.2.0 → hector_cli-0.3.0}/PKG-INFO +229 -9
  2. {hector_cli-0.2.0 → hector_cli-0.3.0}/README.md +228 -8
  3. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/commands/base.py +6 -0
  4. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/core.py +24 -6
  5. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/docker.py +16 -3
  6. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/generator.py +40 -4
  7. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/modules.py +37 -10
  8. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/pipeline.py +50 -14
  9. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/validator.py +9 -1
  10. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector_cli.egg-info/PKG-INFO +229 -9
  11. {hector_cli-0.2.0 → hector_cli-0.3.0}/setup.py +13 -1
  12. {hector_cli-0.2.0 → hector_cli-0.3.0}/LICENSE +0 -0
  13. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/__init__.py +0 -0
  14. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/__main__.py +0 -0
  15. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/commands/__init__.py +0 -0
  16. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/commands/export.py +0 -0
  17. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/commands/init.py +0 -0
  18. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/commands/run.py +0 -0
  19. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/commands/test.py +0 -0
  20. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/commands/validate.py +0 -0
  21. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/connections.py +0 -0
  22. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/dependencies.py +0 -0
  23. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/hubs.py +0 -0
  24. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/mappings.py +0 -0
  25. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/peripherals.py +0 -0
  26. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/reporters.py +0 -0
  27. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/runners.py +0 -0
  28. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector/scaffold.py +0 -0
  29. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector_cli.egg-info/SOURCES.txt +0 -0
  30. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector_cli.egg-info/dependency_links.txt +0 -0
  31. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector_cli.egg-info/entry_points.txt +0 -0
  32. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector_cli.egg-info/requires.txt +0 -0
  33. {hector_cli-0.2.0 → hector_cli-0.3.0}/hector_cli.egg-info/top_level.txt +0 -0
  34. {hector_cli-0.2.0 → hector_cli-0.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hector-cli
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: YAML-driven Renode + Verilator simulation orchestrator for embedded hardware CI
5
5
  Home-page: https://hector-ci.com
6
6
  Author: Nemesis
@@ -50,15 +50,19 @@ Licensed under **AGPL-3.0-or-later** — see [LICENSE](LICENSE) and
50
50
  ## Contents
51
51
 
52
52
  - [Requirements](#requirements)
53
+ - [Installation](#installation)
53
54
  - [Quick start](#quick-start)
55
+ - [Run via Docker (no install)](#run-via-docker-no-install)
54
56
  - [Invocation modes](#invocation-modes)
55
57
  - [Configuration reference](#configuration-reference)
56
58
  - [Top-level fields](#top-level-fields)
57
59
  - [arguments](#arguments)
58
60
  - [matrix](#matrix)
59
61
  - [modules](#modules)
62
+ - [developing your own peripherals](#developing-your-own-peripherals)
60
63
  - [hubs](#hubs)
61
64
  - [machines](#machines)
65
+ - [inline repl and resc](#inline-repl-and-resc)
62
66
  - [peripherals](#peripherals)
63
67
  - [connections (per-machine)](#connections-per-machine)
64
68
  - [mappings](#mappings)
@@ -84,6 +88,34 @@ Licensed under **AGPL-3.0-or-later** — see [LICENSE](LICENSE) and
84
88
 
85
89
  ---
86
90
 
91
+ ## Installation
92
+
93
+ Install the package to get the `hector` command on your `PATH`:
94
+
95
+ ```bash
96
+ cd cli
97
+ pip install . # or: pip install -e . (editable — picks up local edits)
98
+ hector --version
99
+ ```
100
+
101
+ `pip install` creates a `hector` launcher in your environment's scripts directory
102
+ (the venv's `bin/`, or `~/.local/bin` for `pip install --user`). If `hector` isn't
103
+ found afterwards, that scripts directory isn't on your `PATH` — add it, e.g.
104
+ `export PATH="$HOME/.local/bin:$PATH"`.
105
+
106
+ **No install?** Run the module directly from the `cli/` directory — it's equivalent:
107
+
108
+ ```bash
109
+ python -m hector --version
110
+ ```
111
+
112
+ > **Do not add the `cli/` source directory to your `PATH`.** The Python package is
113
+ > named `hector/`, so a bare `hector` would resolve to that **directory** instead of
114
+ > the command, and your shell fails with `permission denied: hector` (or
115
+ > `command not found`). Install with `pip` (above) or use `python -m hector`.
116
+
117
+ ---
118
+
87
119
  ## Quick start
88
120
 
89
121
  ```
@@ -112,6 +144,51 @@ Generated files go in `.hector/` — add it to your `.gitignore`. The Renode **b
112
144
 
113
145
  ---
114
146
 
147
+ ## Run via Docker (no install)
148
+
149
+ If you'd rather not install hector (or even Python) on the host, build the bundled
150
+ image — it sits on top of the official Renode image, so `renode`, `renode-test`
151
+ and `hector` are all inside one container:
152
+
153
+ ```bash
154
+ cd cli
155
+ docker build -t hector-renode .
156
+ # match your project's renode_version:
157
+ docker build --build-arg RENODE_VERSION=1.16.1 -t hector-renode:1.16.1 .
158
+ ```
159
+
160
+ Because Renode is already in the image, hector runs **in-process**
161
+ (`HECTOR_NO_DOCKER=1` is baked in) — no Docker socket, no sibling containers, no
162
+ host-path matching. Use the bundled `hector-docker` wrapper, which mounts your
163
+ project and runs as your UID so output stays yours:
164
+
165
+ ```bash
166
+ ./hector-docker test # run from your project directory
167
+ ./hector-docker validate -f ci.hector.yaml
168
+ ./hector-docker run --renode-args '--console' # headless monitor (no GUI window)
169
+
170
+ # use it like the real thing by symlinking onto your PATH:
171
+ ln -s "$(pwd)/cli/hector-docker" ~/.local/bin/hector
172
+ ```
173
+
174
+ Or the raw form (what the wrapper runs):
175
+
176
+ ```bash
177
+ docker run --rm -it -u "$(id -u):$(id -g)" -e HOME=/tmp \
178
+ -v "$PWD":"$PWD" -w "$PWD" hector-renode test
179
+ ```
180
+
181
+ Override the image tag with `HECTOR_IMAGE` (default `hector-renode:latest`).
182
+
183
+ **Caveats of the in-image mode:** a `build:`/`shell` step's `image:` is ignored —
184
+ the script runs in *this* image instead (a warning is printed), and module builds
185
+ rely on this image's toolchain rather than a per-module one. Interactive `hector
186
+ run` opens Renode's GUI, which needs X forwarding; pass `--renode-args '--console'`
187
+ for a headless monitor. For full per-step image isolation (matching CI), install
188
+ the CLI natively with `pip` and let hector launch real per-step containers.
189
+
190
+ ---
191
+
115
192
  ## Invocation modes
116
193
 
117
194
  | Command | Behaviour |
@@ -122,6 +199,7 @@ Generated files go in `.hector/` — add it to your `.gitignore`. The Renode **b
122
199
  | `hector run --set BIN=fw.elf --set BOARD=nucleo` | Override multiple arguments |
123
200
  | `hector run --debug boardA:3333` | Halt a CPU and open a GDB server |
124
201
  | `hector run --debug boardA:3333 --debug boardB:3334` | Halt multiple CPUs on different ports |
202
+ | `hector run --no-start` | Load the platform and drop into the monitor **paused** — type `start` yourself |
125
203
  | `hector run --renode-args '--console'` | Pass extra flags verbatim to Renode |
126
204
  | `hector run --gather-execution-metrics` | Enable Renode's CPU execution profiler for all machines |
127
205
  | `hector run --gather-execution-metrics boardA` | Enable profiler for one specific machine |
@@ -166,6 +244,11 @@ hector test -f ci.hector.yaml
166
244
  hector run --file boards/nucleo.yaml
167
245
  ```
168
246
 
247
+ **`.yaml` and `.yml` are interchangeable.** If the requested file isn't there but its
248
+ counterpart is, hector uses that instead — so a project may keep `.hector.yml` and
249
+ every command still finds it with no flag, and `-f board.yaml` will pick up
250
+ `board.yml`.
251
+
169
252
  ### Debug mode (`--debug NODE:PORT`)
170
253
 
171
254
  Repeat the flag for each machine you want to debug. ([Renode docs: GDB debugging](https://renode.readthedocs.io/en/latest/debugging/gdb.html))
@@ -181,6 +264,22 @@ server(s) and halts the debugged CPU(s) before resuming, so you can attach to a
181
264
  restored state. (A GDB server is a live connection, never part of saved snapshot
182
265
  state, so it is always (re)started on load.)
183
266
 
267
+ ### Manual start (`--no-start`)
268
+
269
+ Every generated resc ends with a `start`, so `hector run` boots the platform
270
+ immediately. Pass `--no-start` to omit it: hector builds/loads the platform, wires
271
+ everything up, and drops you at the Renode monitor **paused**, so you can inspect
272
+ state, set watchpoints, or step the setup by hand and issue `start` yourself.
273
+
274
+ ```bash
275
+ hector run --no-start # land in the monitor; type `start` when ready
276
+ ```
277
+
278
+ - Applies to a fresh boot and to `--snapshot` (the restored state loads paused).
279
+ - Composes with `--debug`: the GDB server(s) open at load, but nothing runs until
280
+ you `start`, so you can attach a debugger *before* the very first instruction.
281
+ - `hector test` ignores this (tests must run); it only affects `run`/`export`.
282
+
184
283
  Connect with:
185
284
  ```bash
186
285
  arm-none-eabi-gdb firmware.elf
@@ -606,11 +705,21 @@ modules:
606
705
 
607
706
  #### kind: csharp
608
707
 
609
- Builds (or locates) a C# Renode peripheral plugin. The resulting `.dll` is loaded at emulation scope via `i @<path>` before any machine block, making the type available to all machines in the job. ([Renode docs: writing peripherals](https://renode.readthedocs.io/en/latest/advanced/writing-peripherals.html))
708
+ A native C# Renode peripheral, loaded at emulation scope via `i @<path>` before any machine block so the type is available to every machine in the job. ([Renode docs: writing peripherals](https://renode.readthedocs.io/en/latest/advanced/writing-peripherals.html))
709
+
710
+ `source` can take three forms:
610
711
 
611
- Two usage modes:
712
+ **Single `.cs` file (recommended)** — Renode compiles it **at load time** using its bundled C# compiler. No .NET SDK, no build step, nothing to install; the source is compiled against the running Renode's own assemblies, so it always matches the version in use. See the runnable [`csharp-peripheral`](examples/csharp-peripheral) example.
713
+
714
+ ```yaml
715
+ modules:
716
+ my_periph:
717
+ kind: csharp
718
+ type: Antmicro.Renode.Peripherals.Miscellaneous.MyPeripheral
719
+ source: MyPeripheral.cs
720
+ ```
612
721
 
613
- **Pre-built DLL** — point `source` directly at the `.dll`:
722
+ **Pre-built DLL** — point `source` directly at a `.dll` (used as-is):
614
723
 
615
724
  ```yaml
616
725
  modules:
@@ -620,7 +729,7 @@ modules:
620
729
  source: prebuilt/my_periph.dll
621
730
  ```
622
731
 
623
- **Build from source** — point `source` at a directory containing a `.csproj`. `dotnet build` runs inside the Renode container (which ships with Mono/dotnet):
732
+ **Build from a `.csproj`** — point `source` at a directory containing a `.csproj`; `dotnet build` (or `msbuild`) runs in the container. This needs an image that ships the **.NET SDK** *and* Renode's reference assemblies — the stock Renode image has only the runtime, so a `.cs` source is simpler unless you specifically need a pre-built binary:
624
733
 
625
734
  ```yaml
626
735
  modules:
@@ -633,10 +742,63 @@ modules:
633
742
  | Field | Required | Description |
634
743
  |---|---|---|
635
744
  | `kind` | Yes | Must be `csharp`. |
636
- | `type` | Yes | Fully qualified C# class name as it will appear in the generated `.repl`. |
637
- | `source` | Yes | Path to a `.csproj` directory **or** a pre-built `.dll` file. |
745
+ | `type` | Yes | Fully qualified C# class name as it appears in the generated `.repl`. |
746
+ | `source` | Yes | A `.cs` file (compiled at load), a `.csproj` directory (built in the container), **or** a pre-built `.dll`. |
747
+
748
+ The `type` must match the class your source exposes. Multiple peripherals in the same job can share one source (different `type` values, same `source`); Hector emits a single `i @<path>` import even when multiple instances reference it.
749
+
750
+ #### Developing your own peripherals
751
+
752
+ The `modules:` block above only *wires in* a peripheral you've built — the actual
753
+ modelling (the Verilog/C++ of a Verilated block, or the C# of a native peripheral)
754
+ is Renode's domain, not Hector's. Hector compiles your `source:` and loads the
755
+ result; **how** you write that source is documented by Renode and Verilator. The
756
+ references below are where to go to design your own hardware in depth.
757
+
758
+ ##### Verilated (HDL) peripherals
638
759
 
639
- The `type` field is what you would write in a `.repl` entry — it must match the class exposed by the compiled DLL. Multiple peripherals in the same job can share one DLL (different `type` values, same `source`); Hector emits a single `i @<path>` import even when multiple instances reference the same DLL.
760
+ A Verilated peripheral is your RTL (Verilog / SystemVerilog) compiled by Verilator
761
+ and bridged to Renode over a bus interface (APB / AXI-Lite / Wishbone). Hector
762
+ builds it from the CMake project you point `source:` at, linking against the
763
+ **renode-verilator-integration** library (`${INTEGRATION_DIR}`).
764
+
765
+ - **How Renode co-simulates HDL** (the model, the bus connectors, the lifecycle) — [Renode docs: Co-simulating with an HDL simulator](https://renode.readthedocs.io/en/latest/advanced/co-simulating-with-an-hdl-simulator.html)
766
+ - **The integration library + copy-ready CMake samples** (start from `samples/uartlite`, which the `docker-runner`/module examples mirror) — [antmicro/renode-verilator-integration](https://github.com/antmicro/renode-verilator-integration)
767
+ - **Verilating your RTL** (the Verilator C++ API, `--cc`, the `V<top>` model) — [Verilator manual](https://verilator.org/guide/latest/)
768
+ - **Declaring the peripheral in a platform** (the `CoSimulated*` type, its bus window) — [Renode docs: platform description format](https://renode.readthedocs.io/en/latest/advanced/platform_description_format.html)
769
+
770
+ Workflow: verilate your RTL → wrap it with the integration library's bus connector
771
+ in a CMake project → point a `renode-verilator` module's `source:` at that project
772
+ → reference the module from a machine's `peripherals:`.
773
+
774
+ ##### C# peripherals
775
+
776
+ A C# peripheral is a native Renode model — full speed, with direct access to
777
+ Renode's register / IRQ / GPIO infrastructure. Use this when you don't have (or
778
+ don't need) RTL, e.g. a register-level model of a sensor or controller.
779
+
780
+ - **Writing a peripheral from scratch** (interfaces, read/write, reset — the canonical guide) — [Renode docs: Writing your own peripheral](https://renode.readthedocs.io/en/latest/advanced/writing-peripherals.html)
781
+ - **Register modelling helpers** (`DoubleWordRegisterCollection`, fields, value/read/write callbacks) — [Renode docs: Registers](https://renode.readthedocs.io/en/latest/advanced/registers.html)
782
+ - **Hundreds of real models to read and adapt** — the Renode source tree under [`src/.../Emulator/Peripherals`](https://github.com/renode/renode/tree/master/src/Infrastructure/src/Emulator/Peripherals/Peripherals)
783
+ - **Wiring the finished class into a machine** (the `.repl` entry, IRQ/GPIO connections) — [Renode docs: platform description format](https://renode.readthedocs.io/en/latest/advanced/platform_description_format.html)
784
+
785
+ Workflow: implement the class (e.g. an `IDoubleWordPeripheral` with a register
786
+ collection, plus `GPIO`/`IKnownSize`/`IGPIOReceiver` as needed) in a **single
787
+ `.cs` file** → point a `csharp` module's `source:` at it → reference its
788
+ fully-qualified `type` from `peripherals:`. Renode compiles the `.cs` at load
789
+ (bundled C# compiler — no .NET SDK), so this is the simplest, version-matched
790
+ path; the [`csharp-peripheral`](examples/csharp-peripheral) example is a complete,
791
+ runnable starting point. Reach for a `.csproj`/`.dll` only to pre-compile a larger
792
+ project — and note that needs a build image carrying both the .NET SDK and
793
+ Renode's reference assemblies.
794
+
795
+ Either kind, once built, is a first-class Renode peripheral: connect it with
796
+ [connections](#connection-syntax), bind it to host resources with [mappings](#mappings-global),
797
+ and drive it from your [tests](#tests).
798
+
799
+ > **Version note:** Renode's online docs track its latest release. If you pin an
800
+ > older `renode_version:`, cross-check against that release's docs/tag — the
801
+ > co-simulation bus interface and some C# APIs evolve between versions.
640
802
 
641
803
  ---
642
804
 
@@ -725,12 +887,16 @@ machines:
725
887
  backend: renode # optional; 'renode' is the only supported backend
726
888
  platform:
727
889
  - platforms/boards/${BOARD}.repl
890
+ repl: |
891
+ ...
728
892
  firmware: ${FW}
729
893
  peripherals: { ... }
730
894
  connections: |
731
895
  ...
732
896
  mappings: |
733
897
  ...
898
+ resc: |
899
+ ...
734
900
  commands: |
735
901
  ...
736
902
  ```
@@ -738,15 +904,69 @@ machines:
738
904
  | Field | Description |
739
905
  |---|---|
740
906
  | `backend` | Must be `renode` (default). |
741
- | `platform` | List of [`.repl` platform description](https://renode.readthedocs.io/en/latest/advanced/platform_description_format.html) files loaded in order. |
907
+ | `platform` | List of [`.repl` platform description](https://renode.readthedocs.io/en/latest/advanced/platform_description_format.html) **file paths**, loaded in order. |
908
+ | `repl` | Inline `.repl` platform description **text** (see [below](#inline-repl-and-resc)). |
742
909
  | `firmware` | ELF file loaded with [`sysbus LoadELF`](https://renode.readthedocs.io/en/latest/basic/machines.html). Omit or set to `none` to skip. |
743
910
  | `peripherals` | Peripheral instances composed onto this machine. See below. |
744
911
  | `connections` | Signal wiring scoped to this machine. Covers GPIO, IRQ, and bracket-range connections. Bare peripheral names are accepted. |
745
912
  | `mappings` | Per-machine host resource bindings. Same syntax as global `mappings:`. |
913
+ | `resc` | Inline `.resc` monitor-script **text** (see [below](#inline-repl-and-resc)). |
746
914
  | `commands` | Raw [Renode monitor](https://renode.readthedocs.io/en/latest/basic/monitor-syntax.html) commands inserted into the resc after hardware loads. |
747
915
 
748
916
  > **Note:** `artifacts` is now a **top-level** key, not a per-machine one. See [artifacts](#artifacts).
749
917
 
918
+ #### Inline `repl` and `resc`
919
+
920
+ `platform:` takes *paths*, which only works for boards the released Renode image
921
+ already ships. When the board you need exists only on Renode's **master** branch (or
922
+ in your own fork), there is no path to point at — so `repl:` and `resc:` take the
923
+ file **contents** verbatim instead:
924
+
925
+ ```yaml
926
+ machines:
927
+ mcu:
928
+ repl: | # a .repl pasted straight in
929
+ sram: Memory.MappedMemory @ sysbus 0x20000000
930
+ size: 0x10000000
931
+ cpu: CPU.CortexM @ sysbus
932
+ cpuType: "cortex-m3"
933
+ nvic: nvic
934
+ resc: | # a .resc's setup lines
935
+ sysbus ApplySVD @https://.../STM32F103.svd.gz
936
+ sysbus Tag <0x40021000, 0x40021003> "RCC_CR" 0x0A020083
937
+ ```
938
+
939
+ - **`repl:`** is written to `.hector/repl/job_<n>_<node>.inline.repl` and loaded with
940
+ `machine LoadPlatformDescription` (Renode only reads platform descriptions from
941
+ disk). It is loaded **after** any `platform:` files, so it can extend or override
942
+ them — list a released board under `platform:` and patch it with `repl:`.
943
+ - **`resc:`** is emitted verbatim into that machine's block, **after** the platform
944
+ and firmware load and **before** `commands:`.
945
+
946
+ Resulting order inside one machine:
947
+
948
+ ```
949
+ mach create "<node>"
950
+ machine LoadPlatformDescription @<platform: files>
951
+ machine LoadPlatformDescription @<inline repl:>
952
+ sysbus LoadELF @<firmware:>
953
+ <resc:>
954
+ <commands:>
955
+ ```
956
+
957
+ > **Do not put `mach create` in `resc:`** — hector already creates the machine. Use
958
+ > `resc:` for the lines that follow it (`sysbus ApplySVD`, `sysbus Tag`, macros,
959
+ > additional `LoadPlatformDescription`, …).
960
+
961
+ Both accept a block scalar or a list of lines, and both are interpolated like every
962
+ other field. Worked examples:
963
+
964
+ - [`examples/inline-repl-resc`](examples/inline-repl-resc) — the mechanics, on an
965
+ STM32F103 that boots real firmware.
966
+ - [`examples/nucleo-f767zi`](examples/nucleo-f767zi) — the real motivation: a
967
+ **NUCLEO-F767ZI**, which Renode 1.16.1 ships no `.repl` for at all, defined inline
968
+ and running against the pinned release image.
969
+
750
970
  #### peripherals
751
971
 
752
972
  Each entry declares one peripheral instance on this machine. The `type` field is either a built-in Renode class name, a `renode-verilator` module name, or a `csharp` module name. Properties are written directly as flat keys alongside `type` and `at`.