Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6894a5c
[hw] doublebw_vlsu, OPE: add segmented logical tile-row transfers
boboloiono Oct 12, 2026
c43011b
[sw] fp16 matmul vtse: remove TE32 row-stride operand
boboloiono Oct 12, 2026
4316d23
[sw] add fp16-matmul vse "store-group" strategy via 1x4 tiles layout
boboloiono Oct 13, 2026
fab3193
[sw] optimal kernel matmul(*A, *B, *C) without passing M, N, K runtim…
boboloiono Oct 14, 2026
b2ded3d
[sw] fp16 matmul vse with 1x4 via change vector load register mapping…
boboloiono Oct 14, 2026
8ad10c2
[sw] fp16 gemm with vle+vse using 1x4 layout (66%), vsetvl with vtle+…
boboloiono Oct 14, 2026
3f65680
[sw] fp16 gemm LMUL=8 for bias vle32, vfadd, vse32 (66.5%)
boboloiono Oct 14, 2026
a8d721e
[sw] gemm-unit, gemm-alpha: ungroup vle v0 to remove 2 cycle gaps fro…
boboloiono Oct 14, 2026
ab69256
[hw] doublebw_vlsu, OPE: add segmented logical tile-row transfers
boboloiono Oct 12, 2026
775faf7
[sw] fp16 matmul vtse: remove TE32 row-stride operand
boboloiono Oct 12, 2026
9922553
[hw] controller, vlsu: memory operations use EEW instead of SEW
boboloiono Oct 16, 2026
1b5698e
[build] allow sw.vsim to select TE32 VME kernels
boboloiono Oct 16, 2026
e901d21
[sw] passing TCDM size parameter with runtime config SNRT_TCDM_SIZE
boboloiono Oct 16, 2026
f4c7819
[sw] modify fp16 kernel size generation
boboloiono Oct 16, 2026
ba0cbbd
[hw] ope: remove non-standard forward references (typedef) that newer…
boboloiono Oct 16, 2026
0c58524
[hw] spatz: remove combinational loops in OPE and VLSU paths
boboloiono Oct 16, 2026
d656daa
[hw] lint: remove automatic declaration initializers in controller an…
boboloiono Oct 16, 2026
50433d0
[sw] gemm-beta: α XW + β bias (66.85%).
boboloiono Oct 19, 2026
eddb074
[hw] decoder, controller riscv_instr: Align VME v0.4 with updated enc…
boboloiono Oct 19, 2026
daa0f68
[vme] Remove obsolete FP32 GEMM variants
boboloiono Oct 19, 2026
d29f527
[vme] Rework Zvt v0.4 ISA tests
boboloiono Oct 20, 2026
ccb1d83
[HW] Fix OPE tile-word indexing and MAC forwarding
boboloiono Oct 20, 2026
ce18160
[hw] spatz_cluster: remove compute core from doublebw config
boboloiono Oct 21, 2026
149847e
[hw] ope: pipeline back-to-back tile-vector moves
boboloiono Oct 21, 2026
5de5c61
[sw] vme: update Zvt v0.4 software support
boboloiono Oct 21, 2026
16299d1
[hw] ope: document VME microarchitecture
boboloiono Oct 21, 2026
271968d
[docs] remove Chinese VME microarchitecture draft
boboloiono Oct 21, 2026
78f1c52
[hw] modification for vme_v0.4 backend (tcdm=128 KiB, one core)
boboloiono Oct 22, 2026
6ebaef0
[sw] fp16 vq-mamtul with vluxei16 (14.51%)
boboloiono Oct 23, 2026
b6c5fa1
[sw] vq-gemm in VME speedup 1.8x compared to O-POPE benchmark
boboloiono Oct 25, 2026
b8240aa
[sw] gemm-softmax in VME gets 1.44x speedup
boboloiono Oct 25, 2026
54f6c8f
vme: remove obsolete FP32 VLE/VTLE matmul apps
boboloiono Oct 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ sw/toolchain/riscv-gnu-toolchain: sw/toolchain/riscv-gnu-toolchain.version

