# Ara: a RISC-V vector coprocessor for the CVA6 core

> Ara is a 64-bit vector unit that plugs into the PULP platform's CVA6 core as a coprocessor and implements the RISC-V Vector Extension 1.0. It is RTL you simulate with Verilator or ModelSim, and the documentation points you at a separate file for exactly which instructions are supported.

**pulp-platform/ara** — The PULP Ara is a 64-bit Vector Unit, compatible with the RISC-V Vector Extension Version 1.0, working as a coprocessor to CORE-V's CVA6 core

- Repository: https://github.com/pulp-platform/ara
- Stars: 555 · Forks: 210
- Language: C
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/pulp-platform-ara

## What Ara is, and where it sits in the system

Ara is a vector unit working as a coprocessor for the CVA6 core, and it supports the RISC-V Vector Extension, version 1.0. The repository description states it as a 64-bit Vector Unit compatible with the RISC-V Vector Extension Version 1.0, working as a coprocessor to CORE-V's CVA6 core, and the topics confirm the shape of the project with riscv, rvv, rv64gcv, vector, cpu and asic.

The coprocessor relationship is the architectural fact that matters. Ara is not a standalone core and it is not an accelerator you bolt onto an existing processor through a generic bus protocol. It sits next to CVA6, which is itself the PULP platform's open-source RISC-V core, and the vector instructions travel between them. The CVA6 side handles the scalar program, Ara handles the vector part, and the split is visible in the ways you can run the design.

What the tree shows is the standard shape of a hardware project: an apps/ directory with example applications, a hardware/ directory with the SystemVerilog, a config/ directory holding the parameter sets, a toolchain/ directory for the RISC-V LLVM build, patches/ for the IP fixups, a scripts/ directory, and Bender.lock and Bender.yml for dependency management.

The primary language is C, which is consistent with the MemsPool tooling that the Makefile uses for the RTL, the applications and the test infrastructure. The README points at DEPENDENCIES.md for the list of hardware and software dependencies, which is a better starting point than the README itself, because a project with external IP and a custom toolchain has dependencies that do not fit in a paragraph.

The prototyping documentation is published separately at pulp-platform.github.io/ara, and the README is explicitly a pointer to it rather than the manual.

## Getting the source and the toolchain in place

The build starts with submodules, and the README is explicit that a recursive clone is needed for all the necessary submodules.

```bash
make git-submodules
```

If the repository path of any submodule changes, you run a sync so the submodule pointers point back at the remote repositories.

```bash
git submodule sync --recursive
```

The toolchain requirement is specific and non-negotiable: Ara requires a RISC-V LLVM toolchain capable of understanding the vector extension, version 1.0. The README gives you a target for building it in the project root.

```bash
# Build the LLVM toolchain
make toolchain-llvm
```

Next is Spike, the RISC-V ISA simulator, and the README explains why it needs an updated version with vector extension support. It also explains a specific build problem: there are linking issues with the standard libraries when using newer CC/CXX versions to compile Spike, so the project resorts to older compiler versions. Spike was compiled successfully using gcc and g++ version 7.2.0, and the fallback for dynamic linking problems is to add a static libstdc++ flag.

```bash
# Build Spike
make riscv-isa-sim
```

The third tool is Verilator, needed for RTL simulations, and again the README gives a target rather than asking you to install a version yourself.

```bash
# Build Verilator
make verilator
```

The Makefile pins the toolchain components with a version variable, a Verilator commit hash and a DTC commit hash, and it sets install directories under an install prefix for the RISC-V GCC, the RISC-V LLVM, the ISA simulator and Verilator separately. It also handles the compiler selection carefully, overriding the default CC and CXX values only when they have not been set by the user, which is the difference between a build that respects your environment and one that ignores it.

The Makefile is licensed under the Apache License, Version 2.0, with the copyright line naming ETH Zurich and the University of Bologna and the author as Matheus Cavalcante of ETH Zurich.

## Configuring the vector unit before you build anything

Ara's parameters are centralized in the config folder, which provides several configurations to the vector machine, and config/README.md is where the details live.

The selection mechanism is a make variable rather than a file edit, which is the right choice for a build parameter. You prepend config=chosen_ara_configuration to your Makefile commands, or you export the ARA_CONFIGURATION variable, to choose a configuration other than the default one.

```bash
make config=chosen_ara_configuration
```

What those parameters are is not in the README, and that is a genuine gap in the documentation as presented here. A vector unit has the obvious axes: the number of vector registers and their length in elements, the number of lanes in the vector ALU, the memory interface width, the number of outstanding transactions, the vector instruction queue depth. A configuration set lets you trade area, power and frequency against performance and against how much software you can run on it, which is the difference between a configuration that fits a research FPGA and one that fits a test chip.

