Skip to content

Commit

Permalink
Add neureka support similar to ne16
Browse files Browse the repository at this point in the history
  • Loading branch information
lukamac committed Jan 14, 2024
1 parent b3ede52 commit 499fed2
Show file tree
Hide file tree
Showing 14 changed files with 988 additions and 841 deletions.
77 changes: 77 additions & 0 deletions inc/pulp_nnx_neureka.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Luka Macan <luka.macan@unibo.it>
*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "neureka.h"
#include "neureka_pulp_bsp.h"
#include "neureka_task.h"
#include <stdint.h>

/* PULP-NNX interface */

void neureka_nnx_init(neureka_dev_t *dev, neureka_pulp_conf_t *conf);
void neureka_nnx_term(neureka_dev_t *dev);

/** neureka_nnx_dispatch_check
*
* Check whether you can dispatch to the accelerator.
*/
int neureka_nnx_dispatch_check(neureka_dev_t *dev);

/** neureka_nnx_dispatch_wait
*
* Block until you can dispatch to the accelerator.
*/
void neureka_nnx_dispatch_wait(neureka_dev_t *dev);

/** neureka_nnx_dispatch
*
* Dispatch a task to the accelerator.
* Fails with return code 1 if the task cannot be dispatched. Otherwise returns 0.
*/
int neureka_nnx_dispatch(neureka_dev_t *dev, neureka_task_t *task);

/** neureka_nnx_resolve_check
*
* Check whether the task has been resolved.
*/
int neureka_nnx_resolve_check(neureka_dev_t *dev, neureka_task_t *task);

/** neureka_nnx_resolve_wait
*
* Block until you can resolve the task.
*/
void neureka_nnx_resolve_wait(neureka_dev_t *dev, neureka_task_t *task);


/* Additional helper functions */

/** neureka_nnx_dispatch_stride2x2
*
* It uses Neureka's 2x2 strided mode which reduces the number of writes Neureka does.
* This mode doesn't stride the Neureka's subtile input pointer, so we have to
* tile the tile to the subtile's spatial dimensions (in this case 3x3 output).
* Works only if the k_out is divisible by 2.
*/
void neureka_nnx_dispatch_stride2x2(
neureka_dev_t *dev, neureka_task_t *task, const uint32_t w_in, const uint32_t k_in,
const uint32_t w_in_stride, const uint32_t k_in_stride,
const uint32_t h_out, const uint32_t w_out, const uint32_t k_out,
const uint32_t w_out_stride, const uint32_t k_out_stride,
const uint8_t h_ker, const uint8_t w_ker);
93 changes: 93 additions & 0 deletions neureka/bsp/neureka_siracusa_bsp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Luka Macan <luka.macan@unibo.it>
*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "neureka_siracusa_bsp.h"
#include <pmsis.h>

#define NEUREKA_SIRACUSA_CLUSTER_CTRL_BASE_ADDR (0x00200000)
#define NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_OFFS 0x18
#define NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_ADDR \
(NEUREKA_SIRACUSA_CLUSTER_CTRL_ADDR_BASE + NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_OFFS)
#define NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_CG_EN 0x800
#define NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_HCI_PRIO 0x100
#define NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_HCI_MAXSTALL 0xff
#define NEUREKA_SIRACUSA_MAX_STALL (8)
#define NEUREKA_SIRACUSA_EVENT_0 (1 << 12)
#define NEUREKA_SIRACUSA_EVENT_1 (1 << 13)
#define NEUREKA_SIRACUSA_BASE_ADDR (0x00201000)
#define NEUREKA_SIRACUSA_WEIGHT_MEM_BASE_ADDR (0x10400000)
#define NEUREKA_SIRACUSA_WEIGHT_MEM_MRAM_OFFSET (0x00000000)
#define NEUREKA_SIRACUSA_WEIGHT_MEM_SRAM_OFFSET (0x00400000)

void neureka_siracusa_cg_enable() {
*(volatile uint32_t *)NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_ADDR |=
NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_CG_EN;
}

void neureka_siracusa_cg_disable() {
*(volatile uint32_t *)NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_ADDR &=
~NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_CG_EN;
}

