From 119138f505855208a553c4df4e2a8e5681096c74 Mon Sep 17 00:00:00 2001 From: Jacob Bohlin Date: Thu, 9 Jan 2025 11:56:43 +0000 Subject: [PATCH] MLBEDSW-8927 Add Ethos-U55/U65 support for MIRROR_PAD in Regor * Updated the regor Ethos-U55/U65 backend to handle OFM reverse in H and W axes. * Added architectural constraints for negative striding in order to force linear format for OFM reversals for Ethos-U55/U65. * Minor print-formatting change to high_level_command_stream.py. Change-Id: I30b97b8c7fadf5306ca960bd4b45087513270864 Signed-off-by: Jacob Bohlin --- .../architecture/architecture_constraints.hpp | 1 + .../ethosu55/ethos_u55_constraints.hpp | 3 ++- .../ethos_u55_register_cs_generator.cpp | 23 +++++++++++++++++++ .../ethosu85/ethos_u85_constraints.hpp | 3 ++- ethosu/regor/compiler/scheduler.cpp | 7 +++++- ethosu/vela/high_level_command_stream.py | 4 ++-- 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/ethosu/regor/architecture/architecture_constraints.hpp b/ethosu/regor/architecture/architecture_constraints.hpp index 76795730..f1171ea8 100644 --- a/ethosu/regor/architecture/architecture_constraints.hpp +++ b/ethosu/regor/architecture/architecture_constraints.hpp @@ -102,6 +102,7 @@ public: virtual TransposeSupport SupportsTranspose(OpType opType, TransposeType transposeType) = 0; virtual bool SupportsAccumulatorSaveRestore() = 0; virtual bool SupportsLeakyRelu(bool quantized, DataType type) = 0; + virtual bool SupportsNegativeStrides() = 0; bool CanExecute(const ExecutionQuery &query) { diff --git a/ethosu/regor/architecture/ethosu55/ethos_u55_constraints.hpp b/ethosu/regor/architecture/ethosu55/ethos_u55_constraints.hpp index e2c16f0e..045125f5 100644 --- a/ethosu/regor/architecture/ethosu55/ethos_u55_constraints.hpp +++ b/ethosu/regor/architecture/ethosu55/ethos_u55_constraints.hpp @@ -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 // @@ -41,6 +41,7 @@ public: bool SupportsArgMax(OpType opType) override; bool SupportsCast(OpType opType, DataType ifmType, DataType ofmType) override; bool SupportsNonMatchingShapes(const Shape &ifmShape, const Shape &ifm2Shape, const Shape &ofmShape) override; + bool SupportsNegativeStrides() override { return true; }; private: ArchEthosU55 *_arch; diff --git a/ethosu/regor/architecture/ethosu55/ethos_u55_register_cs_generator.cpp b/ethosu/regor/architecture/ethosu55/ethos_u55_register_cs_generator.cpp index 7d49aa49..ce64579a 100644 --- a/ethosu/regor/architecture/ethosu55/ethos_u55_register_cs_generator.cpp +++ b/ethosu/regor/architecture/ethosu55/ethos_u55_register_cs_generator.cpp @@ -349,6 +349,18 @@ TileBox EthosU55RCSGenerator::GetTiles(const HLCFeatureMap &fm, const Shape &str } int fmSize = fm.AllocationSizeBytes(); tiles.address[0] = AddressForCoordinate(fm, strides, area.Start()); + auto elementSize = DataTypeSizeBits(fm.dataType) / 8; + auto depth = fm.shape.Depth(); + if ( fm.reverse == ReverseType::H ) + { + assert(fm.format == TensorFormat::NHWC); + tiles.address[0] += (tiles.height0 - 1) * fm.shape.Width() * depth * elementSize; + } + if ( fm.reverse == ReverseType::W ) + { + assert(fm.format == TensorFormat::NHWC); + tiles.address[0] += (tiles.width0 - 1) * depth * elementSize; + } assert(fm.address <= tiles.address[0] && tiles.address[0] < fm.address + fmSize); if ( area.End().Width() > crossingX ) { @@ -1008,6 +1020,17 @@ void EthosU55RCSGenerator::GenerateOFM(OpType opType, const HLCFeatureMap &fm, c Emit(isa::npu_set_ofm_width0_m1_t(tiles.width0 - 1)); Emit(isa::npu_set_ofm_depth_m1_t(boxSize.Depth() - 1)); // OFM_STRIDE registers + // Make X/Y stride negative if the OFM should be reversed in that axis. + if ( fm.reverse == ReverseType::H ) + { + assert(fm.format == TensorFormat::NHWC); + strides = strides.WithHeight(-strides.Height()); + } + if ( fm.reverse == ReverseType::W ) + { + assert(fm.format == TensorFormat::NHWC); + strides = strides.WithWidth(-strides.Width()); + } Emit(isa::npu_set_ofm_stride_y_t(strides.Height() * fm.stepXY.y)); Emit(isa::npu_set_ofm_stride_x_t(strides.Width() * fm.stepXY.x)); Emit(isa::npu_set_ofm_stride_c_t(strides.Depth())); diff --git a/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.hpp b/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.hpp index 228c0825..bd939523 100644 --- a/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.hpp +++ b/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.hpp @@ -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 // @@ -41,6 +41,7 @@ public: bool SupportsArgMax(OpType opType) override; bool SupportsCast(OpType opType, DataType ifmType, DataType ofmType) override; bool SupportsNonMatchingShapes(const Shape &ifmShape, const Shape &ifm2Shape, const Shape &ofmShape) override; + bool SupportsNegativeStrides() override { return false; }; private: ArchEthosU85 *_arch; diff --git a/ethosu/regor/compiler/scheduler.cpp b/ethosu/regor/compiler/scheduler.cpp index 5523bd16..8d1e181d 100644 --- a/ethosu/regor/compiler/scheduler.cpp +++ b/ethosu/regor/compiler/scheduler.cpp @@ -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 // @@ -210,6 +210,11 @@ static int UpdateSchedulerTensor(Architecture *arch, TensorUsage usage, Schedule { tensor->needsLinearFormat = true; } + // Force linear format for any reversal using negative striding + if ( arch->Constraints()->SupportsNegativeStrides() && conn->reverse != ReverseType::None ) + { + tensor->needsLinearFormat = true; + } for ( auto producer : tensor->producers ) { diff --git a/ethosu/vela/high_level_command_stream.py b/ethosu/vela/high_level_command_stream.py index 8403b94f..bb4ddfec 100644 --- a/ethosu/vela/high_level_command_stream.py +++ b/ethosu/vela/high_level_command_stream.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright 2020-2023 Arm Limited and/or its affiliates +# SPDX-FileCopyrightText: Copyright 2020-2023, 2025 Arm Limited and/or its affiliates # # SPDX-License-Identifier: Apache-2.0 # @@ -179,7 +179,7 @@ class Box: return Block.from_shape(self.get_size_shape()) def __str__(self): - return "" % (self.start_coord, self.end_coord) + return "" % ([int(x) for x in self.start_coord], [int(x) for x in self.end_coord]) __repr__ = __str__ -- GitLab