The Memora.yml file at the repository root is the sibling artefact to Bender.yml, and the Makefile's ROOT_DIR and ARA_DIR variables show the project is arranged around a MemPool layout with a predictable root directory. The cheshire/ directory in the tree suggests the system can also be assembled around Cheshire, which is another PULP component.

For anyone reading the source, the three documents to read first are DEPENDENCIES.md for what you need installed, FUNCTIONALITIES.md for which vector instructions are actually supported, and config/README.md for what the parameters do. The README's job is to route you to them, and it does that adequately.

## Building the example applications and running them on Spike

The apps folder contains example applications that work on Ara, and the build for one of them is a make target from inside that directory.

```bash
cd apps
make bin/hello_world
```

The same applications can be simulated with Spike, and there is a target that builds the Spike binary and another that runs it.

```bash
cd apps
make bin/hello_world.spike
make spike-run-hello_world
```

The apps folder also contains the RISC-V tests repository, including a few unit tests for the vector instructions, built with:

```bash
cd apps
make riscv_tests
```

That unit test set matters more than its size suggests, because it is the fastest way to find out whether a change to the RTL broke an instruction. The vector ISA has many instructions with awkward corner cases around tail elements, element widths and mask handling, and hand-written example programs will not catch those. A conformance suite will.

The README also lists support for the rvv-bench instructions benchmark, so performance work has a tool that is not one of the example applications.

The Ideal Dispatcher mode is the second simulation mode and it is the interesting one for performance analysis. CVA6 can be replaced by an ideal FIFO that dispatches the vector instructions to Ara with the maximum issue-rate possible, and in this mode only Ara and its memory system affect performance. The README is candid about the cost of that isolation, and the three limitations are worth reading before you trust a number it produces. The dispatcher is a simple FIFO, so Ara and the dispatcher cannot have complex interactions. Therefore the vector program should be fire-and-forget, and there cannot be runtime dependencies from the vector to the scalar code. And not all the vector instructions are supported, for example the ones that use the rs2 register.

```bash
cd apps
make bin/${program}.ideal
```

The generated ideal binary is loaded into the L2 memory for the simulation, holding the data the vector code accesses, and the system is then run in that mode with:

```bash
cd hardware
make sim app=${program} ideal_dispatcher=1
```

That mode is a measurement instrument with a stated scope, and the scope is the point: it lets you attribute a result to Ara rather than to the interface between Ara and CVA6.

## RTL simulation with Bender, Verilator and ModelSim

The hardware folder contains all the SystemVerilog files, and the dependencies are handled with Bender, which the README describes as the tool for the external IPs. The checkout step installs Bender and pulls in the hardware IPs.

```bash
# Go to the hardware folder
cd hardware
# Install Bender and checkout all the IPs
make checkout
```

Some of the IPs need patching to work with Verilator, and the README marks that step as required only once, to be repeated only if the IP hardware dependencies are deleted and checked out again.

```bash
# Go to the hardware folder
cd hardware
# Apply the patches (only need to run this once)
make apply-patches
```

The ModelSim flow separates compiling from running. The compile target only builds the hardware without running the simulation, and the app variable selects which binary is loaded into memory.

```bash
# Go to the hardware folder
cd hardware
# Only compile the hardware without running the simulation.
make compile
# Run the simulation with the *hello_world* binary loaded
app=hello_world make sim
# Run the simulation without starting the gui
app=hello_world make simc
```

There is also a variant that takes a full path to a binary, preload=/some_path/some_binary make sim, which is what you need when the program lives outside the standard build output.

The Verilator flow has its own targets, with simv for running simulations against the Verilator model and verilate to build that model.

```bash
# Go to the hardware folder
cd hardware
# Verilate the design
make verilate
# Run the simulation with the *hello_world* binary loaded
app=hello_world make simv
```

The Verilator flow is the one to use for the unit tests, and the README explains why: given the number of unit tests, they use Verilator rather than ModelSim.

```bash
# Go to the hardware folder
cd hardware
# Verilate the design
make verilate
# Run the tests
make riscv_tests_simv
```

A top-level riscv_tests target also compiles the RISC-V tests and runs their simulation, so you do not have to switch directories for that case.

Two analysis flows sit alongside the simulation. Traces are generated by adding trace=1 to the verilate, simv and riscv_tests_simv commands, which produces waveform traces in the fst format that you can open with gtkwave. And VCD dumping uses the vcd_dump=1 option for accurate activity-based power analyses, with the compile and the run both needing the flag.

```bash
make -C apps bin/${program} vcd_dump=1
make -C hardware simc app=${program} vcd_dump=1
```

The README lists the kernels that currently support automatic VCD dumping, which is a fixed set: fmatmul, fconv3d, fft, dwt, exp, cos, log, dropout and jacobi2d. That list is a good picture of what Ara is being used for, because it is a set of machine learning and signal processing kernels.

