diff --git a/ethosu/regor/architecture/ethosu55/ethos_u55_weight_encoder.cpp b/ethosu/regor/architecture/ethosu55/ethos_u55_weight_encoder.cpp index afb1b670d0b781108f94fd17dd56648bc003591f..d3b96116ee4eab9fabf9b0c7f0fc2abdb6472dd4 100644 --- a/ethosu/regor/architecture/ethosu55/ethos_u55_weight_encoder.cpp +++ b/ethosu/regor/architecture/ethosu55/ethos_u55_weight_encoder.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 // @@ -41,12 +41,7 @@ EthosU55WeightEncoder::EthosUEncodingConfig::EthosUEncodingConfig(int cores) : _ void EthosU55WeightEncoder::EthosUEncodingConfig::Rehash() { - _depthOffsetHash = 0; - for ( int offset : this->depthOffsets ) - { - _depthOffsetHash = _depthOffsetHash * 31 ^ offset; - } - + _depthOffsetHash = HashVector32(depthOffsets); _hash = SimpleHash32(ofmBlockDepth, traversal, _depthOffsetHash, ifmType, dilation, ohwiStrides); } @@ -73,8 +68,8 @@ Flags EthosU55WeightEncoder::EthosUEncodingConfig::Format() } -std::unique_ptr EthosU55WeightEncoder::GetEncodingConfig(ArchitectureOpConfig *opCfg, - const WeightsRef &weights, const Kernel *kernel, DataType ifmType, const std::vector &depthOffsets, Flags) +std::unique_ptr EthosU55WeightEncoder::GetEncodingConfig(ArchitectureOpConfig *opCfg, const WeightsRef &weights, + const Kernel *kernel, DataType ifmType, int depthBase, const std::vector &depthOffsets, Flags) { assert(opCfg); assert(kernel); @@ -83,10 +78,11 @@ std::unique_ptr EthosU55WeightEncoder::GetEncodingConfig( EthosU55OpConfig *opConfig = static_cast(opCfg); params->ofmBlockDepth = opConfig->OfmBlock().Depth(); params->traversal = opConfig->Traversal(); - params->depthOffsets = depthOffsets; params->ifmType = ifmType; params->dilation = kernel->Dilation(); + std::for_each(depthOffsets.begin(), depthOffsets.end(), [&](int d) { params->depthOffsets.push_back(d + depthBase); }); + if ( !weights.isScales ) { Shape ohwiStrides = weights.view->StrideBytes() * 8 / DataTypeSizeBits(weights.type); diff --git a/ethosu/regor/architecture/ethosu55/ethos_u55_weight_encoder.hpp b/ethosu/regor/architecture/ethosu55/ethos_u55_weight_encoder.hpp index 2d76faf294a3bb52e9ec829fc61b3980921ad7ab..6230b254a7dd28c2d55a9b96d119c45bc9a8362e 100644 --- a/ethosu/regor/architecture/ethosu55/ethos_u55_weight_encoder.hpp +++ b/ethosu/regor/architecture/ethosu55/ethos_u55_weight_encoder.hpp @@ -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 // @@ -63,7 +63,7 @@ public: public: std::unique_ptr GetEncodingConfig(ArchitectureOpConfig *opCfg, const WeightsRef &weights, - const Kernel *kernel, DataType ifmType, const std::vector &depthOffsets, Flags format); + const Kernel *kernel, DataType ifmType, int depthBase, const std::vector &depthOffsets, Flags format); int StreamsRequired(IWeightEncodingConfig *config, const Shape &weightShape, int &scaleStreamsRequired); diff --git a/ethosu/regor/architecture/ethosu85/ethos_u85_weight_encoder.cpp b/ethosu/regor/architecture/ethosu85/ethos_u85_weight_encoder.cpp index 6357a29b6b48e8e0cfa768aba35cb7264405effa..feaf76c9957ca00f015bac8c4c90b1d74f34eed2 100644 --- a/ethosu/regor/architecture/ethosu85/ethos_u85_weight_encoder.cpp +++ b/ethosu/regor/architecture/ethosu85/ethos_u85_weight_encoder.cpp @@ -44,13 +44,9 @@ EthosU85WeightEncoder::EthosUEncodingConfig::EthosUEncodingConfig(int cores, Fla void EthosU85WeightEncoder::EthosUEncodingConfig::Rehash() { - _depthOffsetHash = 0; - for ( int offset : this->depthOffsets ) - { - _depthOffsetHash = _depthOffsetHash * 31 ^ offset; - } - - _hash = SimpleHash32(_depthOffsetHash, ifmType, ofmBlockDepth, ifmBlockDepth, traversal, acc, dilation, stride, ohwiStrides, ofmUBlock); + _depthOffsetHash = HashVector32(depthOffsets); + _hash = SimpleHash32(_depthOffsetHash, ifmType, ofmBlockDepth, ifmBlockDepth, traversal, acc, dilation, stride, + ohwiStrides, ofmUBlock, _weightFormat); } uint32_t EthosU85WeightEncoder::EthosUEncodingConfig::Hash() @@ -77,7 +73,7 @@ Flags EthosU85WeightEncoder::EthosUEncodingConfig::Format() std::unique_ptr EthosU85WeightEncoder::GetEncodingConfig(ArchitectureOpConfig *opCfg, const WeightsRef &weights, - const Kernel *kernel, DataType ifmType, const std::vector &depthOffsets, Flags format) + const Kernel *kernel, DataType ifmType, int depthBase, const std::vector &depthOffsets, Flags format) { assert(opCfg); assert(kernel); @@ -89,11 +85,12 @@ std::unique_ptr EthosU85WeightEncoder::GetEncodingConfig( params->ifmBlockDepth = opConfig->IfmBlock().Depth(); params->traversal = opConfig->Traversal(); params->acc = opConfig->Acc(); - params->depthOffsets = depthOffsets; params->ifmType = ifmType; params->dilation = kernel->Dilation(); params->stride = kernel->Stride(); + std::for_each(depthOffsets.begin(), depthOffsets.end(), [&](int d) { params->depthOffsets.push_back(d + depthBase); }); + if ( !weights.isScales ) { Shape ohwiStrides = weights.view->StrideBytes() * 8 / DataTypeSizeBits(weights.type); diff --git a/ethosu/regor/architecture/ethosu85/ethos_u85_weight_encoder.hpp b/ethosu/regor/architecture/ethosu85/ethos_u85_weight_encoder.hpp index 34690eba1b94d20cd65ad3d88da5c8e5558912a5..9ec8cb5e28c0784c235dfbdd5f170e531c7964cb 100644 --- a/ethosu/regor/architecture/ethosu85/ethos_u85_weight_encoder.hpp +++ b/ethosu/regor/architecture/ethosu85/ethos_u85_weight_encoder.hpp @@ -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 // @@ -68,7 +68,7 @@ public: public: std::unique_ptr GetEncodingConfig(ArchitectureOpConfig *opCfg, const WeightsRef &weights, - const Kernel *kernel, DataType ifmType, const std::vector &depthOffsets, Flags format); + const Kernel *kernel, DataType ifmType, int depthBase, const std::vector &depthOffsets, Flags format); int StreamsRequired(IWeightEncodingConfig *config, const Shape &weightShape, int &scaleStreamsRequired); diff --git a/ethosu/regor/architecture/weight_encoder.hpp b/ethosu/regor/architecture/weight_encoder.hpp index ea6ecedc2117b5a5b7fc4151e0ddd0684e0863cb..1db9d71e14240178d95225a3a76353784c88e215 100644 --- a/ethosu/regor/architecture/weight_encoder.hpp +++ b/ethosu/regor/architecture/weight_encoder.hpp @@ -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 // @@ -146,7 +146,7 @@ public: virtual ~WeightEncoder() = default; virtual std::unique_ptr GetEncodingConfig(ArchitectureOpConfig *opCfg, const WeightsRef &weights, - const Kernel *kernel, DataType ifmType, const std::vector &depthOffsets, Flags format) = 0; + const Kernel *kernel, DataType ifmType, int depthBase, const std::vector &depthOffsets, Flags format) = 0; virtual int StreamsRequired(IWeightEncodingConfig *config, const Shape &ofmShape, int &scaleStreamsRequired) = 0; diff --git a/ethosu/regor/common/common.cpp b/ethosu/regor/common/common.cpp index c4a6f61a3cce004d7c47bed6cdb122a4ed6d25b5..9f12080ec49ca5f0282e6f74739984f1eabdb7eb 100644 --- a/ethosu/regor/common/common.cpp +++ b/ethosu/regor/common/common.cpp @@ -1,5 +1,5 @@ // -// SPDX-FileCopyrightText: Copyright 2021, 2023 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright 2021, 2023, 2025 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 // @@ -24,6 +24,7 @@ UniqueId GenerateUniqueId() { static std::atomic _id; UniqueId id = _id.fetch_add(1); + assert(id != INVALID_UID); assert(id != std::numeric_limits::max()); return id; } diff --git a/ethosu/regor/common/common.hpp b/ethosu/regor/common/common.hpp index 62a709d1ae37e06e112e4cf739f684a3eabbbe5a..8aa23450b6603b6175f10705942d0f37924e30ec 100644 --- a/ethosu/regor/common/common.hpp +++ b/ethosu/regor/common/common.hpp @@ -73,6 +73,7 @@ using fmt::enums::format_as; } using UniqueId = uint32_t; +constexpr UniqueId INVALID_UID = std::numeric_limits::max(); UniqueId GenerateUniqueId(); diff --git a/ethosu/regor/compiler/scheduler.cpp b/ethosu/regor/compiler/scheduler.cpp index ff762de5dab4c6707ba2c58fbdbe4f66860d8283..e0df646da5c83873fd254a684f5077253245d9cb 100644 --- a/ethosu/regor/compiler/scheduler.cpp +++ b/ethosu/regor/compiler/scheduler.cpp @@ -578,8 +578,10 @@ WeightScaleEncoding Scheduler::EncodeBestWeightFormat( { throw std::runtime_error("Failed to find block configuration\n"); } + // The operation might have been decomposed in depth dimension and have an offset + const int depthBase = op->OFM()->slice.offset ? op->OFM()->slice.offset.Depth() : 0; auto encodingParams = _arch->WeightEncoder()->GetEncodingConfig( - blockConfig, weightsRef, op->Kernel(), ifmType, depthOffsets, weightFormat); + blockConfig, weightsRef, op->Kernel(), ifmType, depthBase, depthOffsets, weightFormat); try { @@ -703,8 +705,10 @@ std::unique_ptr Scheduler::CreateSchedulerOpInfo( std::vector depthOffsets{0, ofmShape.Unpermute(uint32_t(op->OFM()->transpose)).Depth()}; + // The operation might have been decomposed in depth dimension and have an offset + const int depthBase = op->OFM()->slice.offset ? op->OFM()->slice.offset.Depth() : 0; auto encodingParams = _arch->WeightEncoder()->GetEncodingConfig( - blockConfig.get(), weightsRef, op->Kernel(), ifm->tensor->dataType, depthOffsets, weightFormat); + blockConfig.get(), weightsRef, op->Kernel(), ifm->tensor->dataType, depthBase, depthOffsets, weightFormat); const SchedulerTensor *scaleTensor = scales ? scales->tensor.get() : nullptr; weightScales = EncodeQuantizationScaleTensor(std::move(encodingParams), op->OFM()->quantization, scaleTensor); @@ -1022,9 +1026,11 @@ void Scheduler::ProposeWeightBuffering(SchedulerConnection *weights, SchedulerCo std::find_if(subOps.begin(), subOps.end(), [](const auto &subOp) { return IsElementwise(subOp->Type()); }); assert(ofm->transpose == TransposeType::None || (ofm->transpose & TransposeType::MaskC) == TransposeType::C || refCost->stripe == ofm->shape); - auto fullDepthBeforeTransposition = + const int fullDepthBeforeTransposition = (refCost->stripe == ofm->shape) ? refCost->stripe.Unpermute(uint32_t(ofm->transpose)).Depth() : refCost->stripe.Depth(); - auto fullDepthAfterTransposition = refCost->stripe.Depth(); + const int fullDepthAfterTransposition = refCost->stripe.Depth(); + // The operation might have been decomposed in depth dimension and have an offset + const int depthBase = ofm->slice.offset ? schedOp->OFM()->slice.offset.Depth() : 0; std::vector ofmFullDepthSlicesBeforeTransposition = {0, fullDepthBeforeTransposition}; std::vector ofmFullDepthSlicesAfterTransposition = {0, fullDepthAfterTransposition}; @@ -1033,7 +1039,7 @@ void Scheduler::ProposeWeightBuffering(SchedulerConnection *weights, SchedulerCo auto weightFormat = cost->npuWeightsTensor->config->Format(); auto encodingParams = _arch->WeightEncoder()->GetEncodingConfig(cost->Config(), weightsRef, schedOp->Kernel(), - ifm->tensor->dataType, ofmFullDepthSlicesBeforeTransposition, weightFormat); + ifm->tensor->dataType, depthBase, ofmFullDepthSlicesBeforeTransposition, weightFormat); auto fullWeightScales = EncodeWeightAndScaleTensor( std::move(encodingParams), weightTens, scaleTens, weights->quantization, ofm->quantization); @@ -1158,7 +1164,7 @@ void Scheduler::ProposeWeightBuffering(SchedulerConnection *weights, SchedulerCo weightsRef = {&weightTens->bufferView, weightTens->srcTensor->AxisOrder(), weightTens->dataType, false}; encodingParams = _arch->WeightEncoder()->GetEncodingConfig(cost->Config(), weightsRef, - schedOp->Kernel(), ifm->tensor->dataType, cost->ofmDepthSlices, weightFormat); + schedOp->Kernel(), ifm->tensor->dataType, depthBase, cost->ofmDepthSlices, weightFormat); encodedWeightScales = EncodeWeightAndScaleTensor( std::move(encodingParams), weightTens, scaleTens, weights->quantization, ofm->quantization); diff --git a/ethosu/regor/compiler/scheduler_decompose.cpp b/ethosu/regor/compiler/scheduler_decompose.cpp index 60c4023accd785a2cd38a4aed2807a9773ba199b..079509f3f22ab0df868713c52e5f9881d118e210 100644 --- a/ethosu/regor/compiler/scheduler_decompose.cpp +++ b/ethosu/regor/compiler/scheduler_decompose.cpp @@ -63,15 +63,14 @@ static std::unique_ptr MakeMemCopy(const std::shared_ptrshape = Shape::PadAxes(ofmConn->tensor->storageShape, 4, 1); ofmConn->tensor->producers.push_back(op.get()); - auto ifmConn = op->AddInput(TensorUsage::IFM); - ifmConn->tensor = source; + auto ifmConn = op->AddInput(TensorUsage::IFM, source); if ( ifmConn->tensor->dataType == DataType::Int64 ) { // Copy int64 data as int32 data with 2 x C by cloning source tensor ifmConn->tensor = std::make_shared(*source); ifmConn->tensor->dataType = DataType::Int32; ifmConn->tensor->storageShape = source->storageShape.WithDepth(2 * source->storageShape.Depth()); + source->RemoveReader(op.get()); } - ifmConn->tensor->consumers.push_back(op.get()); ifmConn->shape = ofmConn->shape; return op; @@ -534,11 +533,9 @@ SliceT(SchedulerTensor *tensor, const Shape &offset, const Shape &shape, const S } // Clone tensor with new buffer with new unique ID because now the tensor is different - auto clonedTensor = std::make_shared(*tensor); + auto clonedTensor = tensor->Clone(); clonedTensor->bufferView = std::move(outBufferView); clonedTensor->storageShape = shape; - clonedTensor->equivalenceId = GenerateUniqueId(); - clonedTensor->consumers.clear(); return clonedTensor; } @@ -638,7 +635,7 @@ DecomposeBlocks(Architecture *arch, std::unique_ptr op, Shap for ( auto bc = 0; bc < NC; bc++ ) { auto newIfmSlice = ifmConn->slice; - newIfmSlice.offset = Shape::Min(ifmOffset.WithDepth(ifmOffset.Depth() + bc * BC), ifmConn->shape); + newIfmSlice.offset = Shape::Min(ifmOffset, ifmConn->shape); auto newOfmSlice = ofmConn->slice; newOfmSlice.offset = ofmOffset.WithDepth(ofmOffset.Depth() + bc * BC); auto &newOfmShape = ofmConn->SliceShape(); @@ -884,11 +881,13 @@ std::vector> DecomposeConv3D(Architecture *a }; // Create SchedulerTensor for ACC auto acc = std::make_shared(); + acc->uid = GenerateUniqueId(); acc->memArea = ofmConn->tensor->memArea; acc->dataType = ifmConn->tensor->dataType == DataType::Int16 ? DataType::Int64 : DataType::Int32; acc->storageShape = Shape(ofmShape, 4).WithBatch(1); - acc->uid = acc->equivalenceId = GenerateUniqueId(); - const auto ifm0uid = GenerateUniqueId(); + // Create ifm zero point SchedulerTensor, only needed for broadcast + // Setup is done below if needed + auto ifm0 = std::make_shared(); for ( int od = 0; od < OD; od++ ) { std::vector> conv2dSubOps; @@ -928,33 +927,36 @@ std::vector> DecomposeConv3D(Architecture *a subOp->RemoveInput(TensorUsage::Weights); InitConnection(subOp->Output(TensorUsage::OFM), ofmConn, od, OD); - // Create SchedulerTensor for 0 input auto subOpIfm = subOp->Input(TensorUsage::IFM); - auto ifm0 = std::make_shared(); - ifm0->dataType = subOpIfm->tensor->dataType; - ifm0->memArea = subOp->Input(TensorUsage::Scales)->tensor->memArea; - ifm0->format = TensorFormat::NHWC; const auto &ifm0shape = subOp->Output(TensorUsage::OFM)->slice.shape; - const auto bufSize = ifm0shape.Elements(); - const int64_t ifmZp = subOpIfm->quantization.zeroPoints.empty() ? 0 : subOpIfm->quantization.zeroPoints.front(); - std::shared_ptr ifm0buf; - switch ( ifm0->dataType ) + + if ( ifm0->uid == INVALID_UID ) { - case DataType::Int8: - ifm0buf = std::make_shared(std::vector(bufSize, int8_t(ifmZp))); - break; - case DataType::Int16: - ifm0buf = std::make_shared(std::vector(bufSize, int16_t(ifmZp))); - break; - default: - assert(false && "Unsupported ifm data type"); - break; + // Setup SchedulerTensor for 0 input + ifm0->uid = GenerateUniqueId(); + ifm0->dataType = subOpIfm->tensor->dataType; + ifm0->memArea = subOp->Input(TensorUsage::Scales)->tensor->memArea; + ifm0->format = TensorFormat::NHWC; + const auto bufSize = ifm0shape.Elements(); + const auto &zeroPoints = subOpIfm->quantization.zeroPoints; + const int64_t ifmZp = zeroPoints.empty() ? 0 : zeroPoints.front(); + std::shared_ptr ifm0buf; + switch ( ifm0->dataType ) + { + case DataType::Int8: + ifm0buf = std::make_shared(std::vector(bufSize, int8_t(ifmZp))); + break; + case DataType::Int16: + ifm0buf = std::make_shared(std::vector(bufSize, int16_t(ifmZp))); + break; + default: + assert(false && "Unsupported ifm data type"); + break; + } + ifm0->bufferView = BufferView(ifm0buf, 0, DataTypeStorageSizeBits(ifm0->dataType), ifm0shape, {}); + ifm0->storageShape = ifm0->bufferView.ViewShape(); } - ifm0->bufferView = BufferView(ifm0buf, 0, DataTypeStorageSizeBits(ifm0->dataType), ifm0shape, {}); - ifm0->storageShape = ifm0->bufferView.ViewShape(); - ifm0->uid = ifm0->equivalenceId = ifm0uid; - - subOpIfm->tensor = std::move(ifm0); + subOpIfm->tensor = ifm0; subOpIfm->tensor->consumers.push_back(subOp.get()); subOpIfm->shape = ifm0shape; subOpIfm->slice.offset = ifm0shape.WithZeros(); @@ -969,13 +971,11 @@ std::vector> DecomposeConv3D(Architecture *a auto bias = tail->Input(TensorUsage::Scales); // Create SchedulerTensor for 0 (no) bias - auto bias0 = std::make_shared(*bias->tensor); + auto bias0 = bias->tensor->Clone(); auto bias0buf = std::make_shared(std::make_unique(0)); assert(DataTypeStorageSizeBits(bias0->dataType) <= int(8 * sizeof(int64_t))); bias0->bufferView = BufferView(bias0buf, 0, DataTypeStorageSizeBits(bias0->dataType), {1}, {}); bias0->storageShape = bias0->bufferView.ViewShape(); - bias0->uid = bias0->equivalenceId = GenerateUniqueId(); - bias0->consumers.clear(); for ( auto subOp = conv2dSubOps.begin(); subOp != conv2dSubOps.end(); ++subOp ) { @@ -1048,11 +1048,8 @@ std::vector> DecomposeDepthwiseConv2D(Archit { int subOfmDepth = ofmConn->shape.Depth() / depthMultiplier; // Clone ofm tensor with new unique ID for intermediate transposed result - auto transposedOfm = std::make_shared(*ofmConn->tensor); + auto transposedOfm = ofmConn->tensor->Clone(); transposedOfm->storageShape = ofmShape.WithBatch(depthMultiplier).WithDepth(subOfmDepth); - transposedOfm->equivalenceId = GenerateUniqueId(); - transposedOfm->consumers.clear(); - transposedOfm->producers.clear(); // Copies quantization information and slices channels auto constexpr SliceQ = [](const Quantization &quantization, int offset, int step) -> Quantization @@ -1118,10 +1115,7 @@ std::vector> DecomposeDepthwiseConv2D(Archit if ( ofmSlice.offset.Batch() ) { // Need to insert intermediate tensor for memory copy, since DecomposeTranspose // does not handle ofm slice offset - transposeOpOfm = std::make_shared(*transposedOfm); - transposedOfm->equivalenceId = GenerateUniqueId(); - transposedOfm->consumers.clear(); - transposedOfm->producers.clear(); + transposeOpOfm = transposedOfm->Clone(); } auto transposeOp = MakeTransposeOp(transposedOfm, transposeOpOfm, Shape(1, 2, 3, 0)); auto subOps = DecomposeTranspose(arch, std::move(transposeOp)); @@ -1183,9 +1177,8 @@ static std::shared_ptr ReverseHW2(SchedulerTensor *tensor) } // Clone tensor with new buffer with new unique ID because now the tensor is different - auto clonedTensor = std::make_shared(*tensor); + auto clonedTensor = tensor->Clone(); clonedTensor->bufferView = std::move(outBufferView); - clonedTensor->equivalenceId = GenerateUniqueId(); return clonedTensor; } @@ -1253,6 +1246,7 @@ std::vector> DecomposeTransposeConv2D(Archit } // Map to Conv2D by reversing the weights in y and x weightsConn->tensor = ReverseHW(weightsConn->tensor.get()); + weightsConn->tensor->consumers.push_back(op.get()); Kernel newKernel = kernel->WithStride({1, 1}); op->_type = OpType::Conv2D; op->SetKernel(&newKernel); diff --git a/ethosu/regor/compiler/scheduler_operation.hpp b/ethosu/regor/compiler/scheduler_operation.hpp index aca2c5b91bf1afa7d4f460664e9028926826588f..f89f38b183c92468fac97bbc73405c3a090c3f16 100644 --- a/ethosu/regor/compiler/scheduler_operation.hpp +++ b/ethosu/regor/compiler/scheduler_operation.hpp @@ -26,6 +26,7 @@ #include "operation.hpp" #include "tensor.hpp" +#include #include namespace regor @@ -61,7 +62,7 @@ public: bool needsLinearFormat = false; // If two tensors have same equivalence id and same memory area, they can be stored on the same address UniqueId equivalenceId = GenerateUniqueId(); - UniqueId uid = ~0u; // Packing must initialise + UniqueId uid = INVALID_UID; // Packing must initialise std::vector producers; std::vector consumers; @@ -73,6 +74,16 @@ public: this->uid = GenerateUniqueId(); } + std::shared_ptr Clone() const + { + auto clone = std::make_shared(*this); + clone->uid = GenerateUniqueId(); + clone->equivalenceId = GenerateUniqueId(); + clone->consumers.clear(); + clone->producers.clear(); + return clone; + } + void RemoveReader(const SchedulerOperation *op) { auto end = std::remove(consumers.begin(), consumers.end(), op); diff --git a/ethosu/regor/test/test_ethos_u85_weight_encoder.cpp b/ethosu/regor/test/test_ethos_u85_weight_encoder.cpp index cc739fa75a7e787c0f6e2771f607dd37c7ff60ff..fb02f0558a4489867e2a27e5f6d6dc23e96a914e 100644 --- a/ethosu/regor/test/test_ethos_u85_weight_encoder.cpp +++ b/ethosu/regor/test/test_ethos_u85_weight_encoder.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 // @@ -67,7 +67,7 @@ TEST_CASE("ethos_u85_weightsource") auto encoder = arch->WeightEncoder(); auto view = weightTensor.View(); WeightsRef weightsRef = {&view, AxisOrder::OHWI, weightTensor.Type()}; - auto config = encoder->GetEncodingConfig(opCfg.get(), weightsRef, &kernel, DataType::Int8, depthOffsets, WeightFormat::Default); + auto config = encoder->GetEncodingConfig(opCfg.get(), weightsRef, &kernel, DataType::Int8, 0, depthOffsets, WeightFormat::Default); auto transform = [](const WeightTransformParam *, int weight) { return weight; }; auto source = encoder->GetWeightSource(config.get(), DataType::Int8, transform, ¶m); source->SetSource(view.RawData(), 0, weightShape, view.StrideBytes(), 0);