[tutorials] Update GVSOC tutorials and integrate HWPE tutorial#149
[tutorials] Update GVSOC tutorials and integrate HWPE tutorial#149FrancescoConti wants to merge 6 commits into
Conversation
This is a port of @PRASADAR's HWPE tutorial to the current version of GVSOC, performed with AI assistance (Claude Code with Sonnet 4.6). Add HWPE (Hardware Processing Element) tutorial to core/docs/developer_manual/tutorials/hwpe/ and core/docs/developer_manual/tutorials_hwpe.rst. The tutorial guides through three phases: 1. Creating a pulp-open-hwpe target from pulp-open 2. Integrating the HWPE accelerator into the cluster 3. Implementing the C++ HWPE model step by step (8 tasks) Alignment with current gvsoc: - tasks.mk/solutions.mk: updated relative paths to pulp submodule (5 directory levels up instead of 4) - Target files (pulp-open-hwpe.py, pulp_open.py, pulp_open_board.py): updated to current PulpOpenAttr / gvrun.attribute API - integrate_hwpe cluster.py: added pulpnn= parameter and self.conf shim - CMakeLists.txt: updated to current pulp subdirectory list - Task 6-8 solutions: bundle binconv/buffer headers locally (no longer available from neureka/inc/ in current gvsoc-pulp) - test_traces.py: updated latency patterns and cycle offsets (TCDM now returns 0 latency per byte access, giving 1-cycle LOAD_INPUT instead of 4) - run_tutorial_ci.sh: updated binary paths; gvsoc command retained since gvrun does not yet support the full pulp-open platform All 8 model_hwpe tasks pass CI validation.
5dd095a to
b7e9e71
Compare
Extend year ranges to 2026 for all files whose copyright ended before 2026: - 2020 → 2020-2026 - 2020-2022 → 2020-2026 - 2018-2019 → 2018-2026 Add ETH Zurich and University of Bologna as co-holders where the copyright listed only GreenWaves Technologies. Add Apache 2.0 license headers (ETH Zurich and University of Bologna, 2022-2026) to the 28 files that had none: helpers.mk, tasks.mk, solutions.mk, run_tutorial_ci.sh, test_traces.py, per-task application Makefiles, all CMakeLists.txt, and generate_stimuli.py. Generated stimulus data files (task8/inc/*.h) and testset.cfg are left without a copyright header.
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ make create_target_task1 |
There was a problem hiding this comment.
Two problems. (1) Missing -C → No rule to make target. (2) create_target_task1 installs a scaffold whose cluster.py calls L1_subsystem with 3 args while current upstream needs 4, so Verify-1.1 crashes. The path that actually works is to use the solution setup instead:
make -C core/docs/developer_manual/tutorials/hwpe create_target_sol_task4
Note: this one command already creates pulp-open-hwpe.py and the whole pulp_open_hwpe/ folder, so it replaces the manual Task 1.1 (cp pulp-open.py …) and Task 1.2.2 (cp pulp_open/* …)
steps — don't also run those, or you'll overwrite it back to the original and re-introduce the broken dependencies.
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ make build TARGETS=pulp-open-hwpe |
There was a problem hiding this comment.
The current working directory here is .../gvsoc/pulp, but the command expects .../gvsoc. You might want to add cd .../gvsoc
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ cd gvsoc/pulp |
There was a problem hiding this comment.
If you're already in gvsoc/ this should be cd pulp — the gvsoc/ prefix double-counts the cwd and cd fails. (Same issue at line 99 cd gvsoc/pulp/pulp/chips and line 153 cd gvsoc.)
| Similiarly, the references in the following files needs to be modified. Look for the inline hints. | ||
|
|
||
| .. code-block:: text | ||
|
|
||
| /gvsoc/pulp/pulp/chips/pulp_open_hwpe | ||
| ├── pulp_open_board.py | ||
| ├── pulp_open.py | ||
| └── cluster.py |
There was a problem hiding this comment.
This is the single most important bug — it fails silently. The hint only mentions imports and lists 3 files, but a working pulp_open_hwpe needs three kinds of pulp_open→pulp_open_hwpe changes:
- imports in 4 files — soc.py is missing from your list (it's pulp-open-hwpe.py + pulp_open_hwpe/{pulp_open,pulp_open_board,soc}.py);
- hard-coded string paths that fixing imports does NOT touch: pulp_open.py's cluster_config_file='pulp/chips/pulp_open/cluster.json', soc.py's udma_conf_path, cluster.json's power_models;
- the scaffold cluster.py is frozen (no self.conf) and mismatches soc.py. Miss any one and the target silently loads the original cluster (no HWPE).hello still passes (FC-only, never touches the cluster), so it's invisible until the first Section-3 test hangs with zero output. Please add soc.py, spell out the string paths, and note that hello passing ≠ integration works.
| .. code-block:: bash | ||
|
|
||
| $ cd gvsoc | ||
| $ make integrate_hwpe_task1 |
There was a problem hiding this comment.
Needs -C:
make -C core/docs/developer_manual/tutorials/hwpe integrate_hwpe_task1
Also: the cluster.py this installs is a frozen snapshot without self.conf, which crashes against the current soc.py (AttributeError: 'Cluster' object has no attribute 'conf'). We had to replace it with the solution version: cp core/docs/developer_manual/tutorials/hwpe/integrate_hwpe/solutions/pulp_open_hwpe/cluster.py pulp/pulp/chips/pulp_open_hwpe/cluster.py
cp core/docs/developer_manual/tutorials/hwpe/integrate_hwpe/solutions/pulp_open_hwpe l1_subsystem.py pulp/pulp/chips/pulp_open_hwpe/l1_subsystem.py
| :class: task | ||
|
|
||
| Search for hwpe in the gvsoc_config.json file. What went wrong? | ||
| Add the simple_hwpe folder in gvsoc/pulp/pulp/CMakeLists.txt. Then rebuild the model and run the hello application as done previously. |
There was a problem hiding this comment.
Please make this literal: add the line add_subdirectory(simple_hwpe) to pulp/pulp/CMakeLists.txt (e.g. right after add_subdirectory(ne16)). Without it simple_hwpe.so is never compiled — make build exits 0 but run then fails because gapy can't find the hwpe model. (Easy to miss: once added it persists in the pulp submodule, so only a fresh clone exposes it.)
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ make model_hwpe_task1 |
There was a problem hiding this comment.
Needs -C (same as all the other tutorial make targets):
make -C core/docs/developer_manual/tutorials/hwpe model_hwpe_task1
The same -C fix applies verbatim to lines 455, 512, 581, 691, 720, 786, 821
|
|
||
| .. code-block:: bash | ||
|
|
||
| $ make model_hwpe_task6 |
There was a problem hiding this comment.
After this step, make build fails with fatal error: scalar_buffer.hpp: No such file or directory. The starter simple_hwpe/CMakeLists.txt points its includes at ../neureka/inc/binconv and ../neureka/inc/buffer, but on current upstream pulp/pulp/neureka/inc/ contains neither directory, and the starter inc/ doesn't ship scalar_buffer.hpp either. Those headers exist only under solutions/task6/simple_hwpe/inc/.
To get past it: copy the binconv and buffer header directories from the task6 solution's inc/ into pulp/pulp/simple_hwpe/inc/, change the two include entries in simple_hwpe/CMakeLists.txt from ../neureka/inc/binconv and ../neureka/inc/buffer to the local inc/binconv and inc/buffer, then remove the stale build directory for this module so CMake re-configures, and rebuild. Note that each model_hwpe_taskN does a replace_folder that wipes simple_hwpe/, so this same fix has to be repeated for task6, task7 and task8 (using the task7 and task8 solution headers respectively). The proper fix would be to re-base the scaffold's CMakeLists and ship the headers with it.
cp -r core/docs/developer_manual/tutorials/hwpe/model_hwpe/solutions/task6/simple_hwpe/inc/binconv pulp/pulp/simple_hwpe/inc/
cp -r core/docs/developer_manual/tutorials/hwpe/model_hwpe/solutions/task6/simple_hwpe/inc/buffer pulp/pulp/simple_hwpe/inc/
rm -rf build/engine/module_1/pulp/simple_hwpe
| .. admonition:: Task - 3.7.1 Fix LOAD_INPUT latency issue | ||
| :class: task | ||
|
|
||
| To address this issue, uncomment ``#define EFFICIENT_IMPLEMENTATION`` in ``input_load.cpp``. |
There was a problem hiding this comment.
The source actually spells it EFFICIENT_IMPLEMNTATION (missing the second E), and the matching #ifndef uses the same misspelling — so uncomment the line as written in the file. If you type the "correct" EFFICIENT_IMPLEMENTATION it won't match the #ifndef and the optimized path stays off. Better: fix both the #define and the #ifndef to EFFICIENT_IMPLEMENTATION.
| .. admonition:: Task - 3.8.2 Fix FsmEndHandler | ||
| :class: task | ||
|
|
||
| Open ``hwpe_fsm.cpp`` and in ``FsmEndHandler``, uncomment the line ``irq.sync(true)``. |
There was a problem hiding this comment.
Minor: the actual line in FsmEndHandler is _this->irq.sync(true); (with the _this-> prefix). The snippet drops it — worth matching the source so readers can find/grep it.
|
|
||
| After the installation is done, setup the source files to add inline comments to help in performing the tasks. | ||
|
|
||
| .. admonition:: Task - 1.0 setup the source files |
There was a problem hiding this comment.
Create a virtual environment and install requirements
cd .../gvsoc
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt -r core/requirements.txt -r gapy/requirements.txt
| @@ -0,0 +1,861 @@ | |||
| Tutorial - Developing a hardware accelerator | |||
There was a problem hiding this comment.
I suggest add the guidance on how to add CI test.
| │ ├── inc | ||
| │ ├── src | ||
| │ ├── CMakeLists.txt | ||
| │ └── simple_hwpe.py |
There was a problem hiding this comment.
The file tree (line 29) and its description (line 42) call the Python generator simple_hwpe.py, but the actual file is hwpe.py (line 305/311 and the import from pulp.simple_hwpe.hwpe import Hwpe both confirm hwpe.py). A reader will look for a file that doesn't exist. Please fix simple_hwpe.py → hwpe.py here.
| - **/pulp/simple_hwpe/inc**: Relevant includes. | ||
| - **/pulp/simple_hwpe/src**: C++ source codes. | ||
| - **/pulp/simple_hwpe/CMakeLists.txt**: Compilation file requirements. | ||
| - **/pulp/simple_hwpe/simple_hwpe.py**: Python generator to instantiate the simple_hwpe. |
| $ cd gvsoc | ||
| $ make integrate_hwpe_task1 | ||
|
|
||
| All the necessary modifications are to be done in ``gvsoc/pulp/pulp/chips/pulp_open_hwpe/cluster.json``. To include the new HWPE accelerator in the PULP system, an entry of the cluster needs to be updated in ``cluster.json``. The entry needs to be added below the ``dma`` entry as its base address comes next. |
There was a problem hiding this comment.
This says all the necessary modifications for Section 2 are in cluster.json, but Tasks 2.1.2–2.1.4 then edit cluster.py and l1_subsystem.py too. Suggest rewording to "starts with cluster.json" so readers don't think the JSON entry is the whole job.
| .. admonition:: Task - 2.1.4 Connection of Hwpe with L1 subsystem | ||
| :class: task | ||
|
|
||
| Connect the Hwpe's ``irq`` port to the ``event_unit``'s ``hwpe_irq`` port |
There was a problem hiding this comment.
The text says connect irq to "the event_unit's hwpe_irq port", but the code binds to in_event_%d_pe_%d, not a port named hwpe_irq. Please align the prose with the code.
| vp::IoReqStatus Hwpe::hwpe_slave(vp::Block *__this, vp::IoReq *req) | ||
| { | ||
| Hwpe *_this = (Hwpe *)__this; | ||
| _this->trace.msg("Received request (addr: 0x%x, size: 0x%x, is_write: %d, data: 0x%x\n", req->get_addr(), req->get_size(), req->get_is_write(), *(uint32_t *)(req->get_data())); | ||
| } |
There was a problem hiding this comment.
The example body only calls trace.msg(...) and never returns, although the signature is vp::IoReqStatus.
|
|
||
| Can you guess what just happened? The FSM is stuck in an infinite loop. Why is this the case? | ||
|
|
||
| Hint: Check the ``hwpe_fsm.cpp`` file. The exit condition ``input.iteration == iteration.count`` is never met for the ``LOAD_INPUT`` state. Uncomment the trace for ``iteration`` and ``count`` in the FSM. Build the GVSoC model and run the application. You will observe ``iteration=-1`` and ``count=0``. |
There was a problem hiding this comment.
The exit condition is written input.iteration == iteration.count, but it should be input.count (the actual code at line 645 uses this->input.count). iteration.count doesn't exist
| $ make model_hwpe_task7 | ||
|
|
||
|
|
||
| Build the model and run the ``task4`` application. You will notice that both ``LOAD_INPUT`` and ``COMPUTE`` are finished with a latency of 4 instead of 1. |
There was a problem hiding this comment.
Says "both LOAD_INPUT and COMPUTE finish with latency 4", but Task 3.7.2 then optimizes
LOAD_WEIGHT, not COMPUTE. This should read "LOAD_INPUT and LOAD_WEIGHT"
|
|
||
| $ make model_hwpe_task2 | ||
|
|
||
| The Task - 3.2 source files are built on top of Task - 3.2. Did you notice any additional files compared to Task - 3.2 in the ``simple_hwpe`` component? |
There was a problem hiding this comment.
"built on top of Task 3.2" and "compared to Task 3.2" — both should be Task 3.1 (task2 builds on task1). As written it compares the section to itself.
|
Thanks for the comments @lee2716 , will fix :) |
Doc-side fixes to tutorials_hwpe.rst: - add CI hookup subsection and venv prerequisites - rename simple_hwpe.py -> hwpe.py in the file tree/description - restructure Task 1.0 to use the working create_target_sol_task4 path - fix relative cd paths and add cd .../gvsoc to verify blocks - enumerate all pulp_open -> pulp_open_hwpe changes in Task 1.2.3 (imports across 4 files incl. soc.py, hard-coded string paths in pulp_open.py / soc.py / cluster.json) with a warning that hello passing does not imply HWPE integration works - add -C to all integrate_hwpe and model_hwpe make commands - reword the "All necessary modifications are in cluster.json" sentence - renumber three duplicate Task 2.1.4 admonitions to 2.1.4/2.1.5/2.1.6 and fix the wrongly copied title at the irq->event_unit block - align irq port prose with the in_event_*_pe_* binding code - make the add_subdirectory(simple_hwpe) CMakeLists fix literal - add return vp::IO_REQ_OK; to the hwpe_slave snippet - fix self-references (Task 3.2 -> Task 3.1), iteration.count -> input.count, neureka/inc/* -> simple_hwpe/inc/*, COMPUTE -> LOAD_WEIGHT - include the _this-> prefix and trailing semicolon in irq.sync snippet Scaffold/source fixes: - add self.conf = self to all 11 integrate_hwpe cluster.py scaffolds (task_files + task1..task10) so soc.py's cluster.conf.get_property calls resolve against the current upstream pulp_open - vendor binconv/ and buffer/ header directories into the model_hwpe task_files for task6/7/8 and point their CMakeLists at local inc/... so make build no longer fails with scalar_buffer.hpp not found - rename misspelled EFFICIENT_IMPLEMNTATION -> EFFICIENT_IMPLEMENTATION in the task7/task8 task_files and solutions input_load.cpp so the optimized path actually activates when the macro is uncommented
This pull request updates the developer manual's tutorials to reflect recent changes in the build system, simulation workflow, and code structure. It also introduces the HWPE tutorial by @arpansur, which was on a "dead" branch of GVSOC.
The PR is also an experiment in itself as it is aggressively AI-assisted (using Claude Code with Sonnet 4.6). It is an ideal testbed for this as 1) the changes are purely related to documentation and tutorial, no "inner mechanism" is touched, 2) the changes involved porting from an outdated branch of gvsoc on top of a new version, without conceptual changes, 3) the changes are boring and error-prone for a human.
I tested it a bit using the internal regression, but ideally before merging it requires a human going through the full tutorial set to nitpick.
Changes introduced.
The documentation is now more consistent with the current tools and practices, including the use of
gvruninstead ofgvsocfor running simulations, improved parameter passing, and updated code examples. Several corrections and clarifications have also been made to make the tutorials easier to follow.Documentation and Workflow Updates:
Updated all paths and commands in tutorial documentation to use the new
core/docs/developer_manual/tutorialslocation and to referencegvruninstead ofgvsocfor running simulations. Also clarified the build and run sequence, including the need formake configbefore launching simulations. [1] [2] [3]Added a new tutorial reference
tutorials_hwpe.rstto the developer manual index.Code Example Improvements:
Refactored Python code snippets to use the
TargetParameterclass for passing the binary path, updated class inheritance to usegvsoc.systree.Component, and improved parameter passing between components. [1] [2] [3]Updated C++ code examples to use
vp::Block *instead ofvoid *for handler function signatures, improving type safety and clarity. [1] [2] [3] [4]Corrected and clarified interface usage in Python code, switching from
gsystreetogvsoc.systreeand ensuring correct interface types for component connections. [1] [2]Parameter and Configuration Handling:
Updated memory mapping and parameter passing in code examples to use the new
rm_baseargument and clarified its usage.Added an example of how to set instruction latency in a custom ISA, with clarification on when this should be done relative to ISA instantiation. [1] [2]
General Corrections and Clarifications:
These changes ensure the documentation and code samples are up to date, more accurate, and easier for developers to follow.