From 7824a5e6cac9e6d20e2bb3f19a398c1cde440477 Mon Sep 17 00:00:00 2001 From: Johan Gunnarsson Date: Thu, 19 Jun 2025 12:38:22 +0200 Subject: [PATCH] MLBEDSW-10906: Increase raw format shapes to 6D Was previously 4D, which meant that networks with >4D inputs or outputs would have their shapes truncated in the raw format metadata. Signed-off-by: Johan Gunnarsson Change-Id: I0c9e791940d04418a59de609f99bd66f60deb903 --- ethosu/regor/bindings/python/py_regor.cpp | 9 ++-- ethosu/regor/compiler/raw_writer.cpp | 12 ++--- ethosu/regor/include/regor.h | 8 ++-- ethosu/regor/test/test_raw_writer.cpp | 58 +++++++++++++---------- test/test_ethos_u_vela.py | 6 +-- 5 files changed, 51 insertions(+), 42 deletions(-) diff --git a/ethosu/regor/bindings/python/py_regor.cpp b/ethosu/regor/bindings/python/py_regor.cpp index c7a2df4d..a08c1755 100644 --- a/ethosu/regor/bindings/python/py_regor.cpp +++ b/ethosu/regor/bindings/python/py_regor.cpp @@ -1,5 +1,5 @@ // -// SPDX-FileCopyrightText: Copyright 2021, 2023-2024 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright 2021, 2023-2025 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 // @@ -450,7 +450,7 @@ private: address = header.tensor.input.address; data_size = header.tensor.input.size; element_size = header.tensor.input.element_size; - shape.insert(shape.end(), header.tensor.input.shape, header.tensor.input.shape + 4); + shape.insert(shape.end(), std::begin(header.tensor.input.shape), std::end(header.tensor.input.shape)); raw.inputs.emplace_back(region, address, size, element_size, shape); break; case regor_raw_tensor_header_t::RAW_TENSOR_TYPE_OUTPUT: @@ -458,7 +458,7 @@ private: address = header.tensor.output.address; data_size = header.tensor.output.size; element_size = header.tensor.output.element_size; - shape.insert(shape.end(), header.tensor.output.shape, header.tensor.output.shape + 4); + shape.insert(shape.end(), std::begin(header.tensor.output.shape), std::end(header.tensor.output.shape)); raw.outputs.emplace_back(region, address, size, element_size, shape); break; case regor_raw_tensor_header_t::RAW_TENSOR_TYPE_VARIABLE: @@ -466,7 +466,8 @@ private: address = header.tensor.variable.address; data_size = header.tensor.variable.size; element_size = header.tensor.variable.element_size; - shape.insert(shape.end(), header.tensor.variable.shape, header.tensor.variable.shape + 4); + shape.insert(shape.end(), std::begin(header.tensor.variable.shape), + std::end(header.tensor.variable.shape)); raw.variables.emplace_back(region, address, size, element_size, shape); break; default: diff --git a/ethosu/regor/compiler/raw_writer.cpp b/ethosu/regor/compiler/raw_writer.cpp index b2a85013..9cd1482d 100644 --- a/ethosu/regor/compiler/raw_writer.cpp +++ b/ethosu/regor/compiler/raw_writer.cpp @@ -232,8 +232,8 @@ void RawWriter::SerialiseInputTensor(const Tensor *tensor, Address address) header.type = regor_raw_tensor_header_t::RAW_TENSOR_TYPE_INPUT; header.tensor.input.region = INPUT_REGION; header.tensor.input.element_size = DataTypeStorageSizeBytes(tensor->Type(), 1); - auto shape = Shape::PadAxes(tensor->StorageShape(), 4, 1).ToList(); - std::copy(shape.begin(), shape.end(), header.tensor.input.shape); + auto shape = Shape::PadAxes(tensor->StorageShape(), 6, 1).ToList(); + std::copy_n(shape.begin(), 6, header.tensor.input.shape); header.tensor.input.size = DataTypeStorageSizeBytes(tensor->Type(), tensor->StorageShape().Elements()); header.tensor.input.address = address; @@ -255,8 +255,8 @@ void RawWriter::SerialiseOutputTensor(const Tensor *tensor, Address address) header.type = regor_raw_tensor_header_t::RAW_TENSOR_TYPE_OUTPUT; header.tensor.output.region = OUTPUT_REGION; header.tensor.output.element_size = DataTypeStorageSizeBytes(tensor->Type(), 1); - auto shape = Shape::PadAxes(tensor->StorageShape(), 4, 1).ToList(); - std::copy(shape.begin(), shape.end(), header.tensor.output.shape); + auto shape = Shape::PadAxes(tensor->StorageShape(), 6, 1).ToList(); + std::copy_n(shape.begin(), 6, header.tensor.output.shape); header.tensor.output.size = DataTypeStorageSizeBytes(tensor->Type(), tensor->StorageShape().Elements()); header.tensor.output.address = address; @@ -278,8 +278,8 @@ void RawWriter::SerialiseVariableTensor(const Tensor *tensor, Address address) header.type = regor_raw_tensor_header_t::RAW_TENSOR_TYPE_VARIABLE; header.tensor.variable.region = VARIABLE_REGION; header.tensor.variable.element_size = DataTypeStorageSizeBytes(tensor->Type(), 1); - auto shape = Shape::PadAxes(tensor->StorageShape(), 4, 1).ToList(); - std::copy(shape.begin(), shape.end(), header.tensor.variable.shape); + auto shape = Shape::PadAxes(tensor->StorageShape(), 6, 1).ToList(); + std::copy_n(shape.begin(), 6, header.tensor.variable.shape); header.tensor.variable.size = DataTypeStorageSizeBytes(tensor->Type(), tensor->StorageShape().Elements()); header.tensor.variable.address = address; diff --git a/ethosu/regor/include/regor.h b/ethosu/regor/include/regor.h index 59fc1885..f38a64c9 100644 --- a/ethosu/regor/include/regor.h +++ b/ethosu/regor/include/regor.h @@ -1,5 +1,5 @@ // -// SPDX-FileCopyrightText: Copyright 2021-2024 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright 2021-2025 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 // @@ -148,7 +148,7 @@ typedef struct regor_raw_tensor_header_t uint32_t size; uint64_t address; uint8_t element_size; - uint32_t shape[4]; + uint32_t shape[6]; } input; struct { @@ -156,7 +156,7 @@ typedef struct regor_raw_tensor_header_t uint32_t size; uint64_t address; uint8_t element_size; - uint32_t shape[4]; + uint32_t shape[6]; } output; struct { @@ -164,7 +164,7 @@ typedef struct regor_raw_tensor_header_t uint32_t size; uint64_t address; uint8_t element_size; - uint32_t shape[4]; + uint32_t shape[6]; } variable; } tensor; } regor_raw_tensor_header_t; diff --git a/ethosu/regor/test/test_raw_writer.cpp b/ethosu/regor/test/test_raw_writer.cpp index 6838b73f..1204970f 100644 --- a/ethosu/regor/test/test_raw_writer.cpp +++ b/ethosu/regor/test/test_raw_writer.cpp @@ -1,5 +1,5 @@ // -// SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright 2024-2025 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 // @@ -49,19 +49,19 @@ TEST_CASE("raw_writer") REQUIRE_FALSE(scratchFast->IsConstant()); // Build input tensor - const auto input = std::make_shared("input_1", DataType::Int8, Shape({1, 1, 8})); + const auto input = std::make_shared("input_1", DataType::Int8, Shape::FromVector({2, 3, 4, 5, 6, 7})); REQUIRE_FALSE(input->IsConstant()); // Build output tensor - const auto output = std::make_shared("output_1", DataType::Int8, Shape({1, 1, 1, 10})); + const auto output = std::make_shared("output_1", DataType::Int8, Shape::FromVector({3, 4, 5, 6, 7, 8})); REQUIRE_FALSE(output->IsConstant()); // Build variable tensor - const auto variable1 = std::make_shared("variable_1", DataType::Int8, Shape({1, 1, 1, 9})); + const auto variable1 = std::make_shared("variable_1", DataType::Int8, Shape::FromVector({4, 5, 6, 7, 8, 9})); REQUIRE_FALSE(variable1->IsConstant()); // Build another variable tensor - const auto variable2 = std::make_shared("variable_2", DataType::Int8, Shape({1, 1, 1, 11})); + const auto variable2 = std::make_shared("variable_2", DataType::Int8, Shape::FromVector({5, 6, 7, 8, 9, 10})); REQUIRE_FALSE(variable2->IsConstant()); // Create custom op @@ -186,14 +186,16 @@ TEST_CASE("raw_writer") regor_raw_tensor_header_t header; std::copy_n(data.get(), sizeof(header), reinterpret_cast(&header)); REQUIRE(header.type == regor_raw_tensor_header_t::RAW_TENSOR_TYPE_INPUT); - REQUIRE(header.tensor.input.size == 8); + REQUIRE(header.tensor.input.size == 2 * 3 * 4 * 5 * 6 * 7); REQUIRE(header.tensor.input.region == 1); REQUIRE(header.tensor.input.address == 88); REQUIRE(header.tensor.input.element_size == 1); - REQUIRE(header.tensor.input.shape[0] == 1); - REQUIRE(header.tensor.input.shape[1] == 1); - REQUIRE(header.tensor.input.shape[2] == 1); - REQUIRE(header.tensor.input.shape[3] == 8); + REQUIRE(header.tensor.input.shape[0] == 2); + REQUIRE(header.tensor.input.shape[1] == 3); + REQUIRE(header.tensor.input.shape[2] == 4); + REQUIRE(header.tensor.input.shape[3] == 5); + REQUIRE(header.tensor.input.shape[4] == 6); + REQUIRE(header.tensor.input.shape[5] == 7); } // Check output @@ -207,14 +209,16 @@ TEST_CASE("raw_writer") regor_raw_tensor_header_t header; std::copy_n(data.get(), sizeof(header), reinterpret_cast(&header)); REQUIRE(header.type == regor_raw_tensor_header_t::RAW_TENSOR_TYPE_OUTPUT); - REQUIRE(header.tensor.output.size == 10); + REQUIRE(header.tensor.output.size == 3 * 4 * 5 * 6 * 7 * 8); REQUIRE(header.tensor.output.region == 1); REQUIRE(header.tensor.output.address == 99); REQUIRE(header.tensor.output.element_size == 1); - REQUIRE(header.tensor.output.shape[0] == 1); - REQUIRE(header.tensor.output.shape[1] == 1); - REQUIRE(header.tensor.output.shape[2] == 1); - REQUIRE(header.tensor.output.shape[3] == 10); + REQUIRE(header.tensor.output.shape[0] == 3); + REQUIRE(header.tensor.output.shape[1] == 4); + REQUIRE(header.tensor.output.shape[2] == 5); + REQUIRE(header.tensor.output.shape[3] == 6); + REQUIRE(header.tensor.output.shape[4] == 7); + REQUIRE(header.tensor.output.shape[5] == 8); } // Check (input) variable @@ -228,14 +232,16 @@ TEST_CASE("raw_writer") regor_raw_tensor_header_t header; std::copy_n(data.get(), sizeof(header), reinterpret_cast(&header)); REQUIRE(header.type == regor_raw_tensor_header_t::RAW_TENSOR_TYPE_VARIABLE); - REQUIRE(header.tensor.input.size == 9); + REQUIRE(header.tensor.input.size == 4 * 5 * 6 * 7 * 8 * 9); REQUIRE(header.tensor.input.region == 1); REQUIRE(header.tensor.input.address == 11); REQUIRE(header.tensor.input.element_size == 1); - REQUIRE(header.tensor.input.shape[0] == 1); - REQUIRE(header.tensor.input.shape[1] == 1); - REQUIRE(header.tensor.input.shape[2] == 1); - REQUIRE(header.tensor.input.shape[3] == 9); + REQUIRE(header.tensor.input.shape[0] == 4); + REQUIRE(header.tensor.input.shape[1] == 5); + REQUIRE(header.tensor.input.shape[2] == 6); + REQUIRE(header.tensor.input.shape[3] == 7); + REQUIRE(header.tensor.input.shape[4] == 8); + REQUIRE(header.tensor.input.shape[5] == 9); } // Check (output) variable @@ -249,13 +255,15 @@ TEST_CASE("raw_writer") regor_raw_tensor_header_t header; std::copy_n(data.get(), sizeof(header), reinterpret_cast(&header)); REQUIRE(header.type == regor_raw_tensor_header_t::RAW_TENSOR_TYPE_VARIABLE); - REQUIRE(header.tensor.input.size == 11); + REQUIRE(header.tensor.input.size == 5 * 6 * 7 * 8 * 9 * 10); REQUIRE(header.tensor.input.region == 1); REQUIRE(header.tensor.input.address == 22); REQUIRE(header.tensor.input.element_size == 1); - REQUIRE(header.tensor.input.shape[0] == 1); - REQUIRE(header.tensor.input.shape[1] == 1); - REQUIRE(header.tensor.input.shape[2] == 1); - REQUIRE(header.tensor.input.shape[3] == 11); + REQUIRE(header.tensor.input.shape[0] == 5); + REQUIRE(header.tensor.input.shape[1] == 6); + REQUIRE(header.tensor.input.shape[2] == 7); + REQUIRE(header.tensor.input.shape[3] == 8); + REQUIRE(header.tensor.input.shape[4] == 9); + REQUIRE(header.tensor.input.shape[5] == 10); } } diff --git a/test/test_ethos_u_vela.py b/test/test_ethos_u_vela.py index 9cd9dcd3..e1fd13ef 100644 --- a/test/test_ethos_u_vela.py +++ b/test/test_ethos_u_vela.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2021-2024 Arm Limited and/or its affiliates +# SPDX-FileCopyrightText: Copyright 2021-2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: Apache-2.0 # @@ -114,11 +114,11 @@ def test_ethos_u_vela_with_regor_raw_output(tmp_path): assert raw["scratch_fast_shape"].tolist() == [0] assert raw["scratch_fast_region"] == 0 assert raw["scratch_fast_size"] == 0 - assert raw["input_shape"][0].tolist() == [1, 64, 64, 16] + assert raw["input_shape"][0].tolist() == [1, 1, 1, 64, 64, 16] assert raw["input_elem_size"][0] == 1 assert raw["input_region"][0] == 1 assert raw["input_offset"][0] >= 0 - assert raw["output_shape"][0].tolist() == [1, 64, 64, 8] + assert raw["output_shape"][0].tolist() == [1, 1, 1, 64, 64, 8] assert raw["output_elem_size"][0] == 1 assert raw["output_region"][0] == 1 assert raw["output_offset"][0] >= 0 -- GitLab