blob: 0a0aa2cf69a65c4d0024d243fe5e96146b8c78f8 [file]
# 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.
# pylint: disable=invalid-name, unused-argument
import pytest
pytest.importorskip("ethosu.vela")
import numpy as np
import tvm
from tvm import relay
from tvm.relay.backend.contrib.ethosu import preprocess
def set_func_attr(func, compile_name, symbol_name):
"""
Helper function to attach attributes to the external function.
"""
func = func.with_attr("Primitive", tvm.tir.IntImm("int32", 1))
func = func.with_attr("Inline", tvm.tir.IntImm("int32", 1))
func = func.with_attr("Compiler", compile_name)
func = func.with_attr("global_symbol", symbol_name)
return func
def test_single_io():
"""
This test will test the pass wont touch external functions that
have a single input and a single output.
"""
def create_graph():
def create_external_func1(mod_, compiler_name, symbol_name):
x_int = relay.var("x_int", shape=(10, 10))
z0 = relay.nn.relu(x_int)
f1 = relay.Function([x_int], z0)
f1 = set_func_attr(f1, compiler_name, symbol_name)
glb_f1 = relay.GlobalVar(symbol_name)
mod_[glb_f1] = f1
mod_ = relay.transform.InferType()(mod_)
return glb_f1, mod_
mod = tvm.IRModule()
x = relay.var("x", shape=(10, 10))
glb_symbol_f1, mod = create_external_func1(mod, "ethos-u", "ethosu_0")
r = relay.Call(glb_symbol_f1, [x])
main = relay.Function([x], r)
mod["main"] = main
mod = relay.transform.InferType()(mod)
return mod
mod = create_graph()
exp = create_graph()
mod = preprocess.preprocess_ext_io()(mod)
assert tvm.ir.structural_equal(mod, exp, map_free_vars=True)
def test_2ins_single_out():
"""
The test is check two inputs and a single output of external function
"""
def create_graph():
def create_external_func1(mod_, compiler_name, symbol_name):
x_int = relay.var("x_int", shape=(10, 10))
w0_int = relay.var("w0_int", shape=(10, 10))
z0 = relay.add(x_int, w0_int)
f1 = relay.Function([x_int, w0_int], z0)
f1 = set_func_attr(f1, compiler_name, symbol_name)
glb_f1 = relay.GlobalVar(symbol_name)
mod_[glb_f1] = f1
mod_ = relay.transform.InferType()(mod_)
return glb_f1, mod_
mod = tvm.IRModule()
x = relay.var("x", shape=(10, 10))
w0 = relay.var("w0", shape=(10, 10))
glb_symbol_f1, mod = create_external_func1(mod, "ethos-u", "ethosu_0")
r = relay.Call(glb_symbol_f1, [x, w0])
main = relay.Function([x, w0], r)
mod["main"] = main
mod = relay.transform.InferType()(mod)
return mod
def expected():
def create_external_func1(mod_, compiler_name, symbol_name):
ifms_int = relay.var("ifms_int", shape=[200])
# splits
(x_int_flat, w0_int_flat) = relay.split(ifms_int, [100])
# reshapes
x_int = relay.reshape(x_int_flat, newshape=(10, 10))
w0_int = relay.reshape(w0_int_flat, newshape=(10, 10))
z0 = relay.add(x_int, w0_int)
f1 = relay.Function([ifms_int], z0)
f1 = set_func_attr(f1, compiler_name, symbol_name)
glb_f1 = relay.GlobalVar(symbol_name)
mod_[glb_f1] = f1
mod_ = relay.transform.InferType()(mod_)
return glb_f1, mod_
mod = tvm.IRModule()
x = relay.var("x", shape=(10, 10))
w0 = relay.var("w0", shape=(10, 10))
# reshapes
x_reshaped = relay.reshape(x, newshape=100)
w0_reshaped = relay.reshape(w0, newshape=100)
# concat
ifms = relay.concatenate((x_reshaped, w0_reshaped), 0)
glb_symbol_f1, mod = create_external_func1(mod, "ethos-u", "ethosu_0")
r = relay.Call(glb_symbol_f1, [ifms])
main = relay.Function([x, w0], r)
mod["main"] = main
mod = relay.transform.InferType()(mod)
return mod
mod = create_graph()
exp = expected()
mod = preprocess.preprocess_ext_io()(mod)
assert tvm.ir.structural_equal(mod, exp, map_free_vars=True)
def test_single_in_2outs():
"""
The test is to check a single input and two outputs of external function
"""
def create_graph():
def create_external_func1(mod_, compiler_name, symbol_name):
x_int = relay.var("x_int", shape=(10, 10))
p0 = relay.nn.relu(x_int)
q0 = relay.tanh(x_int)
f1_o_tuple = relay.Tuple([p0, q0])
f1 = relay.Function([x_int], f1_o_tuple)
f1 = set_func_attr(f1, compiler_name, symbol_name)
glb_f1 = relay.GlobalVar(symbol_name)
mod_[glb_f1] = f1
mod_ = relay.transform.InferType()(mod_)
return glb_f1, mod_
mod = tvm.IRModule()
x = relay.var("x", shape=(10, 10))
glb_symbol_f1, mod = create_external_func1(mod, "ethos-u", "ethosu_0")
pq_tuple = relay.Call(glb_symbol_f1, [x])
p0 = relay.TupleGetItem(pq_tuple, 0)
q0 = relay.TupleGetItem(pq_tuple, 1)
r = relay.concatenate((p0, q0), axis=0)
main = relay.Function([x], r)
mod["main"] = main
mod = relay.transform.InferType()(mod)
return mod
def expected():
def create_external_func1(mod_, compiler_name, symbol_name):
x_int = relay.var("x_int", shape=(10, 10))
p0 = relay.nn.relu(x_int)
q0 = relay.tanh(x_int)
# reshapes
p0_reshaped = relay.reshape(p0, newshape=100)
q0_reshaped = relay.reshape(q0, newshape=100)
ofms = relay.concatenate((p0_reshaped, q0_reshaped), 0)
f1 = relay.Function([x_int], ofms)
f1 = set_func_attr(f1, compiler_name, symbol_name)
glb_f1 = relay.GlobalVar(symbol_name)
mod_[glb_f1] = f1
mod_ = relay.transform.InferType()(mod_)
return glb_f1, mod_
mod = tvm.IRModule()
x = relay.var("x", shape=(10, 10))
glb_symbol_f1, mod = create_external_func1(mod, "ethos-u", "ethosu_0")
ofms = relay.Call(glb_symbol_f1, [x])
# splits
(p0_flat, q0_flat) = relay.split(ofms, [100])
# reshapes
p0_flat_reshaped = relay.reshape(p0_flat, newshape=(10, 10))
q0_flat_reshaped = relay.reshape(q0_flat, newshape=(10, 10))
# original output
tuple_out = relay.Tuple([p0_flat_reshaped, q0_flat_reshaped])
p0 = relay.TupleGetItem(tuple_out, 0)
q0 = relay.TupleGetItem(tuple_out, 1)
r = relay.concatenate((p0, q0), axis=0)
main = relay.Function([x], r)
mod["main"] = main
mod = relay.transform.InferType()(mod)
return mod
mod = create_graph()
exp = expected()
mod = relay.transform.InferType()(mod)
mod = preprocess.preprocess_ext_io()(mod)
assert tvm.ir.structural_equal(mod, exp, map_free_vars=True)
def test_4ins_2outs():
"""
The test is to check a 4 inputs and two outputs of external function.
This just stand as a general test for multiple ins/outs.
"""
def create_graph():
def create_external_func1(mod_, compiler_name, symbol_name):
x_int = relay.var("x_int", shape=(10, 10))
w0_int = relay.var("w0_int", shape=(10, 10))
w1_int = relay.var("w1_int", shape=(10, 10))
w2_int = relay.var("w2_int", shape=(10, 10))
z0 = relay.add(x_int, w0_int)
p0 = relay.subtract(z0, w1_int)
q0 = relay.multiply(z0, w2_int)
f1_o_tuple = relay.Tuple([p0, q0])
f1 = relay.Function([x_int, w0_int, w1_int, w2_int], f1_o_tuple)
f1 = set_func_attr(f1, compiler_name, symbol_name)
glb_f1 = relay.GlobalVar(symbol_name)
mod_[glb_f1] = f1
mod_ = relay.transform.InferType()(mod_)
return glb_f1, mod_
mod = tvm.IRModule()
x = relay.var("x", shape=(10, 10))
w0 = relay.var("w0", shape=(10, 10))
w1 = relay.var("w1", shape=(10, 10))
w2 = relay.var("w2", shape=(10, 10))
glb_symbol_f1, mod = create_external_func1(mod, "ethos-u", "ethosu_0")
pq_tuple = relay.Call(glb_symbol_f1, [x, w0, w1, w2])
p0 = relay.TupleGetItem(pq_tuple, 0)
q0 = relay.TupleGetItem(pq_tuple, 1)
r = relay.concatenate((p0, q0), axis=0)
main = relay.Function([x, w0, w1, w2], r)
mod["main"] = main
mod = relay.transform.InferType()(mod)
return mod
def expected():
def create_external_func1(mod_, compiler_name, symbol_name):
ifms_int = relay.var("ifms_int", shape=[400])
# splits
(x_int_flat, w0_int_flat, w1_int_flat, w2_int_flat) = relay.split(
ifms_int, [100, 200, 300]
)
# reshapes
x_int = relay.reshape(x_int_flat, newshape=(10, 10))
w0_int = relay.reshape(w0_int_flat, newshape=(10, 10))
w1_int = relay.reshape(w1_int_flat, newshape=(10, 10))
w2_int = relay.reshape(w2_int_flat, newshape=(10, 10))
z0 = relay.add(x_int, w0_int)
p0 = relay.subtract(z0, w1_int)
q0 = relay.multiply(z0, w2_int)
# f1_o_tuple = relay.Tuple([p0, q0])
# reshapes
p0_reshaped = relay.reshape(p0, newshape=100)
q0_reshaped = relay.reshape(q0, newshape=100)
ofms = relay.concatenate((p0_reshaped, q0_reshaped), 0)
f1 = relay.Function([ifms_int], ofms)
f1 = set_func_attr(f1, compiler_name, symbol_name)
glb_f1 = relay.GlobalVar(symbol_name)
mod_[glb_f1] = f1
mod_ = relay.transform.InferType()(mod_)
return glb_f1, mod_
mod = tvm.IRModule()
x = relay.var("x", shape=(10, 10))
w0 = relay.var("w0", shape=(10, 10))
w1 = relay.var("w1", shape=(10, 10))
w2 = relay.var("w2", shape=(10, 10))
# reshapes
x_reshaped = relay.reshape(x, newshape=100)
w0_reshaped = relay.reshape(w0, newshape=100)
w1_reshaped = relay.reshape(w1, newshape=100)
w2_reshaped = relay.reshape(w2, newshape=100)
# concat
ifms = relay.concatenate((x_reshaped, w0_reshaped, w1_reshaped, w2_reshaped), 0)
# call
glb_func, mod = create_external_func1(mod, "ethos-u", "ethosu_0")
ofms = relay.Call(glb_func, [ifms])
# splits
(p0_flat, q0_flat) = relay.split(ofms, [100])
# reshapes
p0_flat_reshaped = relay.reshape(p0_flat, newshape=(10, 10))
q0_flat_reshaped = relay.reshape(q0_flat, newshape=(10, 10))
# original output
tuple_out = relay.Tuple([p0_flat_reshaped, q0_flat_reshaped])
p0 = relay.TupleGetItem(tuple_out, 0)
q0 = relay.TupleGetItem(tuple_out, 1)
r = relay.concatenate((p0, q0), axis=0)
main = relay.Function([x, w0, w1, w2], r)
mod["main"] = main
mod = relay.transform.InferType()(mod)
return mod
mod = create_graph()
exp = expected()
mod = preprocess.preprocess_ext_io()(mod)
assert tvm.ir.structural_equal(mod, exp, map_free_vars=True)
if __name__ == "__main__":
tvm.testing.main()