From 86cfce6fb93c825f4f15bbe4b40e347733567ca9 Mon Sep 17 00:00:00 2001 From: Bumblebee00 Date: Mon, 2 Mar 2026 19:31:53 +0100 Subject: [PATCH 1/3] add placeholdeer code for spatz platform --- Deeploy/Targets/Spatz/Deployer.py | 48 +++++++++++++++++++++ Deeploy/Targets/Spatz/Platform.py | 71 +++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 Deeploy/Targets/Spatz/Deployer.py create mode 100644 Deeploy/Targets/Spatz/Platform.py diff --git a/Deeploy/Targets/Spatz/Deployer.py b/Deeploy/Targets/Spatz/Deployer.py new file mode 100644 index 0000000000..2442059606 --- /dev/null +++ b/Deeploy/Targets/Spatz/Deployer.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import Callable, Dict, Type + +import onnx_graphsurgeon as gs + +from Deeploy.AbstractDataTypes import Pointer +from Deeploy.CommonExtensions.NetworkDeployers.SignPropDeployer import SignPropDeployer +from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.DebugPasses import DebugPrintMergePass +from Deeploy.CommonExtensions.OptimizationPasses.TopologyOptimizationPasses.LoweringOptimizationPasses import \ + NCHWtoNHWCPass, TransposeMatmulInputsPass +from Deeploy.DeeployTypes import DeploymentPlatform, TopologyOptimizer +from Deeploy.Targets.Generic.TopologyOptimizationPasses.Passes import TransposeConstOptPass, TransposeMergePass + + +class SpatzDeployer(SignPropDeployer): + + def __init__(self, + graph: gs.Graph, + deploymentPlatform: DeploymentPlatform, + inputTypes: Dict[str, Type[Pointer]], + loweringOptimizer: TopologyOptimizer, + scheduler: Callable = lambda x: x, + name: str = 'DeeployNetwork', + default_channels_first = False, + deeployStateDir: str = "DeeployStateDir", + inputOffsets: Dict[str, int] = {}): + + super().__init__(graph, + deploymentPlatform, + inputTypes, + loweringOptimizer, + scheduler, + name, + default_channels_first = default_channels_first, + deeployStateDir = deeployStateDir) + +# self.inputOffsets = inputOffsets +# +# self.loweringOptimizer.passes += [ +# TransposeMatmulInputsPass(), +# NCHWtoNHWCPass(self.default_channels_first), +# TransposeMergePass(), +# TransposeConstOptPass(), +# DebugPrintMergePass() +# ] diff --git a/Deeploy/Targets/Spatz/Platform.py b/Deeploy/Targets/Spatz/Platform.py new file mode 100644 index 0000000000..89e8b9b411 --- /dev/null +++ b/Deeploy/Targets/Spatz/Platform.py @@ -0,0 +1,71 @@ +from typing import List + +from Deeploy.DeeployTypes import VariableBuffer, TransientBuffer, ConstantBuffer, StructBuffer, \ + NodeMapper, NodeTemplate, TopologyOptimizer, DeploymentEngine, DeploymentPlatform + +# from Deeploy.Targets.Spatz.Bindings import SpatzAddBindings # <- TODO create this +from Deeploy.Targets.Generic.Bindings import BasicAddBindings +from Deeploy.Targets.Generic.Layers import AddLayer +from Deeploy.Targets.Generic.Parsers import AddParser + +# TODO delete this and use from Deeploy.Targets.Spatz.Templates import AllocateTemplate as SpatzAllocateTemplate +from Deeploy.Targets.Generic.Templates import AllocateTemplate as GenericAllocateTemplate +from Deeploy.Targets.Generic.Templates import FreeTemplate as GenericFreeTemplate + +SpatzAddMapper = NodeMapper(AddParser(), BasicAddBindings) + +SpatzMapping = { + 'Add': AddLayer([SpatzAddMapper]), + # sparse attention : ... +} + + +class SpatzaVariableBuffer(VariableBuffer): + initTemplate = GenericAllocateTemplate.referenceInitTemplate + allocTemplate = GenericAllocateTemplate.referenceAllocateTemplate + deallocTemplate = GenericFreeTemplate.referenceLocalTemplate + + +class SpatzTransientBuffer(TransientBuffer): + initTemplate = GenericAllocateTemplate.referenceInitTemplate + allocTemplate = GenericAllocateTemplate.referenceAllocateTemplate + deallocTemplate = GenericFreeTemplate.referenceLocalTemplate + + +class SpatzConstantBuffer(ConstantBuffer): + initTemplate = GenericAllocateTemplate.referenceGlobalInitTemplate + allocTemplate = GenericAllocateTemplate.referenceGlobalAllocateTemplate + deallocTemplate = NodeTemplate("") # const not deallocated + + +class SpatzStructBuffer(StructBuffer): + initTemplate = GenericAllocateTemplate.referenceStructInitTemplate + allocTemplate = GenericAllocateTemplate.referenceStructAllocateTemplate + deallocTemplate = NodeTemplate("") # struct not deallocated ? + + +SpatzOptimizer = TopologyOptimizer([ + # TODO add something ? +], name = "SpatzOptimizer") + +includeList = [ + # TODO ??? +] + + +class SpatzEngine(DeploymentEngine): + def __init__(self, name: str, Mapping = SpatzMapping, initCode = "", includeList = includeList) -> None: + super().__init__(name, Mapping, initCode, includeList) + + +class SpatzPlatform(DeploymentPlatform): + + def __init__( self, + engines = [SpatzEngine("SpatzVectorProcessor")], + variableBuffer = SpatzaVariableBuffer, + transientBuffer = SpatzTransientBuffer, + constantBuffer = SpatzConstantBuffer, + structBuffer = SpatzStructBuffer, + includeList: List[str] = includeList + ): + super().__init__(engines, variableBuffer, constantBuffer, structBuffer, transientBuffer) From 077455632e0477415ada9ec2089ba752d0879f7d Mon Sep 17 00:00:00 2001 From: Bumblebee00 Date: Mon, 2 Mar 2026 19:33:03 +0100 Subject: [PATCH 2/3] code generation with generic c code --- DeeployTest/Platforms/Spatz/main.c | 65 ++++++++++++++++++++++++ DeeployTest/testUtils/platformMapping.py | 19 ++++++- 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 DeeployTest/Platforms/Spatz/main.c diff --git a/DeeployTest/Platforms/Spatz/main.c b/DeeployTest/Platforms/Spatz/main.c new file mode 100644 index 0000000000..e2b0449fb5 --- /dev/null +++ b/DeeployTest/Platforms/Spatz/main.c @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "Network.h" +#include "testinputs.h" +#include "testoutputs.h" + +int main() { + + printf("Initializing network...\r\n"); + + InitNetwork(0, 1); + + for (uint32_t buf = 0; buf < DeeployNetwork_num_inputs; buf++) { + memcpy(DeeployNetwork_inputs[buf], testInputVector[buf], + DeeployNetwork_inputs_bytes[buf]); + } + + printf("Running network...\r\n"); + RunNetwork(0, 1); + + int32_t tot_err = 0; + uint32_t tot = 0; + OUTPUTTYPE diff; + OUTPUTTYPE expected, actual; + + for (uint32_t buf = 0; buf < DeeployNetwork_num_outputs; buf++) { + tot += DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); + for (uint32_t i = 0; + i < DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); i++) { + expected = ((OUTPUTTYPE *)testOutputVector[buf])[i]; + actual = ((OUTPUTTYPE *)DeeployNetwork_outputs[buf])[i]; + diff = expected - actual; + +#if ISOUTPUTFLOAT == 1 + // RUNWANG: Allow margin of error for float32_t + if ((diff < -1e-4) || (diff > 1e-4)) { + tot_err += 1; + printf("Expected: %10.6f ", (float)expected); + printf("Actual: %10.6f ", (float)actual); + printf("Diff: %10.6f at Index %12u in Output %u\r\n", (float)diff, i, + buf); + } +#else + // RUNWANG: No margin for integer comparison + if (diff != 0) { + tot_err += 1; + printf("Expected: %4d ", expected); + printf("Actual: %4d ", actual); + printf("Diff: %4d at Index %12u in Output %u\r\n", diff, i, buf); + } +#endif + } + } + + printf("Errors: %d out of %d \r\n", tot_err, tot); + + return tot_err; +} \ No newline at end of file diff --git a/DeeployTest/testUtils/platformMapping.py b/DeeployTest/testUtils/platformMapping.py index 9d526906f9..69a83f1e8d 100644 --- a/DeeployTest/testUtils/platformMapping.py +++ b/DeeployTest/testUtils/platformMapping.py @@ -10,6 +10,8 @@ from Deeploy.DeeployTypes import DeploymentPlatform, NetworkDeployer, TopologyOptimizer from Deeploy.MemoryLevelExtension.MemoryLevels import MemoryHierarchy, MemoryLevel from Deeploy.MemoryLevelExtension.NetworkDeployers.MemoryLevelDeployer import MemoryPlatform, MemoryPlatformWrapper +from Deeploy.Targets.Spatz.Deployer import SpatzDeployer +from Deeploy.Targets.Spatz.Platform import SpatzOptimizer, SpatzPlatform from Deeploy.Targets.Chimera.Deployer import ChimeraDeployer from Deeploy.Targets.Chimera.Platform import ChimeraOptimizer, ChimeraPlatform from Deeploy.Targets.CortexM.Deployer import CMSISDeployer @@ -31,7 +33,7 @@ from Deeploy.Targets.SoftHier.Platform import SoftHierOptimizer, SoftHierPlatform _SIGNPROP_PLATFORMS = ["Apollo3", "Apollo4", "QEMU-ARM", "Generic", "MemPool", "SoftHier"] -_NONSIGNPROP_PLATFORMS = ["Siracusa", "Siracusa_w_neureka", "PULPOpen", "Snitch", "Chimera", "GAP9"] +_NONSIGNPROP_PLATFORMS = ["Siracusa", "Siracusa_w_neureka", "PULPOpen", "Snitch", "Chimera", "GAP9", "Spatz"] _PLATFORMS = _SIGNPROP_PLATFORMS + _NONSIGNPROP_PLATFORMS @@ -76,6 +78,9 @@ def mapPlatform(platformName: str) -> Tuple[DeploymentPlatform, bool]: elif platformName == "Chimera": Platform = ChimeraPlatform() + elif platformName == "Spatz": + Platform = SpatzPlatform() + else: raise RuntimeError(f"Deployment platform {platformName} is not implemented") @@ -272,6 +277,18 @@ def mapDeployer(platform: DeploymentPlatform, name = name, default_channels_first = default_channels_first, deeployStateDir = deeployStateDir) + + elif isinstance(platform, (SpatzPlatform)): + deployer = SpatzDeployer( + graph, + platform, + inputTypes, + SpatzOptimizer, + scheduler, + name = name, + default_channels_first = default_channels_first, + deeployStateDir = deeployStateDir + ) else: raise RuntimeError(f"Deployer for platform {platform} is not implemented") From a8fd323b7cbb92c32b6833e8c6e4cfde231642b1 Mon Sep 17 00:00:00 2001 From: Bumblebee00 Date: Thu, 12 Mar 2026 22:18:52 +0100 Subject: [PATCH 3/3] modified spatz c code to use proper memory allocation and copying functions --- DeeployTest/Platforms/Spatz/main.c | 88 ++++++++++++++++-------------- TargetLibraries/Spatz/inc/utils.h | 2 + TargetLibraries/Spatz/src/Util.c | 3 + 3 files changed, 51 insertions(+), 42 deletions(-) create mode 100644 TargetLibraries/Spatz/inc/utils.h create mode 100644 TargetLibraries/Spatz/src/Util.c diff --git a/DeeployTest/Platforms/Spatz/main.c b/DeeployTest/Platforms/Spatz/main.c index e2b0449fb5..2ab98ce54d 100644 --- a/DeeployTest/Platforms/Spatz/main.c +++ b/DeeployTest/Platforms/Spatz/main.c @@ -1,65 +1,69 @@ -/* - * SPDX-FileCopyrightText: 2023 ETH Zurich and University of Bologna - * - * SPDX-License-Identifier: Apache-2.0 - */ #include #include +#include "printf.h" #include "Network.h" #include "testinputs.h" #include "testoutputs.h" int main() { + const unsigned int cid = snrt_cluster_core_idx(); - printf("Initializing network...\r\n"); + // do it only with one of the two spatz cores + if (cid==0){ + printf("Initializing network...\r\n"); - InitNetwork(0, 1); + InitNetwork(0, 1); - for (uint32_t buf = 0; buf < DeeployNetwork_num_inputs; buf++) { - memcpy(DeeployNetwork_inputs[buf], testInputVector[buf], - DeeployNetwork_inputs_bytes[buf]); - } + for (uint32_t buf = 0; buf < DeeployNetwork_num_inputs; buf++) { + snrt_dma_start_1d(DeeployNetwork_inputs[buf], testInputVector[buf], DeeployNetwork_inputs_bytes[buf]); + } - printf("Running network...\r\n"); - RunNetwork(0, 1); + printf("Running network...\r\n"); + RunNetwork(0, 1); - int32_t tot_err = 0; - uint32_t tot = 0; - OUTPUTTYPE diff; - OUTPUTTYPE expected, actual; + int32_t tot_err = 0; + uint32_t tot = 0; + OUTPUTTYPE diff; + OUTPUTTYPE expected, actual; - for (uint32_t buf = 0; buf < DeeployNetwork_num_outputs; buf++) { - tot += DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); - for (uint32_t i = 0; - i < DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); i++) { - expected = ((OUTPUTTYPE *)testOutputVector[buf])[i]; - actual = ((OUTPUTTYPE *)DeeployNetwork_outputs[buf])[i]; - diff = expected - actual; + for (uint32_t buf = 0; buf < DeeployNetwork_num_outputs; buf++) { + tot += DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); + for (uint32_t i = 0; + i < DeeployNetwork_outputs_bytes[buf] / sizeof(OUTPUTTYPE); i++) { + expected = ((OUTPUTTYPE *)testOutputVector[buf])[i]; + actual = ((OUTPUTTYPE *)DeeployNetwork_outputs[buf])[i]; + diff = expected - actual; #if ISOUTPUTFLOAT == 1 - // RUNWANG: Allow margin of error for float32_t - if ((diff < -1e-4) || (diff > 1e-4)) { - tot_err += 1; - printf("Expected: %10.6f ", (float)expected); - printf("Actual: %10.6f ", (float)actual); - printf("Diff: %10.6f at Index %12u in Output %u\r\n", (float)diff, i, - buf); - } + // RUNWANG: Allow margin of error for float32_t + if ((diff < -1e-4) || (diff > 1e-4)) { + tot_err += 1; + printf("Expected: %10.6f ", (float)expected); + printf("Actual: %10.6f ", (float)actual); + printf("Diff: %10.6f at Index %12u in Output %u\r\n", (float)diff, i, + buf); + } #else - // RUNWANG: No margin for integer comparison - if (diff != 0) { - tot_err += 1; - printf("Expected: %4d ", expected); - printf("Actual: %4d ", actual); - printf("Diff: %4d at Index %12u in Output %u\r\n", diff, i, buf); - } + // RUNWANG: No margin for integer comparison + if (diff != 0) { + tot_err += 1; + printf("Expected: %4d ", expected); + printf("Actual: %4d ", actual); + printf("Diff: %4d at Index %12u in Output %u\r\n", diff, i, buf); + } #endif + } } - } - printf("Errors: %d out of %d \r\n", tot_err, tot); + printf("Errors: %d out of %d \r\n", tot_err, tot); - return tot_err; + return tot_err; + } else { + // wait for core 0 to finish + snrt_cluster_hw_barrier(); + return 0; + } + } \ No newline at end of file diff --git a/TargetLibraries/Spatz/inc/utils.h b/TargetLibraries/Spatz/inc/utils.h new file mode 100644 index 0000000000..88c7dc8f78 --- /dev/null +++ b/TargetLibraries/Spatz/inc/utils.h @@ -0,0 +1,2 @@ +#include +void *deeploy_malloc(const size_t size) ; diff --git a/TargetLibraries/Spatz/src/Util.c b/TargetLibraries/Spatz/src/Util.c new file mode 100644 index 0000000000..daf546f649 --- /dev/null +++ b/TargetLibraries/Spatz/src/Util.c @@ -0,0 +1,3 @@ +#include "utils.h" + +void *deeploy_malloc(const size_t size) { return snrt_l1alloc(size); }