3333 #define configENABLE_FPU 0
3434#endif
3535
36+ #ifndef configENABLE_VPU
37+ #define configENABLE_VPU 0
38+ #endif
39+
3640#if __riscv_xlen == 64
3741 #define portWORD_SIZE 8
3842 #define store_x sd
9094 #define portFPU_REG_OFFSET ( regIndex ) ( ( 2 * portWORD_SIZE ) + ( regIndex * portFPU_REG_SIZE ) )
9195 #define portFPU_CONTEXT_SIZE ( portFPU_REG_SIZE * portFPU_REG_COUNT )
9296 #else
93- #error configENABLE_FPU must not be set to 1 if the hardwar does not have FPU
97+ #error configENABLE_FPU must not be set to 1 if the hardware does not have FPU
98+ #endif
99+ #endif
100+
101+ #if ( configENABLE_VPU == 1 )
102+ /* Bit [10:9] in the mstatus encode the status of VPU state which is one of
103+ * the following values:
104+ * 1. Value: 0, Meaning: Off.
105+ * 2. Value: 1, Meaning: Initial.
106+ * 3. Value: 2, Meaning: Clean.
107+ * 4. Value: 3, Meaning: Dirty.
108+ */
109+ #define MSTATUS_VS_MASK 0x600
110+ #define MSTATUS_VS_INITIAL 0x200
111+ #define MSTATUS_VS_CLEAN 0x400
112+ #define MSTATUS_VS_DIRTY 0x600
113+ #define MSTATUS_VS_OFFSET 9
114+ #ifndef __riscv_vector
115+ #error configENABLE_VPU must not be set to 1 if the hardware does not have VPU
94116 #endif
95117#endif
96118/*-----------------------------------------------------------*/
@@ -181,6 +203,61 @@ addi sp, sp, ( portFPU_CONTEXT_SIZE )
181203 .endm
182204/*-----------------------------------------------------------*/
183205
206+ .macro portcontexSAVE_VPU_CONTEXT
207+ /* Store the vector registers on groups of 8. Use the length in bytes (vlenb)
208+ to know how much space they need and reserve it in the stack. */
209+ csrr t0 , vlenb
210+ slli t0 , t0 , 3 /* vlenb * 8 */
211+ neg t0 , t0
212+ /* Store the vector registers. */
213+ add sp , sp , t0
214+ vs8r .v v0 , (sp )
215+ add sp , sp , t0
216+ vs8r .v v8 , (sp )
217+ add sp , sp , t0
218+ vs8r .v v16 , (sp )
219+ add sp , sp , t0
220+ vs8r .v v24 , (sp )
221+ /* Store the VPU registers. */
222+ addi sp , sp , - ( 4 * portWORD_SIZE )
223+ csrr t0 , vstart
224+ store_x t0 , 0 * portWORD_SIZE ( sp )
225+ csrr t0 , vcsr
226+ store_x t0 , 1 * portWORD_SIZE ( sp )
227+ csrr t0 , vl
228+ store_x t0 , 2 * portWORD_SIZE ( sp )
229+ csrr t0 , vtype
230+ store_x t0 , 3 * portWORD_SIZE ( sp )
231+ .endm
232+ /*-----------------------------------------------------------*/
233+
234+ .macro portcontextRESTORE_VPU_CONTEXT
235+ /* Restore the VPU registers. */
236+ load_x t0 , 0 * portWORD_SIZE ( sp )
237+ csrw vstart , t0
238+ load_x t0 , 1 * portWORD_SIZE ( sp )
239+ csrw vcsr , t0
240+ load_x t0 , 2 * portWORD_SIZE ( sp )
241+ load_x t1 , 3 * portWORD_SIZE ( sp )
242+ /* vlen and vtype can only be updated by using vset*vl* instructions. */
243+ vsetvl x0 , t0 , t1
244+ addi sp , sp , ( 4 * portWORD_SIZE )
245+ /* Load the vector registers on groups of 8. Use the length in bytes (vlenb)
246+ to know how much space they use. */
247+ csrr t0 , vlenb
248+ slli t0 , t0 , 3 /* vlenb * 8 */
249+ /* Restore the vector registers. */
250+ vl8r .v v24 , (sp )
251+ add sp , sp , t0
252+ vl8r .v v16 , (sp )
253+ add sp , sp , t0
254+ vl8r .v v8 , (sp )
255+ add sp , sp , t0
256+ vl8r .v v0 , (sp )
257+ add sp , sp , t0
258+ .endm
259+ /*-----------------------------------------------------------*/
260+
184261 .macro portcontextSAVE_CONTEXT_INTERNAL
185262addi sp , sp , - portCONTEXT_SIZE
186263store_x x1 , 2 * portWORD_SIZE ( sp )
@@ -228,6 +305,17 @@ store_x t0, portCRITICAL_NESTING_OFFSET * portWORD_SIZE( sp ) /* Store the criti
2283051 :
229306#endif
230307
308+ #if ( configENABLE_VPU == 1 )
309+ csrr t0 , mstatus
310+ srl t1 , t0 , MSTATUS_VS_OFFSET
311+ andi t1 , t1 , 3
312+ addi t2 , x0 , 3
313+ bne t1 , t2 , 1f /* If VPU status is not dirty, do not save FPU registers. */
314+
315+ portcontexSAVE_VPU_CONTEXT
316+ 1 :
317+ #endif
318+
231319portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */
232320
233321csrr t0 , mstatus
@@ -248,6 +336,21 @@ store_x t0, 1 * portWORD_SIZE( sp )
2483362 :
249337#endif
250338
339+ #if ( configENABLE_VPU == 1 )
340+ /* Mark the VPU as clean, if it was dirty and we saved VPU registers. */
341+ srl t1 , t0 , MSTATUS_VS_OFFSET
342+ andi t1 , t1 , 3
343+ addi t2 , x0 , 3
344+ bne t1 , t2 , 2f
345+
346+ li t1 , ~MSTATUS_VS_MASK
347+ and t0 , t0 , t1
348+ li t1 , MSTATUS_VS_CLEAN
349+ or t0 , t0 , t1
350+ csrw mstatus , t0
351+ 2 :
352+ #endif
353+
251354load_x t0 , pxCurrentTCB /* Load pxCurrentTCB. */
252355store_x sp , 0 ( t0 ) /* Write sp to first TCB member. */
253356
@@ -288,6 +391,17 @@ csrw mstatus, t0
288391/* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */
289392portasmRESTORE_ADDITIONAL_REGISTERS
290393
394+ #if ( configENABLE_VPU == 1 )
395+ csrr t0 , mstatus
396+ srl t1 , t0 , MSTATUS_VS_OFFSET
397+ andi t1 , t1 , 3
398+ addi t2 , x0 , 3
399+ bne t1 , t2 , 3f /* If VPU status is not dirty, do not restore VPU registers. */
400+
401+ portcontextRESTORE_VPU_CONTEXT
402+ 3 :
403+ #endif /* ifdef portasmSTORE_VPU_CONTEXT */
404+
291405#if ( configENABLE_FPU == 1 )
292406 csrr t0 , mstatus
293407 srl t1 , t0 , MSTATUS_FS_OFFSET
0 commit comments