From 4dc73dcea25d951971ae306481d1f201c8d6ebdd Mon Sep 17 00:00:00 2001 From: Kristofer Jonsson Date: Fri, 16 Oct 2020 12:33:47 +0200 Subject: PMU counter shadow Storing PMU counters in shadow variables, in case the PMU was powered off or soft reset. Change-Id: I64ccf3fb6195f9be2d8315891ec612bb75404885 --- src/ethosu_common.h | 1 - src/ethosu_config.h | 83 ------------------------- src/ethosu_device.c | 52 ++++++++++++---- src/ethosu_driver.c | 9 +-- src/ethosu_pmu.c | 171 +++++++++++++++++++++------------------------------- 5 files changed, 111 insertions(+), 205 deletions(-) (limited to 'src') diff --git a/src/ethosu_common.h b/src/ethosu_common.h index 04acea2..30f07be 100644 --- a/src/ethosu_common.h +++ b/src/ethosu_common.h @@ -24,7 +24,6 @@ ******************************************************************************/ #include "ethosu55_interface.h" -#include "ethosu_device.h" #include diff --git a/src/ethosu_config.h b/src/ethosu_config.h index 91fe660..7a9fae2 100644 --- a/src/ethosu_config.h +++ b/src/ethosu_config.h @@ -116,87 +116,4 @@ #define BASE_POINTER_OFFSET 0 #endif -#ifdef PMU_AUTOINIT -/* - * Register control - * b0 = CNT_EN = Enable counters (RW) - * b1 = EVENT_CNT_RST = Reset event counters (WO) - * b2 = CYCLE_CNT_RST = Reset cycle counter (WO) - * b[15:11] = Number of event counters (RO) - */ -#ifndef INIT_PMCR -#define INIT_PMCR 0x0 -#endif - -/* - * Bit k enables event counter k - * k=31 enables the cycle counter - * Read value is current status - */ -#ifndef INIT_PMCNTENSET -#define INIT_PMCNTENSET 0x0 -#endif - -/* - * Bit k disables event counter k - * k=31 disables the cycle counter - * Read value is current status - */ -#ifndef INIT_PMCNTENCLR -#define INIT_PMCNTENCLR 0x0 -#endif - -/* - * Overflow detection set - * Bit k is for counter k - * k=31 is cycle counter - */ -#ifndef INIT_PMOVSSET -#define INIT_PMOVSSET 0x0 -#endif - -/* - * Overflow detection clear - * Bit k is for counter k - * k=31 is cycle counter - */ -#ifndef INIT_PMOVSCLR -#define INIT_PMOVSCLR 0x0 -#endif - -/* - * Interrupt set - * Bit k is for counter k - * k=31 is cycle counter - */ -#ifndef INIT_PMINTSET -#define INIT_PMINTSET 0x0 -#endif - -/* - * Interrupt clear - * Bit k is for counter k - * k=31 is cycle counter - */ -#ifndef INIT_PMINTCLR -#define INIT_PMINTCLR 0x8003 -#endif - -/* Cycle counter - * 48 bits value - */ -#ifndef INIT_PMCCNTR -#define INIT_PMCCNTR 0x0 -#endif - -/* - * b[9:0] Start Event – this event number starts the cycle counter - * b[25:16] Stop Event – this event number stops the cycle counter - */ -#ifndef INIT_PMCCNTR_CFG -#define INIT_PMCCNTR_CFG 0x0 -#endif - -#endif /* #ifdef PMU_AUTOINIT */ - #endif /* #ifndef ETHOSU_CONFIG_H */ diff --git a/src/ethosu_device.c b/src/ethosu_device.c index 85dc022..8fee3f4 100644 --- a/src/ethosu_device.c +++ b/src/ethosu_device.c @@ -37,7 +37,7 @@ static uint32_t stream_length = 0; enum ethosu_error_codes ethosu_dev_init(struct ethosu_device *dev, const void *base_address) { #if !defined(ARM_NPU_STUB) - dev->base_address = (uintptr_t)base_address; + dev->base_address = (volatile uint32_t *)base_address; ethosu_save_pmu_config(dev); #else UNUSED(dev); @@ -189,12 +189,21 @@ enum ethosu_error_codes ethosu_soft_reset(struct ethosu_device *dev) // Register access not permitted return ETHOSU_GENERIC_FAILURE; } + // Reset and set security level ethosu_write_reg(dev, NPU_REG_RESET, reset.word); + // Wait for reset to complete return_code = ethosu_wait_for_reset(dev); + // Save the proto register dev->reset = ethosu_read_reg(dev, NPU_REG_PROT); + + // Soft reset will clear the PMU configuration and counters. The shadow PMU counters + // are cleared by saving the PMU counters to ram, which will read back zeros. + // The PMU configuration will be restored in the invoke function after power save + // has been disabled. + ethosu_save_pmu_counters(dev); #else UNUSED(dev); #endif @@ -534,8 +543,9 @@ uint32_t ethosu_read_reg(struct ethosu_device *dev, uint32_t address) { #if !defined(ARM_NPU_STUB) ASSERT(dev->base_address != 0); + ASSERT(address % 4 == 0); - volatile uint32_t *reg = (uint32_t *)(uintptr_t)(dev->base_address + address); + volatile uint32_t *reg = dev->base_address + address / sizeof(uint32_t); return *reg; #else UNUSED(dev); @@ -549,8 +559,9 @@ void ethosu_write_reg(struct ethosu_device *dev, uint32_t address, uint32_t valu { #if !defined(ARM_NPU_STUB) ASSERT(dev->base_address != 0); + ASSERT(address % 4 == 0); - volatile uint32_t *reg = (uint32_t *)(uintptr_t)(dev->base_address + address); + volatile uint32_t *reg = dev->base_address + address / sizeof(uint32_t); *reg = value; #else UNUSED(dev); @@ -559,6 +570,12 @@ void ethosu_write_reg(struct ethosu_device *dev, uint32_t address, uint32_t valu #endif } +void ethosu_write_reg_shadow(struct ethosu_device *dev, uint32_t address, uint32_t value, uint32_t *shadow) +{ + ethosu_write_reg(dev, address, value); + *shadow = ethosu_read_reg(dev, address); +} + enum ethosu_error_codes ethosu_save_pmu_config(struct ethosu_device *dev) { #if !defined(ARM_NPU_STUB) @@ -574,13 +591,9 @@ enum ethosu_error_codes ethosu_save_pmu_config(struct ethosu_device *dev) // Save start and stop event dev->pmccntr_cfg = ethosu_read_reg(dev, NPU_REG_PMCCNTR_CFG); - // Save the cycle counter - dev->pmccntr = ETHOSU_PMU_Get_CCNTR(); - // Save the event settings and counters for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++) { - dev->pmu_evcntr[i] = ethosu_read_reg(dev, NPU_REG_PMEVCNTR0 + i * sizeof(uint32_t)); dev->pmu_evtypr[i] = ethosu_read_reg(dev, NPU_REG_PMEVTYPER0 + i * sizeof(uint32_t)); } #else @@ -605,13 +618,9 @@ enum ethosu_error_codes ethosu_restore_pmu_config(struct ethosu_device *dev) // Restore start and stop event ethosu_write_reg(dev, NPU_REG_PMCCNTR_CFG, dev->pmccntr_cfg); - // Restore the cycle counter - ETHOSU_PMU_Set_CCNTR(dev->pmccntr); - - // Restore event settings and counters + // Save the event settings and counters for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++) { - ethosu_write_reg(dev, NPU_REG_PMEVCNTR0 + i * sizeof(uint32_t), dev->pmu_evcntr[i]); ethosu_write_reg(dev, NPU_REG_PMEVTYPER0 + i * sizeof(uint32_t), dev->pmu_evtypr[i]); } #else @@ -621,6 +630,25 @@ enum ethosu_error_codes ethosu_restore_pmu_config(struct ethosu_device *dev) return ETHOSU_SUCCESS; } +enum ethosu_error_codes ethosu_save_pmu_counters(struct ethosu_device *dev) +{ +#if !defined(ARM_NPU_STUB) + // Save the cycle counter + dev->pmccntr[0] = ethosu_read_reg(dev, NPU_REG_PMCCNTR_LO); + dev->pmccntr[1] = ethosu_read_reg(dev, NPU_REG_PMCCNTR_HI); + + // Save the event settings and counters + for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++) + { + dev->pmu_evcntr[i] = ethosu_read_reg(dev, NPU_REG_PMEVCNTR0 + i * sizeof(uint32_t)); + } +#else + UNUSED(dev); +#endif + + return ETHOSU_SUCCESS; +} + bool ethosu_status_has_error(struct ethosu_device *dev) { bool status_error = false; diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c index 6c55b0b..77b8727 100644 --- a/src/ethosu_driver.c +++ b/src/ethosu_driver.c @@ -149,7 +149,7 @@ struct opt_cfg_s ******************************************************************************/ struct ethosu_driver ethosu_drv = { - .dev = {.base_address = NULL, .reset = 0, .pmccntr = 0, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}}, + .dev = {.base_address = NULL, .reset = 0, .pmccntr = {0}, .pmu_evcntr = {0, 0, 0, 0}, .pmu_evtypr = {0, 0, 0, 0}}, .abort_inference = false, .status_error = false}; @@ -419,7 +419,7 @@ int ethosu_invoke_v2(const void *custom_data_ptr, if (!ethosu_drv.status_error) { - ethosu_save_pmu_config(ðosu_drv.dev); + ethosu_save_pmu_counters(ðosu_drv.dev); ethosu_set_clock_and_power(ðosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_ENABLE); } @@ -580,17 +580,14 @@ static int handle_command_stream(struct ethosu_driver *drv, return -1; } - // ETHOSU would have been reset in the IRQ handler if there were - // status error(s). So don't read the QREAD register. (void)ethosu_get_qread(&drv->dev, &qread); if (qread != cms_bytes) { - LOG_ERR( + LOG_WARN( "Failure: IRQ received but qread (%" PRIu32 ") not at end of stream (%" PRIu32 ").\n", qread, cms_bytes); return -1; } - // TODO Power off return 0; } diff --git a/src/ethosu_pmu.c b/src/ethosu_pmu.c index 7ca35fc..f7cb957 100644 --- a/src/ethosu_pmu.c +++ b/src/ethosu_pmu.c @@ -42,8 +42,6 @@ #define EVID(A, name) (PMU_EVENT_TYPE_##name) -#define ETHOSU_PMCCNTR_CFG_START_STOP_EVENT_MASK (0x3FF) - #define NPU_REG_PMEVCNTR(x) (NPU_REG_PMEVCNTR0 + ((x) * sizeof(uint32_t))) #define NPU_REG_PMEVTYPER(x) (NPU_REG_PMEVTYPER0 + ((x) * sizeof(uint32_t))) @@ -51,20 +49,13 @@ * Variables *****************************************************************************/ -/** - * NOTE: A pointer to ethosu_driver will be added to the PMU functions - * when multi-NPU functionality is implemented later. We shall use a - * shared ethosu_driver instance till then. - * */ -extern struct ethosu_driver ethosu_drv; - static const enum pmu_event_type eventbyid[] = {EXPAND_PMU_EVENT_TYPE(EVID, COMMA)}; /***************************************************************************** - * Functions + * Static functions *****************************************************************************/ -enum ethosu_pmu_event_type pmu_event_type(uint32_t id) +static enum ethosu_pmu_event_type pmu_event_type(uint32_t id) { switch (id) { @@ -76,7 +67,7 @@ enum ethosu_pmu_event_type pmu_event_type(uint32_t id) return ETHOSU_PMU_SENTINEL; } -uint32_t pmu_event_value(enum ethosu_pmu_event_type event) +static uint32_t pmu_event_value(enum ethosu_pmu_event_type event) { int a = event; if ((a < ETHOSU_PMU_SENTINEL) && (a >= ETHOSU_PMU_NO_EVENT)) @@ -89,29 +80,9 @@ uint32_t pmu_event_value(enum ethosu_pmu_event_type event) } } -void ethosu_pmu_driver_init(void) -{ -#ifdef PMU_AUTOINIT - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCR, INIT_PMCR); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCNTENSET, INIT_PMCNTENSET); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCNTENCLR, INIT_PMCNTENCLR); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMOVSSET, INIT_PMOVSSET); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMOVSCLR, INIT_PMOVSCLR); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMINTSET, INIT_PMINTSET); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMINTCLR, INIT_PMINTCLR); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_LO, INIT_PMCCNTR); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_HI, INIT_PMCCNTR); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_CFG, INIT_PMCCNTR_CFG); - - for (int i = 0; i < ETHOSU_PMU_NCOUNTERS; i++) - { - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMEVCNTR(i), 0); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMEVTYPER(i), 0); - } -#endif -} - -void ethosu_pmu_driver_exit(void) {} +/***************************************************************************** + * Functions + *****************************************************************************/ void ETHOSU_PMU_Enable(void) { @@ -119,8 +90,7 @@ void ETHOSU_PMU_Enable(void) struct pmcr_r pmcr; pmcr.word = ethosu_drv.dev.pmcr; pmcr.cnt_en = 1; - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCR, pmcr.word); - ethosu_drv.dev.pmcr = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCR); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCR, pmcr.word, ðosu_drv.dev.pmcr); } void ETHOSU_PMU_Disable(void) @@ -129,8 +99,7 @@ void ETHOSU_PMU_Disable(void) struct pmcr_r pmcr; pmcr.word = ethosu_drv.dev.pmcr; pmcr.cnt_en = 0; - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCR, pmcr.word); - ethosu_drv.dev.pmcr = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCR); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCR, pmcr.word, ðosu_drv.dev.pmcr); } void ETHOSU_PMU_Set_EVTYPER(uint32_t num, enum ethosu_pmu_event_type type) @@ -138,14 +107,13 @@ void ETHOSU_PMU_Set_EVTYPER(uint32_t num, enum ethosu_pmu_event_type type) ASSERT(num < ETHOSU_PMU_NCOUNTERS); uint32_t val = pmu_event_value(type); LOG_DEBUG("%s: num=%u, type=%d, val=%u\n", __FUNCTION__, num, type, val); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMEVTYPER(num), val); - ethosu_drv.dev.pmu_evtypr[num] = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMEVTYPER(num)); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMEVTYPER(num), val, ðosu_drv.dev.pmu_evtypr[num]); } enum ethosu_pmu_event_type ETHOSU_PMU_Get_EVTYPER(uint32_t num) { ASSERT(num < ETHOSU_PMU_NCOUNTERS); - uint32_t val = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMEVTYPER(num)); + uint32_t val = ethosu_drv.dev.pmu_evtypr[num]; enum ethosu_pmu_event_type type = pmu_event_type(val); LOG_DEBUG("%s: num=%u, type=%d, val=%u\n", __FUNCTION__, num, type, val); return type; @@ -157,9 +125,9 @@ void ETHOSU_PMU_CYCCNT_Reset(void) struct pmcr_r pmcr; pmcr.word = ethosu_drv.dev.pmcr; pmcr.cycle_cnt_rst = 1; - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCR, pmcr.word); - ethosu_drv.dev.pmcr = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCR); - ethosu_drv.dev.pmccntr = 0; + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCR, pmcr.word, ðosu_drv.dev.pmcr); + ethosu_drv.dev.pmccntr[0] = 0; + ethosu_drv.dev.pmccntr[1] = 0; } void ETHOSU_PMU_EVCNTR_ALL_Reset(void) @@ -168,8 +136,7 @@ void ETHOSU_PMU_EVCNTR_ALL_Reset(void) struct pmcr_r pmcr; pmcr.word = ethosu_drv.dev.pmcr; pmcr.event_cnt_rst = 1; - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCR, pmcr.word); - ethosu_drv.dev.pmcr = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCR); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCR, pmcr.word, ðosu_drv.dev.pmcr); for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++) { @@ -180,55 +147,59 @@ void ETHOSU_PMU_EVCNTR_ALL_Reset(void) void ETHOSU_PMU_CNTR_Enable(uint32_t mask) { LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCNTENSET, mask); - ethosu_drv.dev.pmcnten = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCNTENSET); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCNTENSET, mask, ðosu_drv.dev.pmcnten); } void ETHOSU_PMU_CNTR_Disable(uint32_t mask) { LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCNTENCLR, mask); - ethosu_drv.dev.pmcnten = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCNTENSET); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCNTENCLR, mask, ðosu_drv.dev.pmcnten); } uint32_t ETHOSU_PMU_CNTR_Status(void) { - uint32_t val = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCNTENSET); - LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, val); - return val; + LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, ethosu_drv.dev.pmcnten); + return ethosu_drv.dev.pmcnten; } uint64_t ETHOSU_PMU_Get_CCNTR(void) { - uint64_t val = (((uint64_t)ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_HI)) << 32) | - ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_LO); + uint32_t val_lo = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_HI); + uint32_t val_hi = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_LO); + uint64_t val = ((uint64_t)val_hi << 32) | val_lo; + uint64_t shadow = ((uint64_t)ethosu_drv.dev.pmccntr[1] << 32) | ethosu_drv.dev.pmccntr[0]; - LOG_DEBUG("%s: val=%llu, pmccntr=%llu\n", __FUNCTION__, val, ethosu_drv.dev.pmccntr); + LOG_DEBUG("%s: val=%llu, shadow=%llu\n", __FUNCTION__, val, shadow); - // Return the cached value in case the NPU was powered off - if (ethosu_drv.dev.pmccntr > val) + // Return the shadow variable in case the NPU was powered off and lost the cycle count + if (shadow > val) { - return ethosu_drv.dev.pmccntr; + return shadow; } + // Update the shadow variable + ethosu_drv.dev.pmccntr[0] = val_lo; + ethosu_drv.dev.pmccntr[1] = val_hi; + return val; } void ETHOSU_PMU_Set_CCNTR(uint64_t val) { - uint32_t mask = ETHOSU_PMU_CNTR_Status(); + uint32_t active = ETHOSU_PMU_CNTR_Status() & ETHOSU_PMU_CCNT_Msk; LOG_DEBUG("%s: val=%llu\n", __FUNCTION__, val); - if (mask & ETHOSU_PMU_CCNT_Msk) + if (active) { ETHOSU_PMU_CNTR_Disable(ETHOSU_PMU_CCNT_Msk); } - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_LO, (val & MASK_0_31_BITS)); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_HI, (val & MASK_32_47_BITS) >> 32); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCCNTR_LO, val & MASK_0_31_BITS, ðosu_drv.dev.pmccntr[0]); + ethosu_write_reg_shadow( + ðosu_drv.dev, NPU_REG_PMCCNTR_HI, (val & MASK_32_47_BITS) >> 32, ðosu_drv.dev.pmccntr[1]); - if (mask & ETHOSU_PMU_CCNT_Msk) + if (active) { ETHOSU_PMU_CNTR_Enable(ETHOSU_PMU_CCNT_Msk); } @@ -238,14 +209,17 @@ uint32_t ETHOSU_PMU_Get_EVCNTR(uint32_t num) { ASSERT(num < ETHOSU_PMU_NCOUNTERS); uint32_t val = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMEVCNTR(num)); - LOG_DEBUG("%s: num=%u, val=%u, pmu_evcntr=%u\n", __FUNCTION__, num, val, ethosu_drv.dev.pmu_evcntr[num]); + LOG_DEBUG("%s: num=%u, val=%u, shadow=%u\n", __FUNCTION__, num, val, ethosu_drv.dev.pmu_evcntr[num]); - // Return the cached value in case the NPU was powered off + // Return the shadow variable in case the NPU was powered off and lost the event count if (ethosu_drv.dev.pmu_evcntr[num] > val) { return ethosu_drv.dev.pmu_evcntr[num]; } + // Update the shadow variable + ethosu_drv.dev.pmu_evcntr[num] = val; + return val; } @@ -262,8 +236,6 @@ uint32_t ETHOSU_PMU_Get_CNTR_OVS(void) return ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMOVSSET); } -// TODO: check if this function name match with the description & -// implementation. void ETHOSU_PMU_Set_CNTR_OVS(uint32_t mask) { LOG_DEBUG("%s:\n", __FUNCTION__); @@ -273,22 +245,19 @@ void ETHOSU_PMU_Set_CNTR_OVS(uint32_t mask) void ETHOSU_PMU_Set_CNTR_IRQ_Enable(uint32_t mask) { LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMINTSET, mask); - ethosu_drv.dev.pmint = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMINTSET); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMINTSET, mask, ðosu_drv.dev.pmint); } void ETHOSU_PMU_Set_CNTR_IRQ_Disable(uint32_t mask) { LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMINTCLR, mask); - ethosu_drv.dev.pmint = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMINTSET); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMINTCLR, mask, ðosu_drv.dev.pmint); } uint32_t ETHOSU_PMU_Get_IRQ_Enable(void) { - uint32_t mask = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMINTSET); - LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask); - return mask; + LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, ethosu_drv.dev.pmint); + return ethosu_drv.dev.pmint; } void ETHOSU_PMU_CNTR_Increment(uint32_t mask) @@ -296,49 +265,45 @@ void ETHOSU_PMU_CNTR_Increment(uint32_t mask) LOG_DEBUG("%s:\n", __FUNCTION__); uint32_t cntrs_active = ETHOSU_PMU_CNTR_Status(); + // Disable counters + ETHOSU_PMU_CNTR_Disable(mask); + + // Increment cycle counter if (mask & ETHOSU_PMU_CCNT_Msk) { - if (mask & ETHOSU_PMU_CCNT_Msk) - { - ETHOSU_PMU_CNTR_Disable(ETHOSU_PMU_CCNT_Msk); - uint64_t val = ETHOSU_PMU_Get_CCNTR() + 1; - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_LO, (val & MASK_0_31_BITS)); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_HI, (val & MASK_32_47_BITS) >> 32); - if (cntrs_active & ETHOSU_PMU_CCNT_Msk) - { - ETHOSU_PMU_CNTR_Enable(ETHOSU_PMU_CCNT_Msk); - } - } + uint64_t val = ETHOSU_PMU_Get_CCNTR() + 1; + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCCNTR_LO, val & MASK_0_31_BITS, ðosu_drv.dev.pmccntr[0]); + ethosu_write_reg_shadow( + ðosu_drv.dev, NPU_REG_PMCCNTR_HI, (val & MASK_32_47_BITS) >> 32, ðosu_drv.dev.pmccntr[1]); } + for (int i = 0; i < ETHOSU_PMU_NCOUNTERS; i++) { - uint32_t cntr = (0x0001 << i); - - if (mask & cntr) + if (mask & (1 << i)) { - ETHOSU_PMU_CNTR_Disable(cntr); - uint32_t val = ethosu_read_reg(ðosu_drv.dev, NPU_REG_PMEVCNTR(i)); - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMEVCNTR(i), val + 1); - if (cntrs_active & cntr) - { - ETHOSU_PMU_CNTR_Enable(cntr); - } + uint32_t val = ETHOSU_PMU_Get_EVCNTR(i); + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMEVCNTR(i), val + 1, ðosu_drv.dev.pmu_evcntr[i]); } } + + // Reenable the active counters + ETHOSU_PMU_CNTR_Enable(cntrs_active); } void ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(uint32_t start_event) { LOG_DEBUG("%s: start_event=%u\n", __FUNCTION__, start_event); - struct pmccntr_cfg_r *cfg = (struct pmccntr_cfg_r *)ðosu_drv.dev.pmccntr_cfg; - cfg->CYCLE_CNT_CFG_START = start_event & ETHOSU_PMCCNTR_CFG_START_STOP_EVENT_MASK; - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_CFG, cfg->word); + struct pmccntr_cfg_r cfg; + cfg.word = ethosu_drv.dev.pmccntr_cfg; + cfg.CYCLE_CNT_CFG_START = start_event; + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCCNTR_CFG, cfg.word, ðosu_drv.dev.pmccntr_cfg); } void ETHOSU_PMU_PMCCNTR_CFG_Set_Stop_Event(uint32_t stop_event) { LOG_DEBUG("%s: stop_event=%u\n", __FUNCTION__, stop_event); - struct pmccntr_cfg_r *cfg = (struct pmccntr_cfg_r *)ðosu_drv.dev.pmccntr_cfg; - cfg->CYCLE_CNT_CFG_STOP = stop_event & ETHOSU_PMCCNTR_CFG_START_STOP_EVENT_MASK; - ethosu_write_reg(ðosu_drv.dev, NPU_REG_PMCCNTR_CFG, cfg->word); + struct pmccntr_cfg_r cfg; + cfg.word = ethosu_drv.dev.pmccntr_cfg; + cfg.CYCLE_CNT_CFG_STOP = stop_event; + ethosu_write_reg_shadow(ðosu_drv.dev, NPU_REG_PMCCNTR_CFG, cfg.word, ðosu_drv.dev.pmccntr_cfg); } -- cgit v1.2.1