Base pointer offset and soft reset

Allow user to define a base pointer offset, if the CPU and the NPU have
address spaces offseted from each other.

Soft reset NPU before every inference.

Added log prints.

Change-Id: I98a746d20dc780fefa23ad68816f5ba2ba2e6c6e
diff --git a/src/ethosu_config.h b/src/ethosu_config.h
index 07eb824..91fe660 100644
--- a/src/ethosu_config.h
+++ b/src/ethosu_config.h
@@ -108,6 +108,14 @@
 #define AXI_LIMIT3_MAX_OUTSTANDING_WRITES 16
 #endif
 
+/*
+ * Address offset between the CPU and the NPU. The offset is
+ * applied to the QBASE and BASEP registers.
+ */
+#ifndef BASE_POINTER_OFFSET
+#define BASE_POINTER_OFFSET 0
+#endif
+
 #ifdef PMU_AUTOINIT
 /*
  * Register control
diff --git a/src/ethosu_device.c b/src/ethosu_device.c
index 60fc243..404a0e7 100644
--- a/src/ethosu_device.c
+++ b/src/ethosu_device.c
@@ -17,6 +17,7 @@
  */
 #include "ethosu_device.h"
 #include "ethosu_common.h"
+#include "ethosu_config.h"
 
 #include <assert.h>
 #include <stddef.h>
@@ -26,6 +27,9 @@
 #define REG_OFFSET 4
 #define BYTES_1KB 1024
 
+#define ADDRESS_BITS 48
+#define ADDRESS_MASK ((1ull << ADDRESS_BITS) - 1)
+
 #if defined(ARM_NPU_STUB)
 static uint32_t stream_length = 0;
 #endif
@@ -93,29 +97,24 @@
     enum ethosu_error_codes ret_code = ETHOSU_SUCCESS;
 
 #if !defined(ARM_NPU_STUB)
-    uint32_t qbase0;
-    uint32_t qbase1;
-    uint32_t qsize;
-    uint32_t *reg_basep;
-    int num_base_reg;
-
     ASSERT(num_base_addr <= ETHOSU_DRIVER_BASEP_INDEXES);
 
-    qbase0       = ((uint64_t)cmd_stream_ptr) & MASK_0_31_BITS;
-    qbase1       = (((uint64_t)cmd_stream_ptr) & MASK_32_47_BITS) >> 32;
-    qsize        = cms_length;
-    num_base_reg = num_base_addr * 2;
-    reg_basep    = (uint32_t *)base_addr;
+    uint64_t qbase = (uint64_t)cmd_stream_ptr + BASE_POINTER_OFFSET;
+    ASSERT(qbase <= ADDRESS_MASK);
+    LOG_DEBUG("QBASE=0x%016llx, QSIZE=%u, base_pointer_offset=0x%08x\n", qbase, cms_length, BASE_POINTER_OFFSET);
+    ethosu_write_reg(dev, NPU_REG_QBASE0, qbase & 0xffffffff);
+    ethosu_write_reg(dev, NPU_REG_QBASE1, qbase >> 32);
+    ethosu_write_reg(dev, NPU_REG_QSIZE, cms_length);
 
-    for (int i = 0; i < num_base_reg; i++)
+    for (int i = 0; i < num_base_addr; i++)
     {
-        ethosu_write_reg(dev, NPU_REG_BASEP0 + (i * BASEP_OFFSET), reg_basep[i]);
+        uint64_t addr = base_addr[i] + BASE_POINTER_OFFSET;
+        ASSERT(addr <= ADDRESS_MASK);
+        LOG_DEBUG("BASEP%d=0x%016llx\n", i, addr);
+        ethosu_write_reg(dev, NPU_REG_BASEP0 + (2 * i) * BASEP_OFFSET, addr & 0xffffffff);
+        ethosu_write_reg(dev, NPU_REG_BASEP0 + (2 * i + 1) * BASEP_OFFSET, addr >> 32);
     }
 
-    ethosu_write_reg(dev, NPU_REG_QBASE0, qbase0);
-    ethosu_write_reg(dev, NPU_REG_QBASE1, qbase1);
-    ethosu_write_reg(dev, NPU_REG_QSIZE, qsize);
-
     ret_code = ethosu_set_command_run(dev);
 #else
     // NPU stubbed
@@ -282,6 +281,7 @@
     regioncfg.word &= ~(0x3 << (2 * region));
     regioncfg.word |= (memory_type & 0x3) << (2 * region);
     ethosu_write_reg(dev, NPU_REG_REGIONCFG, regioncfg.word);
+    LOG_DEBUG("REGIONCFG%u=0x%08x\n", region, regioncfg.word);
 #else
     // NPU stubbed
     UNUSED(dev);
diff --git a/src/ethosu_driver.c b/src/ethosu_driver.c
index 9d74980..f47d3f2 100644
--- a/src/ethosu_driver.c
+++ b/src/ethosu_driver.c
@@ -43,10 +43,20 @@
 void ethosu_irq_handler(void)
 {
     uint8_t irq_raised = 0;
+
+    LOG_DEBUG("Interrupt. status=0x%08x, qread=%d\n",
+              ethosu_read_reg(&ethosu_drv.dev, NPU_REG_STATUS),
+              ethosu_read_reg(&ethosu_drv.dev, NPU_REG_QREAD));
+
+    // Verify that interrupt has been raised
     (void)ethosu_is_irq_raised(&ethosu_drv.dev, &irq_raised);
     ASSERT(irq_raised == 1);
     irq_triggered = true;
+
+    // Clear interrupt
     (void)ethosu_clear_irq_status(&ethosu_drv.dev);
+
+    // Verify that interrupt has been successfully cleard
     (void)ethosu_is_irq_raised(&ethosu_drv.dev, &irq_raised);
     ASSERT(irq_raised == 0);
 }
@@ -280,8 +290,10 @@
     }
     int custom_data_32bit_size = (custom_data_size / BYTES_IN_32_BITS - CUSTOM_OPTION_LENGTH_32_BIT_WORD);
 
+    ethosu_soft_reset(&ethosu_drv.dev);
     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;
@@ -464,7 +476,7 @@
 {
     uint32_t qread     = 0;
     uint32_t cms_bytes = cms_length * BYTES_IN_32_BITS;
-    LOG_INFO("handle_command_stream cms_length %d\n", cms_length);
+    LOG_INFO("handle_command_stream: cmd_stream=%p, cms_length %d\n", cmd_stream, cms_length);
 
     if (0 != ((ptrdiff_t)cmd_stream & MASK_16_BYTE_ALIGN))
     {