MLBEDSW-2594 Initialize the Ethos-U before every job

This includes resetting the Ethos-U and restoring the
previosuly saved PMU configuration (if any).

Change-Id: Id952fb6fef513468952b6a469e857510f8c0214c
diff --git a/include/ethosu_device.h b/include/ethosu_device.h
index 46772ba..81f24a9 100644
--- a/include/ethosu_device.h
+++ b/include/ethosu_device.h
@@ -22,6 +22,9 @@
  * Includes
  ******************************************************************************/
 
+#include "pmu_ethosu.h"
+
+#include <stdbool.h>
 #include <stdint.h>
 
 #ifdef __cplusplus
@@ -51,6 +54,10 @@
 struct ethosu_device
 {
     uintptr_t base_address;
+    bool restore_pmu_config;
+    uint64_t pmccntr;
+    uint32_t pmu_evcntr[ETHOSU_PMU_NCOUNTERS];
+    enum ethosu_pmu_event_type pmu_evtypr[ETHOSU_PMU_NCOUNTERS];
 };
 
 struct ethosu_id
@@ -355,6 +362,22 @@
 
 void ethosu_write_reg(struct ethosu_device *dev, uint32_t address, uint32_t value);
 
+/**
+ * Save the PMU configuration to ethosu_device struct.
+ * \param[in] dev              Ethos-U device where the PMU configuration is
+ *                             saved.
+ * \return                     \ref ethosu_error_codes
+ */
+enum ethosu_error_codes ethosu_save_pmu_config(struct ethosu_device *dev);
+
+/**
+ * Restore the PMU configuration from a ethosu_device struct.
+ * \param[in] dev              Ethos-U device where the PMU configuration is
+ *                             stored.
+ * \return                     \ref ethosu_error_codes
+ */
+enum ethosu_error_codes ethosu_restore_pmu_config(struct ethosu_device *dev);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/pmu_ethosu.h b/include/pmu_ethosu.h
index e83b879..41614e7 100644
--- a/include/pmu_ethosu.h
+++ b/include/pmu_ethosu.h
@@ -19,7 +19,6 @@
 #ifndef PMU_ETHOSU_H
 #define PMU_ETHOSU_H
 
-#include "ethosu_device.h"
 #include <stdint.h>
 
 #ifdef __cplusplus
diff --git a/src/ethosu_device.c b/src/ethosu_device.c
index 9bda87d..60fc243 100644
--- a/src/ethosu_device.c
+++ b/src/ethosu_device.c
@@ -551,3 +551,42 @@
     UNUSED(value);
 #endif
 }
+
+enum ethosu_error_codes ethosu_save_pmu_config(struct ethosu_device *dev)
+{
+#if !defined(ARM_NPU_STUB)
+    dev->pmccntr = ETHOSU_PMU_Get_CCNTR();
+    for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++)
+    {
+        dev->pmu_evcntr[i] = ETHOSU_PMU_Get_EVCNTR(i);
+        dev->pmu_evtypr[i] = ETHOSU_PMU_Get_EVTYPER(i);
+    }
+    if (!dev->restore_pmu_config)
+    {
+        dev->restore_pmu_config = true;
+    }
+#else
+    UNUSED(dev);
+#endif
+
+    return ETHOSU_SUCCESS;
+}
+
+enum ethosu_error_codes ethosu_restore_pmu_config(struct ethosu_device *dev)
+{
+#if !defined(ARM_NPU_STUB)
+    if (dev->restore_pmu_config)
+    {
+        ETHOSU_PMU_Set_CCNTR(dev->pmccntr);
+        for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++)
+        {
+            ETHOSU_PMU_Set_EVCNTR(i, dev->pmu_evcntr[i]);
+            ETHOSU_PMU_Set_EVTYPER(i, dev->pmu_evtypr[i]);
+        }
+    }
+#else
+    UNUSED(dev);
+#endif
+
+    return ETHOSU_SUCCESS;
+}
diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c
index 1a9337e..9d74980 100644
--- a/src/ethosu_driver.c
+++ b/src/ethosu_driver.c
@@ -29,7 +29,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-struct ethosu_driver ethosu_drv = {.dev = {.base_address = NULL}, .abort_inference = false};
+struct ethosu_driver ethosu_drv = {.dev             = {.base_address       = NULL,
+                                           .restore_pmu_config = false,
+                                           .pmccntr            = 0,
+                                           .pmu_evcntr         = {0, 0, 0, 0},
+                                           .pmu_evtypr         = {0, 0, 0, 0}},
+                                   .abort_inference = false};
 
 // IRQ
 static volatile bool irq_triggered = false;
@@ -276,6 +281,7 @@
     int custom_data_32bit_size = (custom_data_size / BYTES_IN_32_BITS - CUSTOM_OPTION_LENGTH_32_BIT_WORD);
 
     ethosu_set_clock_and_power(&ethosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_DISABLE);
+    ethosu_restore_pmu_config(&ethosu_drv.dev);
     while (data_ptr < (data_start_ptr + custom_data_32bit_size))
     {
         int ret = 0;
@@ -337,6 +343,7 @@
             break;
         }
     }
+    ethosu_save_pmu_config(&ethosu_drv.dev);
     ethosu_set_clock_and_power(&ethosu_drv.dev, ETHOSU_CLOCK_Q_ENABLE, ETHOSU_POWER_Q_ENABLE);
     return return_code;
 }