// TODO: Check if needed for neureka
void neureka_siracusa_hci_setpriority_neureka() {
*(volatile uint32_t *)NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_ADDR |=
NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_HCI_PRIO;
}

// TODO: Check if needed for neureka
void neureka_siracusa_hci_setpriority_core() {
*(volatile uint32_t *)NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_ADDR &=
~NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_HCI_PRIO;
}

// TODO: Check if needed for neureka
void neureka_siracusa_hci_reset_max_stall() {
*(volatile uint32_t *)NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_ADDR &=
~NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_HCI_MAXSTALL;
}

// TODO: Check if needed for neureka
void neureka_siracusa_hci_set_max_stall(uint32_t max_stall) {
*(volatile uint32_t *)NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_ADDR |=
max_stall & NEUREKA_SIRACUSA_CLUSTER_CTRL_HWPE_MASK_HCI_MAXSTALL;
}

void neureka_siracusa_open(neureka_siracusa_conf_t *conf) {
neureka_siracusa_cg_enable();
neureka_siracusa_hci_setpriority_neureka();
neureka_siracusa_hci_set_max_stall(conf->max_stall);
}

void neureka_siracusa_close() {
neureka_siracusa_hci_reset_max_stall();
neureka_siracusa_hci_setpriority_core();
neureka_siracusa_cg_disable();
}

void neureka_siracusa_event_wait_and_clear() {
eu_evt_maskWaitAndClr(NEUREKA_SIRACUSA_EVENT);
}

static const neureka_dev_t neureka_siracusa_dev = {
.hwpe_dev = (struct hwpe_dev_t){
.base_addr = (volatile uint32_t *)NEUREKA_SIRACUSA_BASE_ADDR}};

const neureka_dev_t *neureka_siracusa_get_dev() { return &neureka_siracusa_dev; }
81 changes: 81 additions & 0 deletions neureka/bsp/neureka_siracusa_bsp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Luka Macan <luka.macan@unibo.it>
*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef __NEUREKA_siracusa_BSP_H__
#define __NEUREKA_siracusa_BSP_H__

#include "neureka.h"
#include <stdint.h>

/**
* neureka_siracusa_cg_enable
*
* Enable clock gating of the neureka.
*/
void neureka_siracusa_cg_enable();

/**
* neureka_siracusa_cg_enable
*
* Disable clock gating of the neureka.
*/
void neureka_siracusa_cg_disable();

/**
* neureka_siracusa_setpriority_neureka
*
* Set HCI interconnect bus priority to prioritize neureka.
*/
void neureka_siracusa_hci_setpriority_neureka();

/**
* neureka_siracusa_setpriority_core
*
* Set HCI bus priority to prioritize cores.
*/
void neureka_siracusa_hci_setpriority_core();

/**
* neureka_siracusa_hci_reset_maxstall
*
* Reset the HCI bus maxstall parameter.
* TODO: Check if it disables it also or just resets?
*/
void neureka_siracusa_hci_reset_max_stall();

/**
* neureka_siracusa_hci_set_maxstall
*
* Set the HCI bus maxstall. Maxstall defines how many cycles
* will the HCI bus stall the lower priority master, i.e. neureka or core,
* before letting it do a transaction.
*/
void neureka_siracusa_hci_set_max_stall(uint32_t max_stall);

typedef struct neureka_siracusa_conf_t {
int max_stall;
} neureka_siracusa_conf_t;

void neureka_siracusa_open(neureka_siracusa_conf_t *conf);
void neureka_siracusa_close();
void neureka_siracusa_event_wait_and_clear();
const neureka_dev_t *neureka_siracusa_get_dev();

#endif // !__NEUREKA_siracusa_BSP_H__
54 changes: 54 additions & 0 deletions neureka/gvsoc/neureka_gvsoc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Luka Macan <luka.macan@unibo.it>
*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef __NEUREKA_GVSOC_H__
#define __NEUREKA_GVSOC_H__

#include "neureka.h"
#include "neureka_task.h"

#define NEUREKA_REG_GVSOC_LOG_LEVEL 24
#define NEUREKA_REG_GVSOC_LOG_FORMAT 25

