IVGCVSW-5980 JSON profiling output

 * Add new ProfilingDetails class to construct operator details string
 * Add new macro which helps append layer details to ostream
 * Add ProfilingEnabled to NetworkProperties so that profiling can be
   realised when loading the network
 * Add further optional info to WorkloadInfo specific to convolutions
 * Generalise some JsonPrinter functions into JsonUtils for reusability
 * Remove explicit enabling of profiling within InferenceModel as it is
   done when loading network
 * Add ProfilingDetails macros to ConvolutionWorkloads for validation

Signed-off-by: Keith Davis <keith.davis@arm.com>
Change-Id: Ie84bc7dc667e72e6bcb635544f9ead7af1765690
diff --git a/src/backends/cl/workloads/ClConvolution2dWorkload.cpp b/src/backends/cl/workloads/ClConvolution2dWorkload.cpp
index 5c731aa..b3df7ce 100644
--- a/src/backends/cl/workloads/ClConvolution2dWorkload.cpp
+++ b/src/backends/cl/workloads/ClConvolution2dWorkload.cpp
@@ -120,6 +120,23 @@
                                                   aclDilationInfo,
                                                   isFastMathEnabled);
 
+     // Add details for profiling output
+    std::string workloadName = "ClConvolution2dWorkload_Execute_Guid" + std::to_string(this->GetGuid());
+
+    WorkloadInfo detailsInfo;
+
+    detailsInfo.m_InputTensorInfos = info.m_InputTensorInfos;
+    detailsInfo.m_OutputTensorInfos = info.m_OutputTensorInfos;
+    detailsInfo.m_WeightsTensorInfo = armnn::Optional<armnn::TensorInfo>(descriptor.m_Weight->GetTensorInfo());
+    detailsInfo.m_ConvolutionMethod = armnn::Optional<std::string>(GetConvolutionMethodString());
+    if (descriptor.m_Parameters.m_BiasEnabled)
+    {
+        detailsInfo.m_BiasTensorInfo = armnn::Optional<armnn::TensorInfo>(descriptor.m_Bias->GetTensorInfo());
+    }
+
+    // Report Profiling Details
+    ARMNN_REPORT_PROFILING_WORKLOAD_DESC(workloadName, descriptor.m_Parameters, detailsInfo);
+
     InitializeArmComputeClTensorData(*m_KernelTensor, m_Data.m_Weight);
 
     if (m_BiasTensor)
@@ -144,6 +161,23 @@
     return m_ConvolutionMethod;
 }
 
+std::string ClConvolution2dWorkload::GetConvolutionMethodString()
+{
+    switch ( m_ConvolutionMethod )
+    {
+        case arm_compute::ConvolutionMethod::FFT:
+            return "FFT";
+        case arm_compute::ConvolutionMethod::DIRECT:
+            return "Direct";
+        case arm_compute::ConvolutionMethod::GEMM:
+            return "GEMM";
+        case arm_compute::ConvolutionMethod::WINOGRAD:
+            return "Winograd";
+        default:
+            return "Unknown";
+    }
+}
+
 void ClConvolution2dWorkload::FreeUnusedTensors()
 {
     FreeTensorIfUnused(m_KernelTensor);