sw/toolchain/llvm-project: sw/toolchain/llvm-project.version
mkdir -p sw/toolchain
cd sw/toolchain && git clone https://github.com/boboloiono/llvm-project.git
test -d $@/.git || git clone https://github.com/boboloiono/llvm-project.git $@
cd sw/toolchain/llvm-project && \
git checkout `cat ../llvm-project.version` && \
git submodule update --init --recursive --jobs=8 .

sw/toolchain/riscv-opcodes: sw/toolchain/riscv-opcodes.version
mkdir -p sw/toolchain
cd sw/toolchain && git clone https://github.com/boboloiono/riscv-opcodes.git
test -d $@/.git || git clone https://github.com/boboloiono/riscv-opcodes.git $@
cd sw/toolchain/riscv-opcodes && \
git checkout `cat ../riscv-opcodes.version` && \
git submodule update --init --recursive --jobs=8 .
Expand Down
18 changes: 9 additions & 9 deletions hw/ip/snitch/src/riscv_instr.sv
Original file line number Diff line number Diff line change
Expand Up @@ -1078,15 +1078,15 @@ package riscv_instr;
localparam logic [31:0] P_FLH_RRPOST = 32'b1010000??????????001?????1111011;
localparam logic [31:0] P_FLW_RRPOST = 32'b1010000??????????010?????1111011;
localparam logic [31:0] P_FLD_RRPOST = 32'b1010000??????????011?????1111011;
localparam logic [31:0] MSETMTYPE = 32'b1000001??????????111000001010111;
localparam logic [31:0] MSETTN = 32'b100001000000?????111?????1010111;
localparam logic [31:0] MSETTM = 32'b100001000001?????111?????1010111;
localparam logic [31:0] MSETTK = 32'b100001000010?????111?????1010111;
localparam logic [31:0] MSETMTYPEI = 32'b1000010???11?????111000001010111;
localparam logic [31:0] VTFMM_TVV = 32'b1111001??????????001????01110111;
localparam logic [31:0] VTFMM_ALT_TVV = 32'b1111001??????????001????11110111;
localparam logic [31:0] VTMMU_TVV = 32'b1111001??????????000????01110111;
localparam logic [31:0] VTMMS_TVV = 32'b1111001??????????000????11110111;
localparam logic [31:0] MSETTN = 32'b100010000000?????111?????1010111;
localparam logic [31:0] MSETTM = 32'b100010000001?????111?????1010111;
localparam logic [31:0] MSETTK = 32'b100010000010?????111?????1010111;
localparam logic [31:0] MSETMTYPEI = 32'b100?100??100000??111000001010111;
localparam logic [31:0] MSETMTYPE = 32'b1000010??????????111000001010111;
localparam logic [31:0] VTFMM_TVV = 32'b1111001??????????001???001110111;
localparam logic [31:0] VTFMM_ALT_TVV = 32'b1111001??????????001???011110111;
localparam logic [31:0] VTMMU_TVV = 32'b1111001??????????000???001110111;
localparam logic [31:0] VTMMS_TVV = 32'b1111001??????????000???011110111;
localparam logic [31:0] VTLE8 = 32'b0001001??????????111000000000111;
localparam logic [31:0] VTLE16 = 32'b0011001??????????111000000000111;
localparam logic [31:0] VTLE32 = 32'b0101001??????????111000000000111;
Expand Down
16 changes: 11 additions & 5 deletions hw/ip/spatz/src/generated/spatz_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,19 @@ package spatz_pkg;
localparam int unsigned NrPhysicalTile = 16;
// Tile Dimension
localparam int unsigned OPEComputeEdge = 8;
// The ratio of Tile Dimension and OPE FMA array size
// Number of compute-edge groups along one tile edge
localparam int unsigned NrAccPerComputeElem = 2;
localparam int unsigned TileEdge = OPEComputeEdge * NrAccPerComputeElem;
// The controller further limits tk to 32/SEW, or to one for 64-bit accumulation.
localparam int unsigned KMAX = (AccElemWidth <= 32) ? (32 / 8) : 1;
// Datapath between VLSU and OPE
localparam int unsigned TileDataWidth = TileEdge*AccElemWidth;
// Maximum storage required for one complete Tile row, in bytes.
localparam int unsigned TileRowBWidth = TileEdge * AccElemBytes;
// Fixed word width of the datapath between VLSU and OPE, in bytes.
localparam int unsigned TileWordBWidth = TileEdge * AccElemBytes;

