1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "TestMemory.h" 18 19 #include "TestNeuralNetworksWrapper.h" 20 21 #include <gtest/gtest.h> 22 #include <sys/mman.h> 23 #include <sys/types.h> 24 #include <unistd.h> 25 26 using WrapperCompilation = ::android::nn::test_wrapper::Compilation; 27 using WrapperExecution = ::android::nn::test_wrapper::Execution; 28 using WrapperMemory = ::android::nn::test_wrapper::Memory; 29 using WrapperModel = ::android::nn::test_wrapper::Model; 30 using WrapperOperandType = ::android::nn::test_wrapper::OperandType; 31 using WrapperResult = ::android::nn::test_wrapper::Result; 32 using WrapperType = ::android::nn::test_wrapper::Type; 33 34 namespace { 35 36 // Tests the various ways to pass weights and input/output data. 37 class MemoryTest : public ::testing::Test { 38 protected: 39 void SetUp() override {} 40 41 }; 42 43 TEST_F(MemoryTest, TestFd) { 44 // Create a file that contains matrix2 and matrix3. 45 char path[] = "/data/local/tmp/TestMemoryXXXXXX"; 46 int fd = mkstemp(path); 47 const uint32_t offsetForMatrix2 = 20; 48 const uint32_t offsetForMatrix3 = 200; 49 static_assert(offsetForMatrix2 + sizeof(matrix2) < offsetForMatrix3, "matrices overlap"); 50 lseek(fd, offsetForMatrix2, SEEK_SET); 51 write(fd, matrix2, sizeof(matrix2)); 52 lseek(fd, offsetForMatrix3, SEEK_SET); 53 write(fd, matrix3, sizeof(matrix3)); 54 fsync(fd); 55 56 WrapperMemory weights(offsetForMatrix3 + sizeof(matrix3), PROT_READ, fd, 0); 57 ASSERT_TRUE(weights.isValid()); 58 59 WrapperModel model; 60 WrapperOperandType matrixType(WrapperType::TENSOR_FLOAT32, {3, 4}); 61 WrapperOperandType scalarType(WrapperType::INT32, {}); 62 int32_t activation(0); 63 auto a = model.addOperand(&matrixType); 64 auto b = model.addOperand(&matrixType); 65 auto c = model.addOperand(&matrixType); 66 auto d = model.addOperand(&matrixType); 67 auto e = model.addOperand(&matrixType); 68 auto f = model.addOperand(&scalarType); 69 70 model.setOperandValueFromMemory(e, &weights, offsetForMatrix2, sizeof(Matrix3x4)); 71 model.setOperandValueFromMemory(a, &weights, offsetForMatrix3, sizeof(Matrix3x4)); 72 model.setOperandValue(f, &activation, sizeof(activation)); 73 model.addOperation(ANEURALNETWORKS_ADD, {a, c, f}, {b}); 74 model.addOperation(ANEURALNETWORKS_ADD, {b, e, f}, {d}); 75 model.identifyInputsAndOutputs({c}, {d}); 76 ASSERT_TRUE(model.isValid()); 77 model.finish(); 78 79 // Test the three node model. 80 Matrix3x4 actual; 81 memset(&actual, 0, sizeof(actual)); 82 WrapperCompilation compilation2(&model); 83 ASSERT_EQ(compilation2.finish(), WrapperResult::NO_ERROR); 84 WrapperExecution execution2(&compilation2); 85 ASSERT_EQ(execution2.setInput(0, matrix1, sizeof(Matrix3x4)), WrapperResult::NO_ERROR); 86 ASSERT_EQ(execution2.setOutput(0, actual, sizeof(Matrix3x4)), WrapperResult::NO_ERROR); 87 ASSERT_EQ(execution2.compute(), WrapperResult::NO_ERROR); 88 ASSERT_EQ(CompareMatrices(expected3, actual), 0); 89 90 close(fd); 91 unlink(path); 92 } 93 94 TEST_F(MemoryTest, TestAHardwareBuffer) { 95 const uint32_t offsetForMatrix2 = 20; 96 const uint32_t offsetForMatrix3 = 200; 97 98 AHardwareBuffer_Desc desc{ 99 .width = offsetForMatrix3 + sizeof(matrix3), 100 .height = 1, 101 .layers = 1, 102 .format = AHARDWAREBUFFER_FORMAT_BLOB, 103 .usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, 104 }; 105 AHardwareBuffer* buffer = nullptr; 106 ASSERT_EQ(AHardwareBuffer_allocate(&desc, &buffer), 0); 107 108 void* bufferPtr = nullptr; 109 ASSERT_EQ(AHardwareBuffer_lock(buffer, desc.usage, -1, NULL, &bufferPtr), 0); 110 memcpy((uint8_t*)bufferPtr + offsetForMatrix2, matrix2, sizeof(matrix2)); 111 memcpy((uint8_t*)bufferPtr + offsetForMatrix3, matrix3, sizeof(matrix3)); 112 ASSERT_EQ(AHardwareBuffer_unlock(buffer, nullptr), 0); 113 114 WrapperMemory weights(buffer); 115 ASSERT_TRUE(weights.isValid()); 116 117 WrapperModel model; 118 WrapperOperandType matrixType(WrapperType::TENSOR_FLOAT32, {3, 4}); 119 WrapperOperandType scalarType(WrapperType::INT32, {}); 120 int32_t activation(0); 121 auto a = model.addOperand(&matrixType); 122 auto b = model.addOperand(&matrixType); 123 auto c = model.addOperand(&matrixType); 124 auto d = model.addOperand(&matrixType); 125 auto e = model.addOperand(&matrixType); 126 auto f = model.addOperand(&scalarType); 127 128 model.setOperandValueFromMemory(e, &weights, offsetForMatrix2, sizeof(Matrix3x4)); 129 model.setOperandValueFromMemory(a, &weights, offsetForMatrix3, sizeof(Matrix3x4)); 130 model.setOperandValue(f, &activation, sizeof(activation)); 131 model.addOperation(ANEURALNETWORKS_ADD, {a, c, f}, {b}); 132 model.addOperation(ANEURALNETWORKS_ADD, {b, e, f}, {d}); 133 model.identifyInputsAndOutputs({c}, {d}); 134 ASSERT_TRUE(model.isValid()); 135 model.finish(); 136 137 // Test the three node model. 138 Matrix3x4 actual; 139 memset(&actual, 0, sizeof(actual)); 140 WrapperCompilation compilation2(&model); 141 ASSERT_EQ(compilation2.finish(), WrapperResult::NO_ERROR); 142 WrapperExecution execution2(&compilation2); 143 ASSERT_EQ(execution2.setInput(0, matrix1, sizeof(Matrix3x4)), WrapperResult::NO_ERROR); 144 ASSERT_EQ(execution2.setOutput(0, actual, sizeof(Matrix3x4)), WrapperResult::NO_ERROR); 145 ASSERT_EQ(execution2.compute(), WrapperResult::NO_ERROR); 146 ASSERT_EQ(CompareMatrices(expected3, actual), 0); 147 148 AHardwareBuffer_release(buffer); 149 buffer = nullptr; 150 } 151 } // end namespace 152