RISC-V Vector (RVV) Intrinsic Documentation

repository·main·Indexed 18 days ago

https://github.com/riscv-non-isa/riscv-rvv-intrinsic-doc

Documentation for the RISC-V Vector specification and its associated C intrinsics. This repository provides specification drafts and auto-generated intrinsic prototypes, including detailed guides for BFloat16 vector operations such as segmented loads, stores, and narrowing/widening conversions. It includes a compiler compatibility guide for RVV versions v1.0, v0.12, and v0.11 across Clang and GCC.

Tokens
85.8K
Snippets
240
Records
271
Agent score
63%

What's inside riscv-rvv-intrinsic-doc

  1. Overview of RISC-V Vector Intrinsic Documentation

    main

    This project provides documentation for the RISC-V Vector specification and its associated C intrinsics.

    • Specification Drafts: Located in the doc/ directory.
    • Intrinsic Prototypes: Auto-generated prototypes are available in the auto-generated/ directory. These are produced by scripts found in the rvv-intrinsic-generator/ repository.

    For the most up-to-date information, users should refer to the Releases page.

  2. BFloat16 Miscellaneous Vector Utility Intrinsics Overview

    main

    The BFloat16 miscellaneous vector utility intrinsics provide several categories of operations for manipulating BFloat16 vector data. These utilities are categorized by their functional purpose, such as reinterpreting data types, managing LMUL (Length Multiplier) extensions or truncations, and handling vector initialization, insertion, extraction, and creation.

    Note that these specific utility intrinsics do not utilize policy variants.

  3. Handle Agnostic Values and Undefined Behavior

    main

    An agnostic value is an indeterminate value at the element granularity. This includes:

    • Tail elements produced via ta instructions.
    • Masked-off elements produced via ma instructions.
    • All elements in an uninitialized value.
    • Values assigned via vundefined intrinsics.

    Warning: Evaluating an agnostic value is undefined behavior. Do not rely on its contents.

  4. How the RISC-V Vector Intrinsic naming scheme works

    main

    RISC-V vector intrinsics use a structured naming scheme to encode control over the vector programming model directly into the function name. This allows for explicit control over:

    1. EEW (Effective Element Width) and EMUL (Effective LMUL): Encoded in the suffix for explicit intrinsics (e.g., _i32m1).
    2. Vector Length (vl): Specified via the size_t vl argument (Application Vector Length).
    3. Masking and Policy: Suffixes determine if an operation is masked (vm) and how tail/mask-off elements are handled (vta, vma).
    4. Rounding Modes: For fixed-point (vxrm) and floating-point (frm) operations.

    There are two main types of intrinsics:

    • Explicit (Non-overloaded): The function name contains all configuration details (EEW, EMUL, etc.), making the execution state highly readable.
    • Implicit (Overloaded): The function name omits EEW/EMUL, allowing the same function name to accept different data types (relying on C overloading).
  5. Use Zvfbfa extension BF16 vector compute intrinsics

    main

    The Zvfbfa extension provides additional BF16 (bfloat16) vector compute support. It includes several families of multiply-accumulate and multiply-accumulate-subtract intrinsics that operate on BF16 inputs and accumulate into F32 (float32) vectors.

    Key intrinsic families include:

    • vfwmacc: Vector-Vector or Vector-Scalar Multiply-Accumulate.
    • vfwnmacc: Vector-Vector or Vector-Scalar Multiply-Accumulate-Subtract (Negative Multiply-Accumulate).
    • vfwmsac: Vector-Vector or Vector-Scalar Multiply-Sum-Accumulate.
    • vfwnmsac: Vector-Vector or Vector-Scalar Multiply-Negative-Sum-Accumulate.

    These intrinsics support various register grouping (LMUL) configurations (e.g., mf2, m1, m2, m4, m8) and can be used in three modes:

    1. Standard: Direct execution.
    2. Masked (_m): Execution controlled by a mask register (vm).
    3. Rounding Mode (_rm): Execution with a specified rounding mode (frm).
  6. Understand the RISC-V Vector C Intrinsic API structure

    main

    The RISC-V Vector C Intrinsic specification organizes its API into several distinct categories based on how the intrinsics are invoked and their behavior. When using these intrinsics, you will encounter four main types:

    1. Explicit (Non-overloaded) intrinsics: These require specific function names that do not rely on C++ overloading to resolve types.
    2. Implicit (Overloaded) intrinsics: These use C++ function overloading, allowing the same function name to work with different data types.
    3. Policy Variants: Both Explicit and Implicit intrinsics have versions that include policy variants, which likely allow for fine-grained control over vector execution behavior.

    The intrinsics are further categorized by their functional domain, including:

    • Vector loads and stores
    • Vector loads and stores (segment)
    • Vector integer arithmetic
    • Vector fixed-point arithmetic
    • Vector floating-point arithmetic
    • Vector reduction operations
    • Vector mask intrinsics
    • Vector permutation intrinsics
    • Miscellaneous vector utility intrinsics
  7. Use Zvfbfa extension for BF16 vector compute

    main

    The Zvfbfa extension provides additional support for bfloat16 (BF16) vector computations in RISC-V. It includes a variety of fused multiply-add (FMA) and multiply-subtract (FMS) operations, supporting different register grouping patterns (LMUL) such as m1, m2, m4, m8, and fractional LMULs like mf2 and mf4.

    Key operation types include:

    • FMA (Fused Multiply-Add): vfmacc, vfmadd
    • FMS (Fused Multiply-Subtract): vfmsac, vfmsub, vfnmsub
    • FNMA (Fused Negative Multiply-Add): vfnmacc, vfnmadd
    • FNMS (Fused Negative Multiply-Subtract): vfnmsac, vfnmsub

    Operations are available in two primary forms:

    • Vector-Vector (vv): Operates on two vector registers (vs1, vs2).
    • Vector-Scalar (vf): Operates on one vector register (vs2) and one scalar BF16 value (rs1).

    All functions support masking via a mask register vm and require a vector length vl and floating-point rounding mode frm.

  8. Understand RVV Tuple Types and NFIELD restrictions

    main

    RVV intrinsic types can be organized into tuples using NFIELD (number of fields). These tuple types are used with segment load/store intrinsics and can be manipulated using vget and vset pseudo-intrinsics.

    Key Constraints:

    • The combination of LMUL (element multiplier) and NFIELD must follow the RVV specification: EMUL * NFIELDS ≤ 8.
    • Tuple types are available only if their corresponding non-tuple (NFIELD=1) types are available.
    • vget and vset require the index to be a compile-time constant.

    Tuple Type Availability by EMUL:

    • EMUL=1/8: Supports up to NFIELD=8.
    • EMUL=1/4: Supports up to NFIELD=8.
    • EMUL=1/2: Supports up to NFIELD=8.
    • EMUL=1: Supports up to NFIELD=8.
    • EMUL=2: Supports up to NFIELD=4.
    • EMUL=4: Supports up to NFIELD=2.
  9. Control Floating-Point Rounding Mode

    main

    Floating-point intrinsics support two modes:

    1. Implicit FP rounding mode: Uses the default rounding mode (when FENV_ACCESS is off) or the fenv dynamic rounding mode (when FENV_ACCESS is on).
    2. Explicit FP rounding mode: Uses an explicit frm argument. These intrinsics are suffixed with _rm. The frm argument must be a constant integer expression from the __RISCV_FRM enum.

    Note: Explicit frm intrinsics are intended for use when FENV_ACCESS is off to allow for more aggressive compiler optimization.

    enum __RISCV_FRM {
      __RISCV_FRM_RNE = 0,
      __RISCV_FRM_RTZ = 1,
      __RISCV_FRM_RDN = 2,
      __RISCV_FRM_RUP = 3,
      __RISCV_FRM_RMM = 4,
    };
  10. Check availability of vector crypto intrinsics

    main

    The availability of vector crypto instruction intrinsics is determined by the minimum vector length specified by the Zvl*b sub-extension in the architecture. To use a specific intrinsic, the hardware must support a minimum vector length that is at least one Element Group Width (EGW) long for the operation being performed.

    For example, the intrinsic __riscv_vaesdf_vs_u32m4 operates on a single element group provided from vs2. Since it uses vuint32mf2_t, the vector length must be at least 128 bits. Consequently, this intrinsic requires the zvl256b extension to be available.

    vuint32m4_t __riscv_vaesdf_vs_u32m4 (vuint32m4_t vd, vuint32mf2_t vs2, size_t vl);