There is also a linting flow with Synopsys SpyGlass scripts in hardware/spyglass, run with make lint in the hardware folder using a specific MemPool configuration.

## Where Ara stops being the right choice

There are three limits, and the first is architectural coupling.

The first is that Ara is designed around CVA6. It is a coprocessor for that core, and the way it is exercised depends on it: the CVA6 side issues the vector instructions, and the Ideal Dispatcher mode exists precisely because replacing CVA6 with an ideal FIFO is a special case that needs its own caveats. For a commercial RISC-V core other than CVA6, Ara is a design to study rather than a design to integrate, because the instruction dispatch, the memory system and the L2 model are all part of the same project.

The second is the release history versus the commit history. The recent releases are v2.2.0 from 2021-11-02, v2.1.0 from 2021-07-16 and v2.0.0 from 2021-06-24, so the tagged releases are about five years old, while the last push was on 2026-10-16 and the repository is not archived. The project is clearly still being worked on and the tagged releases are not where that work is visible. Anyone planning around a version number is planning around a 2021 snapshot, and the branch structure in the repository suggests there is more than one line of development, with a main default branch and a separate cheshire directory.

The third is the toolchain cost, which is the practical barrier for most newcomers. You need a RISC-V LLVM that understands vector extension 1.0, built from the project, an updated Spike compiled with gcc and g++ 7.2.0 because newer compilers hit linking problems with the standard libraries, and a Verilator version built from a pinned commit. The build pulls external IPs through Bender and needs patches applied to them. None of this is a packaging complaint, and each step is documented, but it is several hours of setup before you can simulate a hello world, and it is not the experience of installing a package.

The honest alternative depends on which half of Ara you actually need. For software development against the Vector Extension, there is no substitute for a simulator: Spike with vector support, or QEMU with a vector-enabled build, gives you an instruction set simulator to write and debug vector code without any RTL at all, and it is a fraction of the setup. For hardware implementation, the alternative is to write the vector unit yourself against the RISC-V Vector Specification 1.0, which is a serious undertaking but gives you a design matched to your own core and your own microarchitecture. Ara's value in both cases is that it is a working reference implementation with a simulation flow around it, and the cost of that reference is the toolchain it assumes.

## Conclusion

Adopt Ara if you are building RISC-V vector hardware or evaluating the Vector Extension 1.0 in simulation, since it gives you a working coprocessor RTL, a simulator flow and a parameterised configuration. Do not adopt it as a drop-in accelerator for a commercial core, because it is tied to CVA6 and to the PULP IP flow. Before you start, read FUNCTIONALITIES.md for the supported instruction list and DEPENDENCIES.md for the hardware and software requirements, and note the last push was on 2026-10-16.

## FAQ

### What is Ara and which RISC-V specification does it implement?

Ara is a 64-bit vector unit that works as a coprocessor for the CVA6 core, and it supports the RISC-V Vector Extension version 1.0. It is written in SystemVerilog and C, and the repository carries Bender files, a Memora.yml configuration and a config folder with several vector machine configurations.

### How do I get the Ara repository and its toolchain set up?

Run make git-submodules to fetch all the necessary submodules, and git submodule sync --recursive if a submodule path changed. Then build the RISC-V LLVM toolchain with make toolchain-llvm, the Spike simulator with make riscv-isa-sim, and Verilator with make verilator, all from the project root.

### How do I build and run the Ara example applications?

From the apps folder, run make bin/hello_world to build an application, and make bin/hello_world.spike followed by make spike-run-hello_world to build and run it under Spike. The apps folder also holds the RISC-V tests repository, built with make riscv_tests.

### How do I run the Ara unit tests in RTL simulation?

The README notes that given the number of unit tests, Verilator is used rather than ModelSim. From the hardware folder, run make apply-patches once, make verilate to build the model and make riscv_tests_simv to run the tests, or use the top-level riscv_tests target to compile the tests and run their simulation in one step.

### What is the Ideal Dispatcher mode in Ara and what are its limits?

CVA6 can be replaced by an ideal FIFO that dispatches vector instructions to Ara with the maximum issue rate possible, so only Ara and its memory system affect performance. The dispatcher is a simple FIFO with no complex interactions, so the vector program must be fire-and-forget with no runtime dependencies from the vector to the scalar code, and not all vector instructions are supported, for example the ones using the rs2 register.

## Sources

- [Issues](https://github.com/pulp-platform/ara/issues)
- [pulp-platform/ara on GitHub](https://github.com/pulp-platform/ara)
- [README](https://github.com/pulp-platform/ara/blob/main/README.md)
- [Releases](https://github.com/pulp-platform/ara/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pulp-platform-ara
