IVGCVSW-5742 'NonConstWeights: Update FullyConnected in android-nn-driver'

* Enabled weights and bias as inputs in FULLY_CONNECTED operator.

!armnn:5180

Signed-off-by: Sadik Armagan <sadik.armagan@arm.com>
Change-Id: Id325a8bf5be5a772191d27ae89485e992f0c48fa
diff --git a/test/FullyConnected.cpp b/test/FullyConnected.cpp
index 8550c8d..a68a587 100644
--- a/test/FullyConnected.cpp
+++ b/test/FullyConnected.cpp
@@ -264,4 +264,116 @@
     BOOST_TEST(outdata[7] == 8);
 }
 
+BOOST_AUTO_TEST_CASE(TestFullyConnectedWeightsAsInput)
+{
+    auto driver = std::make_unique<ArmnnDriver>(DriverOptions(armnn::Compute::CpuRef));
+
+    V1_0::ErrorStatus error;
+    std::vector<bool> sup;
+
+    ArmnnDriver::getSupportedOperations_cb cb = [&](V1_0::ErrorStatus status, const std::vector<bool>& supported)
+    {
+        error = status;
+        sup = supported;
+    };
+
+    HalPolicy::Model model = {};
+
+    // operands
+    int32_t actValue      = 0;
+    float   weightValue[] = {1, 0, 0, 0, 0, 0, 0, 0,
+                             0, 1, 0, 0, 0, 0, 0, 0,
+                             0, 0, 1, 0, 0, 0, 0, 0,
+                             0, 0, 0, 1, 0, 0, 0, 0,
+                             0, 0, 0, 0, 1, 0, 0, 0,
+                             0, 0, 0, 0, 0, 1, 0, 0,
+                             0, 0, 0, 0, 0, 0, 1, 0,
+                             0, 0, 0, 0, 0, 0, 0, 1}; //identity
+    float   biasValue[]   = {0, 0, 0, 0, 0, 0, 0, 0};
+
+    // fully connected operation
+    AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 1, 1, 8});
+    AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{8, 8});
+    AddInputOperand<HalPolicy>(model, hidl_vec<uint32_t>{8});
+    AddIntOperand<HalPolicy>(model, actValue);
+    AddOutputOperand<HalPolicy>(model, hidl_vec<uint32_t>{1, 8});
+
+    model.operations.resize(1);
+
+    model.operations[0].type = HalPolicy::OperationType::FULLY_CONNECTED;
+    model.operations[0].inputs  = hidl_vec<uint32_t>{0,1,2,3};
+    model.operations[0].outputs = hidl_vec<uint32_t>{4};
+
+    // make the prepared model
+    android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver);
+
+    // construct the request for input
+    V1_0::DataLocation inloc = {};
+    inloc.poolIndex          = 0;
+    inloc.offset             = 0;
+    inloc.length             = 8 * sizeof(float);
+    RequestArgument input    = {};
+    input.location           = inloc;
+    input.dimensions         = hidl_vec<uint32_t>{1, 1, 1, 8};
+
+    // construct the request for weights as input
+    V1_0::DataLocation wloc = {};
+    wloc.poolIndex          = 1;
+    wloc.offset             = 0;
+    wloc.length             = 64 * sizeof(float);
+    RequestArgument weights = {};
+    weights.location        = wloc;
+    weights.dimensions      = hidl_vec<uint32_t>{8, 8};
+
+    // construct the request for bias as input
+    V1_0::DataLocation bloc = {};
+    bloc.poolIndex          = 2;
+    bloc.offset             = 0;
+    bloc.length             = 8 * sizeof(float);
+    RequestArgument bias    = {};
+    bias.location           = bloc;
+    bias.dimensions         = hidl_vec<uint32_t>{8};
+
+    V1_0::DataLocation outloc = {};
+    outloc.poolIndex          = 3;
+    outloc.offset             = 0;
+    outloc.length             = 8 * sizeof(float);
+    RequestArgument output    = {};
+    output.location           = outloc;
+    output.dimensions         = hidl_vec<uint32_t>{1, 8};
+
+    V1_0::Request request = {};
+    request.inputs  = hidl_vec<RequestArgument>{input, weights, bias};
+    request.outputs = hidl_vec<RequestArgument>{output};
+
+    // set the input data
+    float indata[] = {1,2,3,4,5,6,7,8};
+    AddPoolAndSetData(8, request, indata);
+
+    // set the weights data
+    AddPoolAndSetData(64, request, weightValue);
+    // set the bias data
+    AddPoolAndSetData(8, request, biasValue);
+
+    // add memory for the output
+    android::sp<IMemory> outMemory = AddPoolAndGetData<float>(8, request);
+    float* outdata = static_cast<float*>(static_cast<void*>(outMemory->getPointer()));
+
+    // run the execution
+    if (preparedModel != nullptr)
+    {
+        Execute(preparedModel, request);
+    }
+
+    // check the result
+    BOOST_TEST(outdata[0] == 1);
+    BOOST_TEST(outdata[1] == 2);
+    BOOST_TEST(outdata[2] == 3);
+    BOOST_TEST(outdata[3] == 4);
+    BOOST_TEST(outdata[4] == 5);
+    BOOST_TEST(outdata[5] == 6);
+    BOOST_TEST(outdata[6] == 7);
+    BOOST_TEST(outdata[7] == 8);
+}
+
 BOOST_AUTO_TEST_SUITE_END()