typedef enum neureka_gvsoc_log_format_e {
NEUREKA_GVSOC_LOG_FORMAT_DECIMAL = 0,
NEUREKA_GVSOC_LOG_FORMAT_HEXADECIMAL = 3
} neureka_gvsoc_log_format_e;

typedef enum neureka_gvsoc_log_level_e {
NEUREKA_GVSOC_LOG_LEVEL_JOB_START_END = 0,
NEUREKA_GVSOC_LOG_LEVEL_CONFIG = 1,
NEUREKA_GVSOC_LOG_LEVEL_ACTIV_INOUT = 2,
NEUREKA_GVSOC_LOG_LEVEL_ALL = 3
} neureka_gvsoc_log_level_e;

static void neureka_gvsoc_log_activate(neureka_dev_t *dev,
neureka_gvsoc_log_level_e log_level,
neureka_gvsoc_log_format_e format) {
hwpe_task_reg_write(&dev->hwpe_dev, NEUREKA_REG_GVSOC_LOG_LEVEL, log_level);
hwpe_task_reg_write(&dev->hwpe_dev, NEUREKA_REG_GVSOC_LOG_FORMAT, format);
}

static void neureka_gvsoc_log_deactivate(neureka_dev_t *dev) {
hwpe_task_reg_write(&dev->hwpe_dev, NEUREKA_REG_GVSOC_LOG_LEVEL,
NEUREKA_GVSOC_LOG_LEVEL_JOB_START_END);
}

#endif // __NEUREKA_GVSOC_H__
27 changes: 17 additions & 10 deletions neureka/inc/pulp_nnx_error_codes.h → neureka/hal/neureka.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,22 @@
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef __NE16_ERROR_CODES_H__
#define __NE16_ERROR_CODES_H__
#include "neureka.h"

typedef enum {
success = 0,
weightBitwidthOutOfBounds,
unsupportedWeightOffsetMode,
unsupportedFeatureBitwidth,
dimensionMismatch
} nnx_error_code;
#define NEUREKA_STATUS_EMPTY (0x000)
#define NEUREKA_STATUS_FULL (0x101)

#endif // __NE16_ERROR_CODES_H__
inline int neureka_task_queue_size(neureka_dev_t *dev) { return 2; }

inline int neureka_task_queue_tasks_in_flight(neureka_dev_t *dev) {
uint32_t status = hwpe_task_queue_status(&dev->hwpe_dev);
return (status & 0x1) + ((status >> 8) & 0x1);
}

inline int neureka_task_queue_empty(neureka_dev_t *dev) {
return hwpe_task_queue_status(&dev->hwpe_dev) == NEUREKA_STATUS_EMPTY;
}

inline int neureka_task_queue_full(neureka_dev_t *dev) {
return hwpe_task_queue_status(&dev->hwpe_dev) == NEUREKA_STATUS_FULL;
}
22 changes: 14 additions & 8 deletions neureka/src/pulp_nnx_util.c → neureka/hal/neureka.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,19 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include "pulp_nnx_util.h"
#include "pulp_nnx_hal.h"
#ifndef __NEUREKA_H__
#define __NEUREKA_H__

void nnx_activate_gvsoc_logging(int log_level) {
NEUREKA_WRITE_IO_REG(NEUREKA_REG_GVSOC_TRACE, log_level);
}
#include "hwpe.h"
#include <stdint.h>

void nnx_deactivate_gvsoc_logging() {
NEUREKA_WRITE_IO_REG(NEUREKA_REG_GVSOC_TRACE, 0);
}
typedef struct neureka_dev_t {
hwpe_dev_t hwpe_dev; /* Implements the HWPE device interface */
} neureka_dev_t;

int neureka_task_queue_size(neureka_dev_t *dev);
int neureka_task_queue_tasks_in_flight(neureka_dev_t *dev);
int neureka_task_queue_empty(neureka_dev_t *dev);
int neureka_task_queue_full(neureka_dev_t *dev);

#endif // __NEUREKA_H__
Loading

0 comments on commit 499fed2

Please sign in to comment.