typedef logic [$clog2(TileEdge)-1:0] tile_dim_t;
typedef logic [$clog2(TileEdge+1)-1:0] tile_count_t;
typedef logic [$clog2(TileWordBWidth)-1:0] tile_word_elem_idx_t;
typedef logic [$clog2(NrPhysicalTile)-1:0] mt_t;
typedef struct packed {
logic tile_valid;
Expand Down Expand Up @@ -146,19 +149,22 @@ package spatz_pkg;
typedef logic [N_FU*ELENB-1:0] vrf_be_t;
typedef logic [N_FU*ELEN-1:0] vrf_data_t;

typedef logic [TileDataWidth-1:0] tile_row_t;
typedef logic [8*TileRowBWidth-1:0] tile_row_t;
typedef logic [8*TileWordBWidth-1:0] tile_word_t;
typedef struct packed {
mt_t idx;
tile_dim_t row;
tile_dim_t col;
tile_count_t elems;
vew_e tew;
} tile_r_req_t;
typedef struct packed {
mt_t idx;
tile_dim_t row;
tile_dim_t col;
tile_count_t elems;
vew_e tew;
tile_row_t data;
tile_word_t data;
} tile_w_req_t;

// Instruction ID
Expand Down
35 changes: 35 additions & 0 deletions hw/ip/spatz/src/ope/docs/1. overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Spatz VME: Study Overview

## Research Focus

This study integrates the Zvt version 0.4 Vector Matrix Extension into the Snitch–Spatz system. Spatz already provides a compact vector register file (VRF), vector arithmetic, and access to a banked tightly coupled data memory (TCDM). The extension adds matrix configuration, an Outer Product Engine (OPE), and matrix tile state. Matrix instructions take their source operands from the VRF and accumulate into tiles, while existing vector instructions remain available for data preparation and result processing.

The central question is how to make matrix arithmetic useful in a complete GEMM kernel on a compact vector processor. Input loads, register allocation, instruction supply, tile transfers, and output processing can limit performance even when the arithmetic array is busy. The study considers FP32-to-FP32 and widening FP16-to-FP32 computation and examines how tile layout and instruction scheduling affect these costs.

## Design and Evaluation Questions

- **Operand and result movement:** How much data moves from TCDM to the VRF, from the VRF to the OPE, and from the tiles back to memory or vector registers? When does direct tile storage avoid a VRF transfer, and when is a tile-to-vector move useful for post-processing?
- **Shared resources:** How do the VAU and OPE share VRF access, and how do the controller and execution units preserve dependencies between vector and matrix instructions?
- **Tile geometry:** How do the architectural tile edge (TE), physical compute edge (CE), VRF word width, and Tile interface width affect instruction count, execution time, and transfer granularity?
- **Kernel mapping:** How do output tile layouts, vector register groups, FP16 operand packing, and store schedules affect input reuse, register lifetime, and overlap between computation and output transfer?
- **Measured behavior:** Which predicted costs appear in cycle-accurate simulations, and which stalls arise from instruction supply, memory accesses, VRF contention, or accumulator dependencies?

## Scope of the Work

The hardware contribution is the integration of the OPE and tile data paths into Spatz, including matrix configuration, instruction dispatch, dependency management, and coordination with the double-bandwidth VLSU. The software contribution is a set of matrix kernels and scheduling choices that exercise the FP32 and widening FP16 modes. An analytical model separates instruction counts, element transfers, and byte traffic before the measured performance is discussed.

TE describes the tile visible to a matrix instruction; CE describes the physical compute array that processes it. Changing CE can change the number and timing of physical execution beats without changing the number of architectural matrix instructions for a fixed TE and workload. Likewise, a tile-to-vector move uses the VRF path, while a tile load or store uses the VLSU Tile interface. The analysis treats these as distinct transfers.

## Chapter Roadmap

1. **Introduction** states the workload problem, research goals, and hardware and software contributions.
2. **[Background and Related Work](<2. Background and Related Work.md>)** introduces matrix dataflows, vector data movement, SSR, MX, O-POPE, and matrix engine integration choices. It compares where operands and partial sums reside and how results leave the compute unit.
3. **[System Overview and Spatz VME Architecture](<3. System Overview and Spatz VME Architecture.md>)** introduces Snitch, Spatz, the VRF, VAU, OPE, VLSU, and TCDM. It follows instruction dispatch and completion, then defines the software-visible Zvt configuration, tiles, arithmetic, and transfer operations.
4. **[Spatz VME Microarchitecture](<4. Spatz VME Microarchitecture.md>)** describes the implemented controller, scoreboards, shared VRF arbitration, distributed OPE, accumulator behavior, and VLSU Tile path.
5. **[System-Level and ISA Exploration](<5. System-Level and ISA Exploration.md>)** examines VLEN, TE, CE, precision, instruction demand, accumulator capacity, and the distinct VRF and Tile transfer paths. It separates analytical design points from the implemented configuration.
6. **[Kernel Design](<6. Kernel Design.md>)** will describe FP32 and packed FP16 operand layouts, output tile mappings, register allocation, configuration changes, and store schedules. This chapter is reserved for later writing.
7. **Experimental Methodology** specifies the hardware configuration, instruction cache and buffer, workloads, baselines, correctness checks, simulation procedure, and definitions of cycles and utilization.
8. **Results and Discussion** evaluates the kernel and hardware choices against the analytical predictions, using traces and measured cycles to explain bottlenecks and limitations.
9. **Conclusion and Future Work** summarizes the supported findings and identifies remaining architectural and software opportunities.

The analytical model establishes expected work and traffic; the experimental results determine whether a particular mapping or schedule improves execution on this implementation. Statements about issue limits and transfer cycles therefore refer to the specified register mapping and data path rather than to a general Zvt ISA limit.
31 changes: 31 additions & 0 deletions hw/ip/spatz/src/ope/docs/2. Background and Related Work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# 2. Background and Related Work

## 2.1 Matrix Workloads and Data Reuse

Matrix multiplication appears both as a standalone kernel and as one stage of a longer computation. Inputs may require packing, transposition, or conversion before multiplication. Outputs may be consumed by bias addition, scaling, activation, or quantization. The cost of these stages depends on where the operands and partial sums reside and how results reach the next operation. Arithmetic throughput alone therefore does not describe the cost of a complete matrix workload.

For a matrix product `C[M,N] += A[M,K] × B[K,N]`, an inner-product mapping computes each output element by reducing one row of `A` against one column of `B`. A row-wise vector mapping broadcasts an element of `A` across a row of `B` and updates a corresponding row of `C`; it offers contiguous vector accesses for row-major `B` and `C`, but keeping several output rows live consumes vector registers. An outer-product mapping uses a column segment of `A` and a row segment of `B` at each reduction step to update a two-dimensional region of `C`. Each input element is reused across one dimension of that region, while the output partial sums must remain available throughout the reduction.

Mixed-precision matrix multiplication reduces input storage and transfer width while retaining a wider accumulator. A widening FP16-to-FP32 operation, for example, consumes FP16 multiplicands and accumulates into FP32 results. The wider accumulator limits rounding during the `K` reduction, while input conversion and packing still contribute to the overall workload. These properties motivate examining memory traffic, register pressure, and output handling alongside the compute datapath.

## 2.2 Data Movement in Compact Vector Processors

A vector instruction applies one operation to multiple elements and amortizes instruction fetch and decode over the vector length. A vector register file (VRF) can also retain inputs and intermediate values close to the functional units, reducing accesses to shared L1 memory. In its floating-point Spatz cluster, Perotti et al. analyze this trade-off and use a compact, latch-based 2 KiB VRF per vector processing element. A small VRF lowers storage cost, but the available register capacity and ports constrain how many matrix operands and output partial sums can remain live at once. [Spatz paper](https://arxiv.org/html/2309.10137#S4)

Regular matrix loops also spend scalar instructions on address updates and explicit data transfers. Stream Semantic Registers (SSR) associate registers with configured memory streams, removing many explicit loads and stores from the inner loop of a scalar core. SSR primarily changes how operands are supplied; the storage of matrix partial sums depends on the compute architecture coupled to those streams. [SSR paper](https://arxiv.org/abs/1911.08356)

These approaches trade instruction traffic against data movement and local storage. A longer vector or a more aggressive loop unroll can reduce control overhead, but may occupy more registers or enlarge the instruction stream. A matrix instruction can describe more arithmetic work, yet still require packing, register transfers, and result writeback. The useful comparison is therefore the movement of `A`, `B`, and `C` through memory, the VRF, and the compute unit over the full kernel.

## 2.3 Matrix Engine Integration

Matrix extensions differ in how much of the vector datapath they reuse. MX extends Spatz by retaining the existing VRF and functional units, adding operand broadcast and a compact buffer near the FPUs to increase reuse during matrix multiplication. This limits new hardware but keeps matrix arithmetic tied to the throughput and scheduling of the vector functional unit. [MX paper](https://arxiv.org/abs/2401.04012)

Architectures with separate tile state keep output partial sums outside the ordinary vector registers. Arm SME, for example, provides ZA matrix storage with tile-slice transfers to vector registers and memory. Intel AMX provides tile registers and a tile-multiplication engine. These designs expose different tile organizations and transfer operations, so their peak arithmetic rates alone are not a sufficient basis for comparing full kernels. [Arm SME overview](https://learn.arm.com/insights/sme/) · [Intel AMX overview](https://www.intel.com/content/www/us/en/products/docs/accelerator-engines/what-is-intel-amx.html)

An outer-product engine can exploit the reuse of each operand across a two-dimensional compute array. O-POPE studies a pipelined implementation that uses FPU pipeline registers to hold intermediate results and reduce dedicated buffering. That work concerns the compute engine itself; integrating such an engine into a vector processor additionally requires instruction dispatch, register dependencies, memory access, and paths for moving tile results to later vector operations. [O-POPE paper](https://arxiv.org/abs/2606.02333)

## 2.4 Position of This Work

This work integrates a separate Outer Product Engine (OPE) into Spatz while retaining the VRF as the source of matrix operands. The OPE holds two-dimensional tile results, and the existing vector datapath remains available for input preparation and output processing. Tile transfers to and from memory provide another path for results that do not require a vector post-processing step. The design consequently combines a dedicated matrix compute and accumulator path with shared vector storage and a common instruction-control domain.

The questions addressed by this integration are concrete: how operands reach the OPE without adding dedicated VRF operand ports; how vector and matrix instructions remain ordered while using different result storage; and when tile results should pass through the VRF instead of moving directly to memory. Chapter 3 introduces the Snitch–Spatz system and the software-visible Zvt model. Chapter 4 describes the corresponding hardware paths and dependency mechanisms.
Loading