FPU Functions

group 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 + FCSR, 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 and FCSR 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.