pulp-runtime/include/hal/hmr/hmr_v1.h
2023-10-30 22:15:17 +01:00

210 lines
10 KiB
C

/*
* Copyright (C) 2023 ETH Zurich and University of Bologna
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __HAL_HMR_HMR_V1_H__
#define __HAL_HMR_HMR_V1_H__
#include "archi/hmr/hmr_v1.h"
#include "archi/pulp.h"
#include <stdbool.h>
#define NUM_TMR_GROUPS (ARCHI_CLUSTER_NB_PE/3)
#define NUM_TMR_CORES (ARCHI_CLUSTER_NB_PE-(ARCHI_CLUSTER_NB_PE%3))
#define NUM_DMR_GROUPS (ARCHI_CLUSTER_NB_PE/2)
#define NUM_DMR_CORES (ARCHI_CLUSTER_NB_PE-(ARCHI_CLUSTER_NB_PE%2))
// Interleaved cores
#define TMR_IS_CORE(core_id) (core_id<NUM_TMR_CORES)
#define DMR_IS_CORE(core_id) (core_id<NUM_DMR_CORES)
#if HMR_IN_INTERLEAVED
#define TMR_GROUP_ID(core_id) (core_id % NUM_TMR_GROUPS)
#define TMR_CORE_ID(group_id, offset) (group_id + (offset * NUM_TMR_GROUPS))
#define TMR_BARRIER_ID(group_id) (1+group_id)
#define TMR_BARRIER_SETUP(group_id) (1<<group_id | 1<<(group_id+NUM_TMR_GROUPS) | 1<<(group_id+2*NUM_TMR_GROUPS))
#define DMR_GROUP_ID(core_id) (core_id % NUM_DMR_GROUPS)
#define DMR_CORE_ID(group_id, offset) (group_id + (offset * NUM_DMR_GROUPS))
#define DMR_BARRIER_ID(group_id) (1+group_id)
#define DMR_BARRIER_SETUP(group_id) (1<<group_id | 1<<(group_id+NUM_DMR_GROUPS))
#else
#define TMR_GROUP_ID(core_id) (core_id/3)
#define TMR_CORE_ID(group_id, offset) ((group_id * 3) + core_offset)
#define TMR_BARRIER_ID(group_id) (1+group_id+(group_id/2))
#define TMR_BARRIER_SETUP(group_id) (1<<(3*group_id) | 1<<(3*group_id + 1) | 1<<(3*group_id+2))
#define DMR_GROUP_ID(core_id) (core_id/2)
#define DMR_CORE_ID(group_id, offset) ((group_id * 2) + core_offset)
#define DMR_BARRIER_ID(group_id) (1+group_id)
#define DMR_BARRIER_SETUP(group_id) (1<<(2*group_id) | 1<<(2*group_id + 1))
#endif
#define TMR_IS_MAIN_CORE(core_id) (TMR_IS_CORE(core_id) && (TMR_CORE_ID(TMR_GROUP_ID(core_id), 0) == core_id))
#define DMR_IS_MAIN_CORE(core_id) (DMR_IS_CORE(core_id) && (DMR_CORE_ID(DMR_GROUP_ID(core_id), 0) == core_id))
void pos_hmr_tmr_irq();
void pos_hmr_synch();
/* Allows for setting up proper barriers depending on available cores */
static void hmr_setup_barrier(unsigned int num_avail_cores){
eu_bar_setup(eu_bar_addr(0), num_avail_cores);
}
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);
}
static inline unsigned int hmr_get_active_cores(unsigned int cid) {
return pulp_read32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TOP_OFFSET + HMR_REGISTERS_CORES_EN_REG_OFFSET);
}
static inline unsigned int hmr_get_core_status(unsigned int cid, unsigned int core_id) {
return pulp_read32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_CORE_OFFSET + (core_id * HMR_CORE_INCREMENT) + HMR_CORE_REGS_CURRENT_MODE_REG_OFFSET);
}
static inline unsigned int hmr_get_core_mismatches(unsigned int cid, unsigned int core_id) {
return pulp_read32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_CORE_OFFSET + (core_id * HMR_CORE_INCREMENT) + HMR_CORE_REGS_MISMATCHES_REG_OFFSET);
}
static inline unsigned int hmr_reset_core_mismatches(unsigned int cid, unsigned int core_id) {
return pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_CORE_OFFSET + (core_id * HMR_CORE_INCREMENT) + HMR_CORE_REGS_MISMATCHES_REG_OFFSET, 0);
}
static inline unsigned int hmr_get_dmr_status_all(unsigned int cid) {
return pulp_read32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TOP_OFFSET + HMR_REGISTERS_DMR_ENABLE_REG_OFFSET);
}
static inline void hmr_set_dmr_status_all(unsigned int cid, unsigned int status) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TOP_OFFSET + HMR_REGISTERS_DMR_ENABLE_REG_OFFSET, status);
}
static inline void hmr_enable_all_dmr(unsigned int cid) {
hmr_set_dmr_status_all(cid, (1<<NUM_DMR_GROUPS)-1);
}
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, bool setback, bool synch_req) {
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<<HMR_DMR_REGS_DMR_CONFIG_RAPID_RECOVERY_BIT : 0) |
(setback ? 1<<HMR_DMR_REGS_DMR_CONFIG_SETBACK_BIT : 0) |
(synch_req ? 1<<HMR_DMR_REGS_DMR_CONFIG_SYNCH_REQ_BIT : 0));
}
static inline void hmr_set_dmr_config_all(unsigned int cid, bool rapid_recovery, bool setback, bool synch_req) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TOP_OFFSET + HMR_REGISTERS_DMR_CONFIG_REG_OFFSET,
(rapid_recovery ? 1<<HMR_REGISTERS_DMR_CONFIG_RAPID_RECOVERY_BIT : 0) |
(setback ? 1<<HMR_REGISTERS_DMR_CONFIG_SETBACK_BIT : 0) |
(synch_req ? 1<<HMR_REGISTERS_DMR_CONFIG_SYNCH_REQ_BIT : 0));
}
static inline unsigned int hmr_get_dmr_config(unsigned int cid, unsigned int dmr_id) {
return pulp_read32(ARCHI_HMR_GLOBAL_ADDR(0) + HMR_DMR_OFFSET + HMR_DMR_INCREMENT*dmr_id + HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET);
}
static inline void hmr_set_dmr_config_bare(unsigned int cid, unsigned int dmr_id, unsigned int config) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(0) + HMR_DMR_OFFSET + HMR_DMR_INCREMENT*dmr_id + HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET, config);
}
static inline void hmr_force_dmr_resynch(unsigned int cid, unsigned int dmr_id) {
unsigned int config = pulp_read32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_DMR_OFFSET + HMR_DMR_INCREMENT*dmr_id + HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET);
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_DMR_OFFSET + HMR_DMR_INCREMENT*dmr_id + HMR_DMR_REGS_DMR_CONFIG_REG_OFFSET, config | (1<<HMR_DMR_REGS_DMR_CONFIG_FORCE_RECOVERY_BIT));
}
static inline unsigned int hmr_get_tmr_status_all(unsigned int cid) {
return pulp_read32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TOP_OFFSET + HMR_REGISTERS_TMR_ENABLE_REG_OFFSET);
}
static inline void hmr_set_tmr_status_all(unsigned int cid, unsigned int status) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TOP_OFFSET + HMR_REGISTERS_TMR_ENABLE_REG_OFFSET, status);
}
static inline void hmr_enable_all_tmr(unsigned int cid) {
hmr_set_tmr_status_all(cid, (1<<NUM_TMR_GROUPS)-1);
}
static inline void hmr_enable_tmr(unsigned int cid, unsigned int tmr_id) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TMR_OFFSET + HMR_TMR_INCREMENT*tmr_id + HMR_TMR_REGS_TMR_ENABLE_REG_OFFSET, 1<<HMR_TMR_REGS_TMR_ENABLE_TMR_ENABLE_BIT);
}
static inline void hmr_self_enable_tmr() {
if (TMR_IS_MAIN_CORE(core_id())) {
eu_bar_setup(eu_bar_addr(TMR_BARRIER_ID(TMR_GROUP_ID(core_id()))), TMR_BARRIER_SETUP(TMR_GROUP_ID(core_id())));
pulp_write32(ARCHI_HMR_ADDR + HMR_TMR_OFFSET + HMR_TMR_INCREMENT*core_id() + HMR_TMR_REGS_TMR_ENABLE_REG_OFFSET, 1<<HMR_TMR_REGS_TMR_ENABLE_TMR_ENABLE_BIT);
while (hmr_get_core_status(0, core_id()) != 1<<HMR_CORE_REGS_CURRENT_MODE_TRIPLE_BIT) {
asm volatile ("nop");
}
}
}
static inline void hmr_self_enable_dmr() {
if (DMR_IS_MAIN_CORE(core_id())) {
eu_bar_setup(eu_bar_addr(DMR_BARRIER_ID(DMR_GROUP_ID(core_id()))), DMR_BARRIER_SETUP(DMR_GROUP_ID(core_id())));
pulp_write32(ARCHI_HMR_ADDR + HMR_DMR_OFFSET + HMR_DMR_INCREMENT*core_id() + HMR_DMR_REGS_DMR_ENABLE_REG_OFFSET, 1<<HMR_DMR_REGS_DMR_ENABLE_DMR_ENABLE_BIT);
while (hmr_get_core_status(0, core_id()) != 1<<HMR_CORE_REGS_CURRENT_MODE_DUAL_BIT) {
asm volatile ("nop");
}
}
}
static inline void hmr_disable_all_tmr(unsigned int cid) {
hmr_set_tmr_status_all(cid, 0);
}
static inline void hmr_disable_tmr(unsigned int cid, unsigned int tmr_id) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TMR_OFFSET + HMR_TMR_INCREMENT*tmr_id + HMR_TMR_REGS_TMR_ENABLE_REG_OFFSET, 0);
}
static inline void hmr_set_tmr_config(unsigned int cid, unsigned int tmr_id, bool delay_resynch, bool setback, bool reload_setback, bool rapid_recovery, bool synch_req) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(0) + HMR_TMR_OFFSET + HMR_TMR_INCREMENT*tmr_id + HMR_TMR_REGS_TMR_CONFIG_REG_OFFSET,
(delay_resynch ? 1<<HMR_TMR_REGS_TMR_CONFIG_DELAY_RESYNCH_BIT : 0) |
(setback ? 1<<HMR_TMR_REGS_TMR_CONFIG_SETBACK_BIT : 0) |
(reload_setback ? 1<<HMR_TMR_REGS_TMR_CONFIG_RELOAD_SETBACK_BIT : 0) |
(rapid_recovery ? 1<<HMR_TMR_REGS_TMR_CONFIG_RAPID_RECOVERY_BIT : 0) |
(synch_req ? 1<<HMR_TMR_REGS_TMR_CONFIG_SYNCH_REQ_BIT : 0));
}
static inline unsigned int hmr_get_tmr_config(unsigned int cid, unsigned int tmr_id) {
return pulp_read32(ARCHI_HMR_GLOBAL_ADDR(0) + HMR_TMR_OFFSET + HMR_TMR_INCREMENT*tmr_id + HMR_TMR_REGS_TMR_CONFIG_REG_OFFSET);
}
static inline void hmr_set_tmr_config_bare(unsigned int cid, unsigned int tmr_id, unsigned int config) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(0) + HMR_TMR_OFFSET + HMR_TMR_INCREMENT*tmr_id + HMR_TMR_REGS_TMR_CONFIG_REG_OFFSET, config);
}
static inline void hmr_set_tmr_config_all(unsigned int cid, bool delay_resynch, bool setback, bool reload_setback, bool rapid_recovery, bool synch_req) {
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(0) + HMR_TOP_OFFSET + HMR_REGISTERS_TMR_CONFIG_REG_OFFSET,
(delay_resynch ? 1<<HMR_REGISTERS_TMR_CONFIG_DELAY_RESYNCH_BIT : 0) |
(setback ? 1<<HMR_REGISTERS_TMR_CONFIG_SETBACK_BIT : 0) |
(reload_setback ? 1<<HMR_REGISTERS_TMR_CONFIG_RELOAD_SETBACK_BIT : 0) |
(rapid_recovery ? 1<<HMR_REGISTERS_TMR_CONFIG_RAPID_RECOVERY_BIT : 0) |
(synch_req ? 1<<HMR_REGISTERS_TMR_CONFIG_SYNCH_REQ_BIT : 0));
}
static inline void hmr_force_tmr_resynch(unsigned int cid, unsigned int tmr_id) {
unsigned int config = pulp_read32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TMR_OFFSET + HMR_TMR_INCREMENT*tmr_id + HMR_TMR_REGS_TMR_CONFIG_REG_OFFSET);
pulp_write32(ARCHI_HMR_GLOBAL_ADDR(cid) + HMR_TMR_OFFSET + HMR_TMR_INCREMENT*tmr_id + HMR_TMR_REGS_TMR_CONFIG_REG_OFFSET, config | (1<<HMR_TMR_REGS_TMR_CONFIG_FORCE_RESYNCH_BIT));
}
static void hmr_tmr_barrier_setup_all() {
for (int i = 0; i < NUM_TMR_GROUPS; i++) {
eu_bar_setup(eu_bar_addr(TMR_BARRIER_ID(i)), TMR_BARRIER_SETUP(i));
}
}
#endif // __HAL_HMR_HMR_V1_H__