Skip to content

Commit

Permalink
Merge pull request #128 from tum-ei-eda/patch_uma_new
Browse files Browse the repository at this point in the history
Support for UMA examples and their ETISS plugins
  • Loading branch information
PhilippvK authored Jan 23, 2024
2 parents 0b2f68e + 928e80f commit e24ec10
Show file tree
Hide file tree
Showing 22 changed files with 1,336 additions and 5 deletions.
1 change: 1 addition & 0 deletions mlonmcu/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def handle_docker(args):
# def main(args):
def main(args=None):
"""Console script for mlonmcu."""

parser = argparse.ArgumentParser(
description="ML on MCU Flow",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
Expand Down
38 changes: 38 additions & 0 deletions mlonmcu/feature/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,44 @@ def get_required_cache_flags(self):
return ret


@register_feature("uma_backends")
class UMABackends(BackendFeature):
"""Add directories that contain UMA backends."""

REQUIRED = []

DEFAULTS = {
**FeatureBase.DEFAULTS,
"uma_dir": "",
"uma_target": "",
}

def __init__(self, features=None, config=None):
super().__init__("uma_backends", features=features, config=config)

@property
def uma_dir(self):
return self.config["uma_dir"]

@property
def uma_target(self):
return self.config["uma_target"]

def add_backend_config(self, backend, config):
assert backend in SUPPORTED_TVM_BACKENDS, f"Unsupported feature '{self.name}' for backend '{backend}'"
tvmcArgs = ["--experimental-tvmc-extension", self.uma_dir]
if f"{backend}.tvmc_extra_args" in config:
config[f"{backend}.tvmc_extra_args"].extend(tvmcArgs)
else:
config[f"{backend}.tvmc_extra_args"] = tvmcArgs
extras = config.get(f"{backend}.extra_target", [])
if self.uma_target not in extras:
if isinstance(extras, str):
extras = [extras]
extras.append(self.uma_target)
config[f"{backend}.extra_target"] = extras


@register_feature("demo")
class Demo(PlatformFeature):
"""Run demo application instead of benchmarking code."""
Expand Down
2 changes: 1 addition & 1 deletion mlonmcu/flow/tvm/backend/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class TVMBackend(Backend):

name = None

FEATURES = {"autotuned", "cmsisnnbyoc", "muriscvnnbyoc", "disable_legalize", "moiopt"}
FEATURES = {"autotuned", "cmsisnnbyoc", "muriscvnnbyoc", "disable_legalize", "moiopt", "uma_backends"}

DEFAULTS = {
"print_outputs": False,
Expand Down
19 changes: 15 additions & 4 deletions mlonmcu/setup/tasks/tvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,15 @@
Tasks = get_task_factory()


def requires_patch(context: MlonMcuContext):
return context.environment.has_feature("disable_legalize")


def _validate_tvm(context: MlonMcuContext, params=None):
# user_vars = context.environment.vars
patch = bool(params.get("patch", False))
if patch:
if not context.environment.has_feature("disable_legalize"):
if not requires_patch(context):
return False
return context.environment.has_framework("tvm")

Expand All @@ -63,10 +67,10 @@ def _validate_tvm_build(context: MlonMcuContext, params=None):
# if not (context.environment.has_feature("cmsisnnbyoc") or context.environment.has_feature("muriscvnnbyoc")):
# return False
if patch:
if not context.environment.has_feature("disable_legalize"):
if not requires_patch(context):
return False
if use_tlcpack:
assert not context.environment.has_feature("disable_legalize")
assert not requires_patch(context)
return False
if dbg:
assert not use_tlcpack
Expand Down Expand Up @@ -167,6 +171,13 @@ def build_tvm(context: MlonMcuContext, params=None, rebuild=False, verbose=False
r"s/USE_LLVM \(OFF\|ON\)/USE_LLVM " + llvmConfigEscaped + "/g",
str(cfgFile),
)
utils.exec(
"sed",
"-i",
"--",
r"s/USE_UMA OFF/USE_UMA ON/g",
str(cfgFile),
)
if cmsisnn:
utils.exec(
"sed",
Expand Down Expand Up @@ -218,7 +229,7 @@ def install_tvm(


def _validate_tvm_extensions(context: MlonMcuContext, params=None):
return _validate_tvm_build(context, params=params) and context.environment.has_feature("disable_legalize")
return _validate_tvm_build(context, params=params) and requires_patch(context)


@Tasks.provides(["tvm_extensions.src_dir", "tvm_extensions.wrapper"])
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
"""UMA backend for the q_vanilla_accelerator accelerator"""
from .passes import QVanillaAcceleratorConv2dPass, ConvertLayout

# , ConvertLayout, Canonicalize, QVanillaAcceleratorDensePass
from tvm.relay.backend.contrib.uma.api.utils import PassPhase
from tvm.relay.backend.contrib.uma.backend import UMABackend
from .codegen import gen_includes

# from .patterns import conv2d_pattern, dense_pattern, qnn_conv2d_pattern
from .patterns import qnn_conv2d_add_pattern
from .strategies import qnn_conv2d_strategy


class QVanillaAcceleratorBackend(UMABackend):
"""UMA backend for the QVanillaAccelerator accelerator."""

def __init__(self):
print("init!")
super().__init__()

# Target configuration
self._register_target_attr("dimension")

# Relay Pattern registration
self._register_pattern("qnn_conv2d_add", qnn_conv2d_add_pattern())

# self._register_pattern("dense", dense_pattern())

# Relay to Relay function registration
self._register_relay_pass(PassPhase.PRE_PARTITIONING, ConvertLayout())

# self._register_relay_pass(PassPhase.POST_PARTITIONING_0, Canonicalize())

# Relay to TIR function registration
self._register_operator_strategy("qnn.conv2d", qnn_conv2d_strategy)

self._register_tir_pass(PassPhase.TIR_PHASE_0, QVanillaAcceleratorConv2dPass())

# self._register_tir_pass(PassPhase.TIR_PHASE_0, QVanillaAcceleratorDensePass())

# TIR to runtime function registration
self._register_codegen(fmt="c", includes=gen_includes)

@property
def target_name(self):
return "q_vanilla_accelerator"
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
"""UMA codegen for the q_vanilla_accelerator accelerator"""

# import tvm
import pathlib


def gen_includes() -> str:
topdir = pathlib.Path(__file__).parent.absolute()

includes = ""
includes += f'#include "{topdir}/conv2dnchw.cc"'
return includes
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@


#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>


#ifdef __cplusplus
extern "C"
#endif

/*!
* \brief Conv2D function for mock-accelerator examples. Limited to same-padded Conv2D with
* stride (1,1) and datatype int8, as well as a bias addition. \param ifmap Pointer to input feature map data of size
* iw*ih*ic*sizeof(int8). \param weights Pointer to weight data of size
* kh*kw*ic**oc*sizeof(int8). \param bias_data Pointer to bias data of size oc*sizeof(int32).
* \param result Pointer to output feature map data of size
* iw*ih*oc*sizeof(int32). \param oc Number of channels of output feature map. \param iw Width
* of input feature map, ifmap. \param ih Height of input feature map, ifmap. \param ic Number
* of channels of input feature map. \param kh Height of convolution kernels. \param kw Width of
* convolution kernels.\param i_zp and k_zp zero point parameters of
* input feature map and kernel.
*
* \return error code
*
*/

typedef struct regs
{
uint32_t ifmap;
uint32_t weights;
uint32_t bias;
uint32_t result;
int32_t oc;
int32_t iw;
int32_t ih;
int32_t ic;
int32_t kh;
int32_t kw;
int32_t i_zp;
int32_t k_zp;
uint32_t control;
uint32_t status;
} regs_t;

int q_vanilla_accelerator_conv2dnchw(int8_t* q_vanilla_accelerator_0_i0, int8_t* q_vanilla_accelerator_0_i1, int32_t* bias_data, int32_t* compute,
int32_t oc, int32_t iw, int32_t ih, int32_t ic, int32_t kh, int32_t kw, int32_t i_zp, int32_t k_zp) {



// QVanillaAcceleratorT (with timing) base_adr = 0x70002000,
// for QVanillaAccelerator (w/o timing) replace this file with conv2dnchw1.cc contents or interchange the names!
regs_t *p_regs = (regs_t *)0x70002000;

p_regs->ifmap = (uint32_t) q_vanilla_accelerator_0_i0;
p_regs->weights = (uint32_t) q_vanilla_accelerator_0_i1;
p_regs->bias = (uint32_t) bias_data;
p_regs->result = (uint32_t) compute;

p_regs->oc = oc;
p_regs->iw = iw;
p_regs->ih = ih;
p_regs->ic = ic;
p_regs->kh = kh;
p_regs->kw = kw;
p_regs->i_zp = i_zp;
p_regs->k_zp = k_zp;
p_regs->control = 1; //issue start signal

// volatile uint32_t * status_reg = (int32_t*) 0x70000034;

volatile int32_t ready = 0;


while (!ready) {

ready = 0x1 & (p_regs->status);

// printf("ready = %d\n", ready);

}

printf("staus: completed (driver)\n");



return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@


#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>


#ifdef __cplusplus
extern "C"
#endif

/*!
* \brief Conv2D function for mock-accelerator examples. Limited to same-padded Conv2D with
* stride (1,1) and datatype int8, as well as a bias addition. \param ifmap Pointer to input feature map data of size
* iw*ih*ic*sizeof(int8). \param weights Pointer to weight data of size
* kh*kw*ic**oc*sizeof(int8). \param bias_data Pointer to bias data of size oc*sizeof(int32).
* \param result Pointer to output feature map data of size
* iw*ih*oc*sizeof(int32). \param oc Number of channels of output feature map. \param iw Width
* of input feature map, ifmap. \param ih Height of input feature map, ifmap. \param ic Number
* of channels of input feature map. \param kh Height of convolution kernels. \param kw Width of
* convolution kernels.\param i_zp and k_zp zero point parameters of
* input feature map and kernel.
*
* \return error code
*
*/
typedef struct regs
{
uint32_t ifmap;
uint32_t weights;
uint32_t bias;
uint32_t result;
int32_t oc;
int32_t iw;
int32_t ih;
int32_t ic;
int32_t kh;
int32_t kw;
int32_t i_zp;
int32_t k_zp;
uint32_t control;
} regs_t;

int q_vanilla_accelerator_conv2dnchw(int8_t* q_vanilla_accelerator_0_i0, int8_t* q_vanilla_accelerator_0_i1, int32_t* bias_data, int32_t* compute,
int32_t oc, int32_t iw, int32_t ih, int32_t ic, int32_t kh, int32_t kw, int32_t i_zp, int32_t k_zp) {


// QVanillaAccelerator (without timing) base_adr = 0x70000000,
regs_t *p_regs = (regs_t *)0x70000000;

p_regs->ifmap = (uint32_t) q_vanilla_accelerator_0_i0;
p_regs->weights = (uint32_t) q_vanilla_accelerator_0_i1;
p_regs->bias = (uint32_t) bias_data;
p_regs->result = (uint32_t) compute;

p_regs->oc = oc;
p_regs->iw = iw;
p_regs->ih = ih;
p_regs->ic = ic;
p_regs->kh = kh;
p_regs->kw = kw;
p_regs->i_zp = i_zp;
p_regs->k_zp = k_zp;
p_regs->control = 1; //issue start signal

return 0;
}
Loading

0 comments on commit e24ec10

Please sign in to comment.