From fe8cad1255a1b3d07f9361f1892b96f535447e7e Mon Sep 17 00:00:00 2001
From: Axel Farrugia <axel.farrugia@cea.fr>
Date: Tue, 18 Feb 2025 11:28:54 +0100
Subject: [PATCH 1/2] [Feat](Exports) Add a copy_folder function and allow the
 copies to be done through simlinks

---
 aidge_core/export_utils/__init__.py         |  2 +-
 aidge_core/export_utils/code_generation.py  | 23 +++++++++++++++++++--
 aidge_core/export_utils/export_registry.py  |  3 +++
 aidge_core/export_utils/scheduler_export.py |  8 +++++--
 4 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/aidge_core/export_utils/__init__.py b/aidge_core/export_utils/__init__.py
index 72472eee0..a14fc63b1 100644
--- a/aidge_core/export_utils/__init__.py
+++ b/aidge_core/export_utils/__init__.py
@@ -1,5 +1,5 @@
 from .node_export import ExportNode, ExportNodeCpp
-from .code_generation import generate_file, generate_str, copy_file
+from .code_generation import generate_file, generate_str, copy_file, copy_folder
 from .export_registry import ExportLib
 from .scheduler_export import scheduler_export
 from .tensor_export import tensor_to_c, generate_input_file
diff --git a/aidge_core/export_utils/code_generation.py b/aidge_core/export_utils/code_generation.py
index 4f0f4634d..42ae19f79 100644
--- a/aidge_core/export_utils/code_generation.py
+++ b/aidge_core/export_utils/code_generation.py
@@ -44,10 +44,29 @@ def generate_str(template_path: Union[Path, str], **kwargs) -> str:
     return Environment(loader=FileSystemLoader(
         template_path.parent), undefined=StrictUndefined, keep_trailing_newline=True).get_template(template_path.name).render(kwargs)
 
-def copy_file(filename, dst_folder):
+def copy_file(filename, dst_folder, symlink=False):
+    """Copy the given file into the given dst path
+    The symlink arg allows to make a symbolic link instead of copying the file.
+    """
 
     # If directory doesn't exist, create it
     if not os.path.exists(dst_folder):
         os.makedirs(dst_folder)
 
-    shutil.copy(filename, dst_folder)
+    if symlink:
+        dst_folder += "/" + os.path.basename(filename)
+        if not os.path.exists(dst_folder):
+            os.symlink(filename, dst_folder)
+    else:
+        shutil.copy(filename, dst_folder)
+
+def copy_folder(foldername, dst_folder, symlink=False):
+    """Copy the given folder into the given dst path
+    The symlink arg allows to make a symbolic link instead of copying the file.
+    """
+
+    if symlink:
+        os.symlink(foldername, dst_folder)
+    else:
+        shutil.copytree(foldername, dst_folder, dirs_exist_ok=True)
+    
\ No newline at end of file
diff --git a/aidge_core/export_utils/export_registry.py b/aidge_core/export_utils/export_registry.py
index 8927ae516..01329e6a5 100644
--- a/aidge_core/export_utils/export_registry.py
+++ b/aidge_core/export_utils/export_registry.py
@@ -40,6 +40,9 @@ class ExportLib(aidge_core.OperatorImpl):
     # key: Path where static file is
     # Value: Path where to copy the file relative to the export root
     static_files: Dict[str, str] = {}
+    # key: Path where static folder is
+    # Value: Path where to copy the folder relative to the export root
+    static_folders: Dict[str, str] = {}
     # Main memory section
     mem_section = None
     # Custom forward generation jinja file
diff --git a/aidge_core/export_utils/scheduler_export.py b/aidge_core/export_utils/scheduler_export.py
index 0995e4cea..222699ca9 100644
--- a/aidge_core/export_utils/scheduler_export.py
+++ b/aidge_core/export_utils/scheduler_export.py
@@ -2,7 +2,7 @@ import aidge_core
 import os
 import shutil
 from pathlib import Path
-from aidge_core.export_utils import ExportLib, generate_file, copy_file
+from aidge_core.export_utils import ExportLib, generate_file, copy_file, copy_folder
 from typing import List, Tuple
 
 
@@ -208,4 +208,8 @@ def scheduler_export(scheduler, export_folder_path: str, export_lib: ExportLib =
     if export_lib is not None:
         # Copy all static files in the export
         for source, destination in export_lib.static_files.items():
-            copy_file(source, str(export_folder / destination))
+            copy_file(source, str(export_folder / destination), test_mode)
+            
+        # Copy all static folders in the export
+        for source, destination in export_lib.static_folders.items():
+            copy_folder(source, str(export_folder / destination), test_mode)
-- 
GitLab


From 5f9cff678d9bc3c4df77e34fab058c8e2ec9cc51 Mon Sep 17 00:00:00 2001
From: Axel Farrugia <axel.farrugia@cea.fr>
Date: Tue, 18 Feb 2025 11:29:16 +0100
Subject: [PATCH 2/2] [Feat] Add numpy2c converter

---
 aidge_core/export_utils/__init__.py        |  1 +
 aidge_core/export_utils/data_conversion.py | 28 ++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/aidge_core/export_utils/__init__.py b/aidge_core/export_utils/__init__.py
index a14fc63b1..bee59efd0 100644
--- a/aidge_core/export_utils/__init__.py
+++ b/aidge_core/export_utils/__init__.py
@@ -4,3 +4,4 @@ from .export_registry import ExportLib
 from .scheduler_export import scheduler_export
 from .tensor_export import tensor_to_c, generate_input_file
 from .generate_main import generate_main_cpp, generate_main_compare_cpp
+from .data_conversion import aidge2c, aidge2export_type, numpy2c
diff --git a/aidge_core/export_utils/data_conversion.py b/aidge_core/export_utils/data_conversion.py
index 6dba5b78c..9866cf60c 100644
--- a/aidge_core/export_utils/data_conversion.py
+++ b/aidge_core/export_utils/data_conversion.py
@@ -48,3 +48,31 @@ def aidge2export_type(datatype: aidge_core.dtype, conversion_map: Dict[aidge_cor
         return conversion_map[datatype]
     else:
         raise ValueError(f"Unsupported type conversion {datatype} aidge datatype for export")
+
+datatype_converter_numpy2c = {
+    np.float64 : "double",
+    np.float32 : "float",
+    np.float16 : "half_float::half",
+    np.int8    : "int8_t",
+    np.int16   : "int16_t",
+    np.int32   : "int32_t",
+    np.int64   : "int64_t",
+    np.uint8   : "uint8_t",
+    np.uint16  : "uint16_t",
+    np.uint32  : "uint32_t",
+    np.uint64  : "uint64_t"
+}
+
+def numpy2c(datatype):
+    """Convert a numpy datatype to C type
+
+    If the type is not convertible to a C type (e.g. int4), return None and raise a warning.
+
+    :param datatype: Numpy datatype to convert
+    :return: A string representing the C type
+    :rtype: string
+    """
+    if datatype in datatype_converter_numpy2c:
+        return datatype_converter_numpy2c[datatype]
+    else:
+        raise ValueError(f"Unsupported {datatype} numpy datatype")
-- 
GitLab