FPU Functions

group NMSIS_Core_FPU_Functions

Functions that related to the RISC-V FPU (F and D extension).

Nuclei provided floating point unit by RISC-V F and D extension.

  • F extension adds single-precision floating-point computational instructions compliant with the IEEE 754-2008 arithmetic standard, __RISCV_FLEN = 32. The F extension adds 32 floating-point registers, f0-f31, each 32 bits wide, and a floating-point control and status register fcsr, which contains the operating mode and exception status of the floating-point unit.

  • D extension adds double-precision floating-point computational instructions compliant with the IEEE 754-2008 arithmetic standard. The D extension widens the 32 floating-point registers, f0-f31, to 64 bits, __RISCV_FLEN = 64

Defines

__RISCV_FLEN 64
__get_FCSR() __RV_CSR_READ(CSR_FCSR)

Get FCSR CSR Register.

__set_FCSR(val) __RV_CSR_WRITE(CSR_FCSR, (val))

Set FCSR CSR Register with val.

__get_FRM() __RV_CSR_READ(CSR_FRM)

Get FRM CSR Register.

__set_FRM(val) __RV_CSR_WRITE(CSR_FRM, (val))

Set FRM CSR Register with val.

__get_FFLAGS() __RV_CSR_READ(CSR_FFLAGS)

Get FFLAGS CSR Register.

__set_FFLAGS(val) __RV_CSR_WRITE(CSR_FFLAGS, (val))

Set FFLAGS CSR Register with val.

__enable_FPU()

Enable FPU Unit, and set state to initial.

__disable_FPU() __RV_CSR_CLEAR(CSR_MSTATUS, MSTATUS_FS)

Disable FPU Unit.

  • We can save power by disable FPU Unit.

  • When FPU Unit is disabled, any access to FPU related CSR registers and FPU instructions will cause illegal Instuction Exception.

__RV_FLW(freg, addr, ofs)

Load a single-precision value from memory into float point register freg using flw instruction.

The FLW instruction loads a single-precision floating point value from memory address (addr + ofs) into floating point register freg(f0-f31)

Remark

  • FLW and FSW operations need to make sure the address is 4 bytes aligned, otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)

  • FLW and FSW do not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved

Parameters
  • freg[in] The floating point register, eg. FREG(0), f0

  • addr[in] The memory base address, 4 byte aligned required

  • ofs[in] a 12-bit immediate signed byte offset value, should be an const value

__RV_FSW(freg, addr, ofs)

Store a single-precision value from float point freg into memory using fsw instruction.

The FSW instruction stores a single-precision value from floating point register to memory

Remark

  • FLW and FSW operations need to make sure the address is 4 bytes aligned, otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)

  • FLW and FSW do not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved

Parameters
  • freg[in] The floating point register(f0-f31), eg. FREG(0), f0

  • addr[in] The memory base address, 4 byte aligned required

  • ofs[in] a 12-bit immediate signed byte offset value, should be an const value

__RV_FLD(freg, addr, ofs)

Load a double-precision value from memory into float point register freg using fld instruction.

The FLD instruction loads a double-precision floating point value from memory address (addr + ofs) into floating point register freg(f0-f31)

Remark

  • FLD and FSD operations need to make sure the address is 8 bytes aligned, otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)

  • FLD and FSD do not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved.

Attention

  • Function only available for double precision floating point unit, FLEN = 64

Parameters
  • freg[in] The floating point register, eg. FREG(0), f0

  • addr[in] The memory base address, 8 byte aligned required

  • ofs[in] a 12-bit immediate signed byte offset value, should be an const value

__RV_FSD(freg, addr, ofs)

Store a double-precision value from float point freg into memory using fsd instruction.

The FSD instruction stores double-precision value from floating point register to memory

Remark

  • FLD and FSD operations need to make sure the address is 8 bytes aligned, otherwise it will cause exception code 4(Load address misaligned) or 6 (Store/AMO address misaligned)

  • FLD and FSD do not modify the bits being transferred; in particular, the payloads of non-canonical NaNs are preserved.

Attention

  • Function only available for double precision floating point unit, FLEN = 64

Parameters
  • freg[in] The floating point register(f0-f31), eg. FREG(0), f0

  • addr[in] The memory base address, 8 byte aligned required

  • ofs[in] a 12-bit immediate signed byte offset value, should be an const value

__RV_FLOAD __RV_FLD

Load a float point value from memory into float point register freg using flw/fld instruction.

  • For Single-Precison Floating-Point Mode(__FPU_PRESENT == 1, __RISCV_FLEN == 32): It will call __RV_FLW to load a single-precision floating point value from memory to floating point register

  • For Double-Precison Floating-Point Mode(__FPU_PRESENT == 2, __RISCV_FLEN == 64): It will call __RV_FLD to load a double-precision floating point value from memory to floating point register

Attention

Function behaviour is different for __FPU_PRESENT = 1 or 2, please see the real function this macro represent

__RV_FSTORE __RV_FSD

Store a float value from float point freg into memory using fsw/fsd instruction.

  • For Single-Precison Floating-Point Mode(__FPU_PRESENT == 1, __RISCV_FLEN == 32): It will call __RV_FSW to store floating point register into memory

  • For Double-Precison Floating-Point Mode(__FPU_PRESENT == 2, __RISCV_FLEN == 64): It will call __RV_FSD to store floating point register into memory

Attention

Function behaviour is different for __FPU_PRESENT = 1 or 2, please see the real function this macro represent

SAVE_FPU_CONTEXT()

Save FPU context into variables for interrupt nesting.

This macro is used to declare variables which are used for saving FPU context, and it will store the nessary fpu registers into these variables, it need to be used in a interrupt when in this interrupt fpu registers are used.

Remark

  • It need to be used together with RESTORE_FPU_CONTEXT

  • Don’t use variable names __fpu_context in your ISR code

  • If you isr code will use fpu registers, and this interrupt is nested. Then you can do it like this:

    void eclic_mtip_handler(void)
    {
        // !!!Interrupt is enabled here!!!
        // !!!Higher priority interrupt could nest it!!!
    
        // Necessary only when you need to use fpu registers
        // in this isr handler functions
        SAVE_FPU_CONTEXT();
    
        // put you own interrupt handling code here
    
        // pair of SAVE_FPU_CONTEXT()
        RESTORE_FPU_CONTEXT();
    }
    

RESTORE_FPU_CONTEXT()

Restore necessary fpu registers from variables for interrupt nesting.

This macro is used restore necessary fpu registers from pre-defined variables in SAVE_FPU_CONTEXT macro.

Remark

Typedefs

typedef uint64_t rv_fpu_t

Type of FPU register, depends on the FLEN defined in RISC-V.