From 63f83901ef95cf6520d1da54b1c9ea0bf7fa76d1 Mon Sep 17 00:00:00 2001 From: Michael Rogenmoser Date: Thu, 16 Feb 2023 13:53:16 +0100 Subject: [PATCH] Add SW for DMR critical section --- include/archi/hmr/hmr_v1.h | 2 +- include/hal/hmr/hmr_v1.h | 16 +++ kernel/cluster.c | 2 +- kernel/crt0.S | 2 +- kernel/hmr_synch.c | 268 ++++++++++++++++++++++++++++++++++++- 5 files changed, 280 insertions(+), 10 deletions(-) diff --git a/include/archi/hmr/hmr_v1.h b/include/archi/hmr/hmr_v1.h index ec4f2d7..7a4e0bf 100644 --- a/include/archi/hmr/hmr_v1.h +++ b/include/archi/hmr/hmr_v1.h @@ -137,7 +137,7 @@ extern "C" { // DMR configuration enable. #define HMR_DMR_REGS_DMR_ENABLE_REG_OFFSET 0x0 -#define HMR_DMR_REGS_DMR_ENABLE_TMR_ENABLE_BIT 0 +#define HMR_DMR_REGS_DMR_ENABLE_DMR_ENABLE_BIT 0 // DMR configuration bits. #define HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET 0x4 diff --git a/include/hal/hmr/hmr_v1.h b/include/hal/hmr/hmr_v1.h index c184809..06cada6 100644 --- a/include/hal/hmr/hmr_v1.h +++ b/include/hal/hmr/hmr_v1.h @@ -53,6 +53,8 @@ void pos_hmr_tmr_irq(); void pos_hmr_tmr_synch(); +void pos_hmr_dmr_synch(); +void pos_hmr_synch(); static inline unsigned int hmr_get_available_config(unsigned int cid) { return pulp_read32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TOP_OFFSET + HMR_REGISTERS_AVAIL_CONFIG_REG_OFFSET); @@ -90,6 +92,10 @@ static inline void hmr_disable_all_dmr(unsigned int cid) { hmr_set_dmr_status_all(cid, 0); } +static inline void hmr_disable_dmr(unsigned int cid, unsigned int dmr_id) { + pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_DMR_OFFSET + HMR_DMR_INCREMENT*dmr_id + HMR_DMR_REGS_DMR_ENABLE_REG_OFFSET, 0); +} + static inline void hmr_set_dmr_config(unsigned int cid, unsigned int dmr_id, bool rapid_recovery) { pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_DMR_OFFSET + HMR_DMR_INCREMENT*dmr_id + HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET, (rapid_recovery ? 1< this should lock the cores together + // eu_bar_trig_wait_clr(eu_bar_addr(TMR_BARRIER_ID(TMR_GROUP_ID(core_id())))); + __asm__ __volatile__( + // if not a tmr core, check dmr + "li t1, " QU(LOCAL_NUM_TMR_CORES) " \n\t" + "bgeu t0, t1, pos_hmr_dmr_barrier \n" + + // read tmr register of the core + "slli t1, t1, " QU(HMR_TMR_SLL) " \n\t" + "li t2, " QU(ARCHI_HMR_ADDR + HMR_TMR_OFFSET) " \n\t" // t1 is tmr base address + "add t1, t1, t2 \n\t" + "lw t2, " QU(HMR_TMR_REGS_TMR_ENABLE_REG_OFFSET) "(t1) \n\t" + + // if tmr is not intended, pos_hmr_dmr_barrier() + "beq t2, zero, pos_hmr_dmr_barrier \n\t" + + "pos_hmr_tmr_barrier: \n\t" +#if HMR_IN_INTERLEAVED // t1 is barrier id + "li t1, " QU(NUM_TMR_GROUPS) " \n\t" + "remu t1, t0, t1 \n\t" + "addi t1, t1, 1 \n\t" +#else + "li t1, 3 \n\t" + "divu t1, t0, t1 \n\t" + "srli t2, t1, 1 \n\t" + "addi t1, t1, 1 \n\t" + "add t1, t1, t2 \n\t" +#endif // t1 is barrier id + "j pos_hmr_barrier \n" + + "pos_hmr_dmr_barrier: \n\t" +#if HMR_IN_INTERLEAVED // t1 is barrier id + "li t1, " QU(NUM_DMR_GROUPS) " \n\t" + "remu t1, t0, t1 \n\t" + "addi t1, t1, 1 \n" +#else + "srli t1, t0, 1 \n\t" + "addi t1, t1, 1 \n" +#endif + + "pos_hmr_barrier: \n\t" + "sll t1, t1, " QU(EU_BARRIER_SIZE_LOG2) " \n\t" + "li t2, " QU(ARCHI_EU_DEMUX_ADDR + EU_BARRIER_DEMUX_OFFSET) " \n\t" // t1 is tmr base address + "add t1, t1, t2 \n\t" + "p.elw zero, " QU(EU_HW_BARR_TRIGGER_WAIT_CLEAR) "(t1) \n\t" // barrier + : : : "memory"); + + + // several nops to delay and allow for core reset + __asm__ __volatile__( + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + : : : "memory"); + + pos_hmr_sw_reload(); } void __attribute__((naked)) pos_hmr_tmr_synch() { - pos_hmr_store_state_to_stack(); + pos_hmr_store_part_to_stack(); + pos_hmr_store_rest_to_stack(); // store sp to hmr core reg __asm__ __volatile__( @@ -229,7 +439,37 @@ void __attribute__((naked)) pos_hmr_tmr_synch() { "nop\n\t" : : : "memory"); - pos_hmr_tmr_reload(); + pos_hmr_sw_reload(); +} + + +void __attribute__((naked)) pos_hmr_dmr_synch() { + pos_hmr_store_part_to_stack(); + pos_hmr_store_rest_to_stack(); + + // store sp to hmr core reg + __asm__ __volatile__( + "csrr t0, 0xf14 \n\t" // Read core id + "li t1, " QU(ARCHI_HMR_ADDR + HMR_CORE_OFFSET) " \n\t" + "andi t0, t0, 0x01f \n\t" + "sll t0, t0, " QU(HMR_CORE_SLL) " \n\t" + "add t0, t0, t1 \n\t" + "sw sp, " QU(HMR_CORE_REGS_SP_STORE_REG_OFFSET) "(t0) \n\t" + : : : "memory"); + + // enter barrier -> this should lock the cores together + eu_bar_trig_wait_clr(eu_bar_addr(DMR_BARRIER_ID(DMR_GROUP_ID(core_id())))); + + // several nops to delay and allow for core reset + __asm__ __volatile__( + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + : : : "memory"); + + pos_hmr_sw_reload(); } int hmr_tmr_critical_section(int (*function_handle)()) { @@ -249,6 +489,20 @@ int hmr_tmr_critical_section(int (*function_handle)()) { return ret; } +int hmr_dmr_critical_section(int (*function_handle)()) { + int ret = 0; + if (DMR_IS_MAIN_CORE(core_id())) { + // enter critical section + hmr_self_enable_dmr(); + + // do critical stuff + ret += function_handle(); + + // exit critical section + hmr_disable_dmr(0, DMR_GROUP_ID(core_id())); + } +} + // void pos_hmr_tmr_unsync() { // // Update event unit mask