diff --git a/include/aidge/backend/cpu/operator/SliceImpl.hpp b/include/aidge/backend/cpu/operator/SliceImpl.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d27aa83c288c85c894bee7687122c264c7b40b2
--- /dev/null
+++ b/include/aidge/backend/cpu/operator/SliceImpl.hpp
@@ -0,0 +1,54 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#ifndef AIDGE_CPU_OPERATOR_SLICEIMPL_H_
+#define AIDGE_CPU_OPERATOR_SLICEIMPL_H_
+
+#include "aidge/backend/OperatorImpl.hpp"
+#include "aidge/operator/Slice.hpp"
+#include "aidge/utils/Registrar.hpp"
+#include "aidge/utils/Types.h"
+#include <memory>
+#include <vector>
+
+namespace Aidge {
+// class Slice_Op;
+
+// compute kernel registry for forward and backward
+class SliceImplForward_cpu
+    : public Registrable<SliceImplForward_cpu,
+                         std::tuple<DataType, DataType>,
+                         void(const std::vector<DimSize_t>, const void*, DimSize_t, const void*, const void*, const void*, void*)> {
+};
+class SliceImplBackward_cpu
+    : public Registrable<SliceImplBackward_cpu,
+                         std::tuple<DataType, DataType>,
+                         void(const std::vector<DimSize_t>, const void*, DimSize_t, const void*, const void*, const void*, void*)> {
+};
+
+class SliceImpl_cpu : public OperatorImpl {
+public:
+    SliceImpl_cpu(const Slice_Op& op) : OperatorImpl(op) {}
+
+    static std::unique_ptr<SliceImpl_cpu> create(const Slice_Op& op) {
+        return std::make_unique<SliceImpl_cpu>(op);
+    }
+
+    NbElts_t getNbRequiredProtected(const IOIndex_t inputIdx) const override final;
+    void forward() override;
+};
+
+namespace {
+static Registrar<Slice_Op> registrarSliceImpl_cpu("cpu", Aidge::SliceImpl_cpu::create);
+}
+}  // namespace Aidge
+
+#endif /* AIDGE_CPU_OPERATOR_SLICEIMPL_H_ */
diff --git a/include/aidge/backend/cpu/operator/SliceImpl_forward_kernels.hpp b/include/aidge/backend/cpu/operator/SliceImpl_forward_kernels.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ee670f819a2fe2722e6d9409e918da553c700676
--- /dev/null
+++ b/include/aidge/backend/cpu/operator/SliceImpl_forward_kernels.hpp
@@ -0,0 +1,106 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#ifndef AIDGE_CPU_OPERATOR_SLICEIMPL_FORWARD_KERNEL_H_
+#define AIDGE_CPU_OPERATOR_SLICEIMPL_FORWARD_KERNEL_H_
+
+#include "aidge/utils/Registrar.hpp"
+
+#include "aidge/backend/cpu/operator/SliceImpl.hpp"
+
+namespace Aidge {
+template <class I, class O>
+void SliceImpl_cpu_forward_kernel(const std::vector<DimSize_t> inputDims,
+                                const void* input_,
+                                DimSize_t nbSlices,
+                                const void* axes_,
+                                const void* starts_,
+                                const void* ends_,
+                                void* output_) {
+    const I* input = static_cast<const I*>(input_);
+    const int* axes = static_cast<const int*>(axes_);
+    const int* starts = static_cast<const int*>(starts_);
+    const int* ends = static_cast<const int*>(ends_);
+    O* output = static_cast<O*>(output_);
+
+    // Calculate the total number of elements in the input array
+    size_t totalElements = 1;
+    for (size_t dimSize : inputDims) {
+        totalElements *= dimSize;
+    }
+
+    // Create a temporary arrays to store intermediate input/output for each slice op
+    std::vector<I> tempInArray(input, input + totalElements);
+    std::vector<I> tempOutArray(input, input + totalElements);
+    std::vector<size_t> currentDims = inputDims;
+
+    size_t copiedElems = 0;
+    // Loop over each slice operation
+    for(size_t i=0; i< nbSlices; ++i)
+    {
+        copiedElems = 0;
+        I* tempOutArrayPtr = tempOutArray.data();
+        // Extract parameters for the current slice, make sure indexes are positive
+        size_t axisIdx = axes[i]>=0?axes[i]:(axes[i]+currentDims.size());
+        size_t startIdx = starts[i]>=0?starts[i]:(starts[i]+currentDims[axisIdx]);
+        size_t endIdx = ends[i]>=0?ends[i]:(ends[i]+currentDims[axisIdx]);
+
+
+        // Compute the size of the slice over each element on the axis
+        size_t strideOnCurrDim = 1;
+        for(size_t j=(axisIdx+1); j<currentDims.size(); ++j)
+        {
+            strideOnCurrDim *= currentDims[j];
+        }
+        size_t sliceSize  = (endIdx - startIdx) * strideOnCurrDim;
+
+        // For each slice operation, we will slice all elements on the axis (subSlice)
+        // the number of sublices is the product of dimension previous to the slice dimension
+        size_t nbSubSlices = 1;
+        for(size_t j=0; j<axisIdx; ++j)
+        {
+            nbSubSlices*=currentDims[j];
+        }
+
+        // Operate the slice over each element of the dim we want to slice
+        for(size_t s=0; s<nbSubSlices; ++s)
+        {
+            // Compute the pointer postion on input
+            std::size_t copyStartPos = s * strideOnCurrDim * currentDims[axisIdx] + strideOnCurrDim;
+            const I* copyPtr = std::next(tempInArray.data(), copyStartPos);
+            // Copy slice to output array and update pointer
+            std::copy_n(copyPtr, sliceSize , tempOutArrayPtr);
+            tempOutArrayPtr += sliceSize ;
+            copiedElems+= sliceSize ;
+        }
+
+        // Update the input for the next slice operation
+        tempInArray.assign(tempOutArray.begin(), tempOutArray.begin() + copiedElems);
+        currentDims[axisIdx] = endIdx - startIdx;
+    }
+
+    std::copy_n(tempInArray.data(), copiedElems, output);
+}
+
+namespace {
+static Registrar<SliceImplForward_cpu> registrarSliceImplForward_cpu_Float32(
+        {DataType::Float32, DataType::Float32},
+        Aidge::SliceImpl_cpu_forward_kernel<float, float>);
+static Registrar<SliceImplForward_cpu> registrarSliceImplForward_cpu_Int32(
+        {DataType::Int32, DataType::Int32},
+        Aidge::SliceImpl_cpu_forward_kernel<int, int>);
+static Registrar<SliceImplForward_cpu> registrarSliceImplForward_cpu_Float64(
+        {DataType::Float64, DataType::Float64},
+        Aidge::SliceImpl_cpu_forward_kernel<double, double>);
+}  // namespace
+}  // namespace Aidge
+
+#endif /* AIDGE_CPU_OPERATOR_SLICEIMPL_FORWARD_KERNEL_H_ */
diff --git a/src/operator/SliceImpl.cpp b/src/operator/SliceImpl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3eb57fb64a95a8717d99dc191648a2e2281b7a47
--- /dev/null
+++ b/src/operator/SliceImpl.cpp
@@ -0,0 +1,53 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include <cassert>
+#include <chrono>  // std::chrono::milliseconds
+#include <numeric> // std::accumulate
+#include <thread>  // std::this_thread::sleep_for
+#include <vector>
+
+#include "aidge/operator/Slice.hpp"
+#include "aidge/utils/Types.h"
+
+#include "aidge/backend/cpu/operator/SliceImpl.hpp"
+#include "aidge/backend/cpu/operator/SliceImpl_forward_kernels.hpp"
+
+Aidge::NbElts_t Aidge::SliceImpl_cpu::getNbRequiredProtected(const Aidge::IOIndex_t /*inputIdx*/) const {
+    // this implementation can be in-place
+    return 0;
+}
+
+void Aidge::SliceImpl_cpu::forward() {
+    assert(mOp.getInput(0) && "missing input #0");
+    assert(mOp.getInput(1) && "missing input #1"); //TODO fill axes (input #1) if not given
+    assert(mOp.getInput(2) && "missing input #2");
+    assert(mOp.getInput(3) && "missing input #3");
+    
+
+    assert((mOp.getInput(1)->nbDims() == 1) && "input #1 must either be a tensor of rank 1");
+    assert((mOp.getInput(2)->nbDims() == 1) && "input #2 must either be a tensor of rank 1");
+    assert((mOp.getInput(3)->nbDims() == 1) && "input #3 must either be a tensor of rank 1");
+
+    // Find the correct kernel type
+    auto kernelFunc = Registrar<SliceImplForward_cpu>::create({
+        mOp.getInput(0)->dataType(),
+        mOp.getInput(1)->dataType()});
+
+    // Call kernel
+    kernelFunc(mOp.getInput(0)->dims(),
+               mOp.getInput(0)->getImpl()->rawPtr(),
+               mOp.getInput(1)->dims()[0],
+               mOp.getInput(1)->getImpl()->rawPtr(),
+               mOp.getInput(2)->getImpl()->rawPtr(),
+               mOp.getInput(3)->getImpl()->rawPtr(),
+               mOp.getOutput(0)->getImpl()->rawPtr());
+}
\ No newline at end of file
diff --git a/unit_tests/operator/Test_SliceImpl.cpp b/unit_tests/operator/Test_SliceImpl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..94a2f4cc9337da368bd67785b29779ffb9d3d54a
--- /dev/null
+++ b/unit_tests/operator/Test_SliceImpl.cpp
@@ -0,0 +1,55 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include <catch2/catch_test_macros.hpp>
+
+#include "aidge/data/Tensor.hpp"
+#include "aidge/operator/Slice.hpp"
+
+#include "aidge/backend/cpu.hpp"
+
+#include <memory>
+
+using namespace Aidge;
+
+TEST_CASE("[cpu/operator] Slice(forward)") {
+    SECTION("2D Tensor") {
+        std::shared_ptr<Tensor> input = std::make_shared<Tensor>(Array2D<int,2,4> {
+            {
+                {1, 2, 3, 4},
+                {5, 6, 7, 8}
+            }
+        });
+        std::shared_ptr<Tensor> axes =  std::make_shared<Tensor>(Array1D<int,2>{{0, 1}});
+        std::shared_ptr<Tensor> starts =  std::make_shared<Tensor>(Array1D<int,2>{{1, 1}});
+        std::shared_ptr<Tensor> ends =  std::make_shared<Tensor>(Array1D<int,2>{{2, 4}});
+        std::shared_ptr<Tensor> expectedOutput = std::make_shared<Tensor>(Array2D<int,1,3> {
+            {
+                {6, 7, 8}
+            }
+        });
+
+        std::shared_ptr<Node> mySlice = Slice();
+        mySlice->getOperator()->setDatatype(DataType::Int32);
+        mySlice->getOperator()->setBackend("cpu");
+        mySlice->getOperator()->associateInput(0, input);
+        mySlice->getOperator()->associateInput(1, axes);
+        mySlice->getOperator()->associateInput(2, starts);
+        mySlice->getOperator()->associateInput(3, ends);
+        mySlice->getOperator()->computeOutputDims();
+        mySlice->forward();
+
+        REQUIRE(*std::static_pointer_cast<Tensor>(mySlice->getOperator()->getOutput(0)) == *expectedOutput);
+
+
+    }
+
+}
\ No newline at end of file