Skip to content
Snippets Groups Projects
Commit 55cbf4a2 authored by Cyril Moineau's avatar Cyril Moineau
Browse files

Remove old operators

parent 9ab3fd7a
No related branches found
No related tags found
No related merge requests found
import os
import shutil
import numpy as np
from pathlib import Path
from jinja2 import Environment, FileSystemLoader
from aidge_core import ExportNode
from aidge_export_arm_cortexm.utils import ROOT, operator_register
##############################################
############## Export functions ##############
##############################################
def generate_file(filename, templatename, **kwargs):
# Get directory name of the file
dirname = os.path.dirname(filename)
# If directory doesn't exist, create it
if not os.path.exists(dirname):
os.makedirs(dirname)
# Get directory name and name of the template
template_dir = os.path.dirname(templatename)
template_name = os.path.basename(templatename)
# Select template
template = Environment(loader=FileSystemLoader(template_dir)).get_template(template_name)
# Generate file
content = template.render(kwargs)
with open(filename, mode="w", encoding="utf-8") as message:
message.write(content)
def generate_action(template_path, **kwargs):
dirname = os.path.dirname(template_path)
filename = os.path.basename(template_path)
template = Environment(loader=FileSystemLoader(dirname)).get_template(filename)
return template.render(kwargs)
def copyfile(filename, dst_folder):
# If directory doesn't exist, create it
if not os.path.exists(dst_folder):
os.makedirs(dst_folder)
shutil.copy(filename, dst_folder)
def export_to_static(name, array, filepath):
# Get directory name of the file
dirname = os.path.dirname(filepath)
# If directory doesn't exist, create it
if not os.path.exists(dirname):
os.makedirs(dirname)
generate_file(
filepath,
str(ROOT) + "/templates/data/data_static.jinja",
dims = array.shape,
data_t = "float",
name = name,
values = array.tolist()
)
##############################################
################### Utils ####################
##############################################
def get_node_parents(node):
parents = []
for parent in node.get_parents():
if parent.type() != "Producer":
parents.append(parent)
return parents
def get_producer_parents(node):
parents = []
for parent in node.get_parents():
if parent.type() == "Producer":
parents.append(parent)
return parents
##############################################
################### Actions ##################
##############################################
def set_up_output(name, datatype):
return f"{datatype}* {name} = ({datatype}*) mem + {name.upper()}_OFFSET;"
##############################################
############## Operators helper ##############
##############################################
@operator_register("Add")
class Add(ExportNode):
def __init__(self, node, board, dataformat, library):
# Copy dims for first input
node.get_operator().get_output(0).resize(node.get_operator().get_input(0).dims())
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
def export(self, export_folder:str, list_configs:list):
# Copying kernel into export
# Find a more generic system for future dev
if self.library == "aidge":
if self.dataformat == "float32":
copyfile(str(ROOT / "kernels" / "ElemWise" / "Add" / "aidge_add_float32.c"),
str(Path(export_folder) / "src" / "kernels"))
# Add to config list the include of configurations
list_configs.append(f"layers/{self.name}.h")
# Export configuration file
generate_file(
f"{export_folder}/layers/{self.name}.h",
str(ROOT / "templates" / "configuration" / "elemwise.jinja"),
name=self.name,
elemwise_op="\"ADD\"",
nb_inputs=np.prod(self.inputs_dims[0]),
nb_outputs=np.prod(self.outputs_dims[0]))
return list_configs
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel" / "elemwise.jinja"),
name=self.name,
elemwise_type="add",
dataformat="float32", # Only this choice so far
input1_name=self.inputs[0].name(),
input2_name=self.inputs[1].name(),
output_name=self.name
))
return list_actions
@operator_register("Sub")
class Sub(ExportNode):
def __init__(self, node, board, dataformat, library):
# Copy dims for first input
node.get_operator().get_output(0).resize(node.get_operator().get_input(0).dims())
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
def export(self, export_folder:str, list_configs:list):
# Copying kernel into export
# Find a more generic system for future dev
if self.library == "aidge":
if self.dataformat == "float32":
copyfile(str(ROOT / "kernels" / "ElemWise" / "Sub" / "aidge_sub_float32.c"),
str(Path(export_folder) / "src" / "kernels"))
# Add to config list the include of configurations
list_configs.append(f"layers/{self.name}.h")
# Export configuration file
generate_file(
f"{export_folder}/layers/{self.name}.h",
str(ROOT / "templates" / "configuration" / "elemwise.jinja"),
name=self.name,
elemwise_op="\"SUB\"",
nb_inputs=np.prod(self.inputs_dims[0]),
nb_outputs=np.prod(self.outputs_dims[0]))
return list_configs
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel" / "elemwise.jinja"),
name=self.name,
elemwise_type="sub",
dataformat="float32", # Only this choice so far
input1_name=self.inputs[0].name(),
input2_name=self.inputs[1].name(),
output_name=self.name
))
return list_actions
@operator_register("Mul")
class Mul(ExportNode):
def __init__(self, node, board, dataformat, library):
# Copy dims for first input
node.get_operator().get_output(0).resize(node.get_operator().get_input(0).dims())
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
def export(self, export_folder:str, list_configs:list):
# Copying kernel into export
# Find a more generic system for future dev
if self.library == "aidge":
if self.dataformat == "float32":
copyfile(str(ROOT / "kernels" / "ElemWise" / "Mul" / "aidge_mul_float32.c"),
str(Path(export_folder) / "src" / "kernels"))
# Add to config list the include of configurations
list_configs.append(f"layers/{self.name}.h")
# Export configuration file
generate_file(
f"{export_folder}/layers/{self.name}.h",
str(ROOT / "templates" / "configuration" / "elemwise.jinja"),
name=self.name,
elemwise_op="\"MUL\"",
nb_inputs=np.prod(self.inputs_dims[0]),
nb_outputs=np.prod(self.outputs_dims[0]))
return list_configs
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel" / "elemwise.jinja"),
name=self.name,
elemwise_type="mul",
dataformat="float32", # Only this choice so far
input1_name=self.inputs[0].name(),
input2_name=self.inputs[1].name(),
output_name=self.name
))
return list_actions
@operator_register("Div")
class Div(ExportNode):
def __init__(self, node, board, dataformat, library):
# Copy dims for first input
node.get_operator().get_output(0).resize(node.get_operator().get_input(0).dims())
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
def export(self, export_folder:str, list_configs:list):
# Copying kernel into export
# Find a more generic system for future dev
if self.library == "aidge":
if self.dataformat == "float32":
copyfile(str(ROOT / "kernels" / "ElemWise" / "Div" / "aidge_div_float32.c"),
str(Path(export_folder) / "src" / "kernels"))
# Add to config list the include of configurations
list_configs.append(f"layers/{self.name}.h")
# Export configuration file
generate_file(
f"{export_folder}/layers/{self.name}.h",
str(ROOT / "templates" / "configuration" / "elemwise.jinja"),
name=self.name,
elemwise_op="\"DIV\"",
nb_inputs=np.prod(self.inputs_dims[0]),
nb_outputs=np.prod(self.outputs_dims[0]))
return list_configs
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel" / "elemwise.jinja"),
name=self.name,
elemwise_type="div",
dataformat="float32", # Only this choice so far
input1_name=self.inputs[0].name(),
input2_name=self.inputs[1].name(),
output_name=self.name
))
return list_actions
@operator_register("Gemm")
class Gemm(ExportNode):
def __init__(self, node, board, dataformat, library):
w_dims = node.get_operator().get_input(1).dims()
node.get_operator().get_output(0).resize([w_dims[1]])
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
def export(self, export_folder:str, list_configs:list):
# Copying kernel into export
# Find a more generic system for future dev
if self.library == "aidge":
if self.dataformat == "float32":
copyfile(str(ROOT / "kernels" / "FullyConnected" / "aidge_fc_float32.c"),
str(Path(export_folder) / "src" / "kernels"))
# Add to config list the include of configurations
list_configs.append(f"layers/{self.name}.h")
# Export configuration file
generate_file(
f"{export_folder}/layers/{self.name}.h",
str(ROOT / "templates" / "configuration" / "fullyconnected.jinja"),
name=self.name,
nb_channels=self.inputs_dims[0][0],
nb_outputs=self.outputs_dims[0][0],
biases_size=self.outputs_dims[0][0])
return list_configs
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel" / "fullyconnected.jinja"),
name=self.name,
dataformat="float32", # Only this choice so far
input_name=self.inputs[0].name(),
weight_name=self.inputs[1].name(),
bias_name=self.inputs[2].name(),
output_name=self.name
))
return list_actions
@operator_register("Atan")
class Atan(ExportNode):
def __init__(self, node, board, dataformat, library):
# Copy dims for first input
node.get_operator().get_output(0).resize(node.get_operator().get_input(0).dims())
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
def export(self, export_folder:str, list_configs:list):
# Copying kernel into export
# Find a more generic system for future dev
if self.library == "aidge":
if self.dataformat == "float32":
copyfile(str(ROOT / "kernels" / "Activation" / "Atan" / "aidge_atan_float32.c"),
str(Path(export_folder) / "src" / "kernels"))
# Add to config list the include of configurations
list_configs.append(f"layers/{self.name}.h")
# Export configuration file
generate_file(
f"{export_folder}/layers/{self.name}.h",
str(ROOT / "templates" / "configuration" / "activation.jinja"),
name=self.name,
activation_type="\"ATAN\"",
nb_inputs=np.prod(self.inputs_dims[0]),
nb_outputs=np.prod(self.outputs_dims[0]))
return list_configs
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel" / "activation.jinja"),
name=self.name,
activation_type="atan",
dataformat="float32", # Only this choice so far
input_name=self.inputs[0].name(),
output_name=self.name
))
return list_actions
@operator_register("Slice")
class Slice(ExportNode):
def __init__(self, node, board, dataformat, library):
self.axes = node.get_operator().attr.axes
self.starts = node.get_operator().attr.starts
self.ends = node.get_operator().attr.ends
# Compute output dims
out_dims = [self.ends[x-1] - self.starts[x-1] for x in self.axes]
node.get_operator().get_output(0).resize(out_dims)
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
def export(self, export_folder:str, list_configs:list):
# Copying kernel into export
# Find a more generic system for future dev
if self.library == "aidge":
if self.dataformat == "float32":
copyfile(str(ROOT / "kernels" / "Slice" / "aidge_slice_float32.c"),
str(Path(export_folder) / "src" / "kernels"))
# Add to config list the include of configurations
list_configs.append(f"layers/{self.name}.h")
# Export configuration file
generate_file(
f"{export_folder}/layers/{self.name}.h",
str(ROOT / "templates" / "configuration" / "slice.jinja"),
name=self.name,
axes=self.axes,
starts=self.starts,
ends=self.ends,
nb_inputs=np.prod(self.inputs_dims[0]),
nb_outputs=np.prod(self.outputs_dims[0]))
return list_configs
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel" / "slice.jinja"),
name=self.name,
dataformat="float32", # Only this choice so far
input_name=self.inputs[0].name(),
output_name=self.name
))
return list_actions
@operator_register("Concat")
class Concat(ExportNode):
def __init__(self, node, board, dataformat, library):
self.axis = node.get_operator().attr.axis
out_dims = node.get_operator().get_input(0).dims()
out_dims[self.axis - 1] = 0
for parent in node.get_parents():
out_dims[self.axis - 1] += parent.get_operator().get_output(0).dims()[self.axis - 1]
node.get_operator().get_output(0).resize(out_dims)
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
def export(self, export_folder:str, list_configs:list):
# Copying kernel into export
# Find a more generic system for future dev
if self.library == "aidge":
if self.dataformat == "float32":
copyfile(str(ROOT / "kernels" / "Concat" / "aidge_concat_float32.c"),
str(Path(export_folder) / "src" / "kernels"))
# Add to config list the include of configurations
list_configs.append(f"layers/{self.name}.h")
# Get all input size
list_input_size = []
for i in range(len(self.inputs)):
list_input_size.append(np.prod(self.node.get_operator().get_input(i).dims()))
# Export configuration file
generate_file(
f"{export_folder}/layers/{self.name}.h",
str(ROOT / "templates" / "configuration" / "concat.jinja"),
name=self.name,
nb_inputs=len(self.node.get_parents()),
axis=self.axis,
list_input_size=list_input_size,
output_size=np.sum(list_input_size)
)
return list_configs
def forward(self, list_actions:list):
if not self.is_last:
list_actions.append(set_up_output(self.name, "float"))
list_input_names = []
for i in range(len(self.inputs)):
list_input_names.append(self.inputs[i].name())
list_actions.append(generate_action(
str(ROOT / "templates" / "kernel" / "concat.jinja"),
name=self.name,
dataformat="float32",
nb_inputs=len(self.inputs),
list_in_names=list_input_names,
output_name=self.name,
))
return list_actions
@operator_register("Producer")
class Producer(ExportNode):
"""
If there is a standardization of the export operators
then this class should be just a inheritance of ProducerCPP
"""
def __init__(self, node, board, dataformat, library):
super().__init__(node)
self.board = board
self.library = library
self.dataformat = dataformat
self.values = np.array(self.operator.get_output(0))
def export(self, export_folder:str, list_configs:list):
list_configs.append(f"parameters/{self.name}.h")
export_to_static(self.name,
self.values.reshape(-1),
f"{export_folder}/parameters/{self.name}.h")
return list_configs
def forward(self, list_actions:list):
return list_actions
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment