Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Vector context save support on RISC-V #1260

Merged
merged 4 commits into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/.cSpellWords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,7 @@ SHPR
SHTIM
SIFIVE
sinclude
slli
SODR
SOFTIRQ
SPCK
Expand Down Expand Up @@ -937,6 +938,7 @@ USRIO
utest
utilises
utilising
vcsr
VDDCORE
vect
Vect
Expand All @@ -947,13 +949,15 @@ visualisation
vldmdbeq
vldmia
vldmiaeq
vlenb
VMSRNE
vpop
VPOPNE
vpush
VPUSHNE
VRPM
Vrtc
vsetvl
vstmdbeq
vstmiaeq
VTOR
Expand Down
9 changes: 9 additions & 0 deletions portable/GCC/RISC-V/portASM.S
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ definitions. */
* x6
* x5
* portTASK_RETURN_ADDRESS
* [VPU registers (when enabled/available) go here]
* [FPU registers (when enabled/available) go here]
* [chip specific registers go here]
* mstatus
Expand Down Expand Up @@ -233,6 +234,14 @@ chip_specific_stack_frame: /* First add any chip specific registers
or t0, t0, t1
#endif

#if( configENABLE_VPU == 1 )
/* Mark the VPU as clean in the mstatus value. */
li t1, ~MSTATUS_VS_MASK
and t0, t0, t1
li t1, MSTATUS_VS_CLEAN
or t0, t0, t1
#endif

addi a0, a0, -portWORD_SIZE
store_x t0, 0(a0) /* mstatus onto the stack. */

Expand Down
116 changes: 115 additions & 1 deletion portable/GCC/RISC-V/portContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#define configENABLE_FPU 0
#endif

#ifndef configENABLE_VPU
#define configENABLE_VPU 0
#endif

#if __riscv_xlen == 64
#define portWORD_SIZE 8
#define store_x sd
Expand Down Expand Up @@ -90,7 +94,25 @@
#define portFPU_REG_OFFSET( regIndex ) ( ( 2 * portWORD_SIZE ) + ( regIndex * portFPU_REG_SIZE ) )
#define portFPU_CONTEXT_SIZE ( portFPU_REG_SIZE * portFPU_REG_COUNT )
#else
#error configENABLE_FPU must not be set to 1 if the hardwar does not have FPU
#error configENABLE_FPU must not be set to 1 if the hardware does not have FPU
#endif
#endif

#if ( configENABLE_VPU == 1 )
/* Bit [10:9] in the mstatus encode the status of VPU state which is one of
* the following values:
* 1. Value: 0, Meaning: Off.
* 2. Value: 1, Meaning: Initial.
* 3. Value: 2, Meaning: Clean.
* 4. Value: 3, Meaning: Dirty.
*/
#define MSTATUS_VS_MASK 0x600
#define MSTATUS_VS_INITIAL 0x200
#define MSTATUS_VS_CLEAN 0x400
#define MSTATUS_VS_DIRTY 0x600
#define MSTATUS_VS_OFFSET 9
#ifndef __riscv_vector
#error configENABLE_VPU must not be set to 1 if the hardware does not have VPU
#endif
#endif
/*-----------------------------------------------------------*/
Expand Down Expand Up @@ -181,6 +203,61 @@ addi sp, sp, ( portFPU_CONTEXT_SIZE )
.endm
/*-----------------------------------------------------------*/

.macro portcontexSAVE_VPU_CONTEXT
/* Store the vector registers on groups of 8. Use the length in bytes (vlenb)
to know how much space they need and reserve it in the stack. */
csrr t0, vlenb
slli t0, t0, 3 /* vlenb * 8 */
neg t0, t0
/* Store the vector registers. */
add sp, sp, t0
vs8r.v v0, (sp)
add sp, sp, t0
vs8r.v v8, (sp)
add sp, sp, t0
vs8r.v v16, (sp)
add sp, sp, t0
vs8r.v v24, (sp)
/* Store the VPU registers. */
addi sp, sp, -( 4 * portWORD_SIZE )
csrr t0, vstart
store_x t0, 0 * portWORD_SIZE( sp )
csrr t0, vcsr
store_x t0, 1 * portWORD_SIZE( sp )
csrr t0, vl
store_x t0, 2 * portWORD_SIZE( sp )
csrr t0, vtype
store_x t0, 3 * portWORD_SIZE( sp )
.endm
/*-----------------------------------------------------------*/

.macro portcontextRESTORE_VPU_CONTEXT
/* Restore the VPU registers. */
load_x t0, 0 * portWORD_SIZE( sp )
csrw vstart, t0
load_x t0, 1 * portWORD_SIZE( sp )
csrw vcsr, t0
load_x t0, 2 * portWORD_SIZE( sp )
load_x t1, 3 * portWORD_SIZE( sp )
/* vlen and vtype can only be updated by using vset*vl* instructions. */
vsetvl x0, t0, t1
addi sp, sp, ( 4 * portWORD_SIZE )
/* Load the vector registers on groups of 8. Use the length in bytes (vlenb)
to know how much space they use. */
csrr t0, vlenb
slli t0, t0, 3 /* vlenb * 8 */
/* Restore the vector registers. */
vl8r.v v24, (sp)
add sp, sp, t0
vl8r.v v16, (sp)
add sp, sp, t0
vl8r.v v8, (sp)
add sp, sp, t0
vl8r.v v0, (sp)
add sp, sp, t0
.endm
/*-----------------------------------------------------------*/

.macro portcontextSAVE_CONTEXT_INTERNAL
addi sp, sp, -portCONTEXT_SIZE
store_x x1, 2 * portWORD_SIZE( sp )
Expand Down Expand Up @@ -228,6 +305,17 @@ store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the criti
1:
#endif

#if( configENABLE_VPU == 1 )
csrr t0, mstatus
srl t1, t0, MSTATUS_VS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 1f /* If VPU status is not dirty, do not save FPU registers. */

portcontexSAVE_VPU_CONTEXT
1:
#endif

portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */

csrr t0, mstatus
Expand All @@ -248,6 +336,21 @@ store_x t0, 1 * portWORD_SIZE( sp )
2:
#endif

#if( configENABLE_VPU == 1 )
/* Mark the VPU as clean, if it was dirty and we saved VPU registers. */
srl t1, t0, MSTATUS_VS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 2f

li t1, ~MSTATUS_VS_MASK
and t0, t0, t1
li t1, MSTATUS_VS_CLEAN
or t0, t0, t1
csrw mstatus, t0
2:
#endif

load_x t0, pxCurrentTCB /* Load pxCurrentTCB. */
store_x sp, 0 ( t0 ) /* Write sp to first TCB member. */

Expand Down Expand Up @@ -288,6 +391,17 @@ csrw mstatus, t0
/* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
portasmRESTORE_ADDITIONAL_REGISTERS

#if( configENABLE_VPU == 1 )
csrr t0, mstatus
srl t1, t0, MSTATUS_VS_OFFSET
andi t1, t1, 3
addi t2, x0, 3
bne t1, t2, 3f /* If VPU status is not dirty, do not restore VPU registers. */

portcontextRESTORE_VPU_CONTEXT
3:
#endif /* ifdef portasmSTORE_VPU_CONTEXT */

#if( configENABLE_FPU == 1 )
csrr t0, mstatus
srl t1, t0, MSTATUS_FS_OFFSET
Expand Down
Loading