#include "env.h"
#include "util/feature/RandomObject.h"
+#include "util/feature/Reader.h"
#include <iostream>
+#include <cassert>
using namespace tflite;
using namespace tflite::ops::builtin;
+class TfLiteOutputIndex
+{
+public:
+ TfLiteOutputIndex(int index) : _index(index)
+ {
+
+ }
+
+public:
+ int asInt(void) const { return _index; }
+
+private:
+ int _index;
+};
+
+template<typename T> class TfLiteFeatureView;
+
+template<> class TfLiteFeatureView<float> : public nnfw::util::feature::Reader<float>
+{
+public:
+ TfLiteFeatureView(tflite::Interpreter &interp, const TfLiteOutputIndex &index);
+
+public:
+ float at(uint32_t ch, uint32_t row, uint32_t col) const;
+
+private:
+ nnfw::util::feature::Shape _shape;
+ float *_base;
+};
+
+TfLiteFeatureView<float>::TfLiteFeatureView(tflite::Interpreter &interp, const TfLiteOutputIndex &index)
+{
+ const auto tensor_index = interp.outputs().at(index.asInt());
+ auto tensor_ptr = interp.tensor(tensor_index);
+
+ assert(tensor_ptr->type == kTfLiteFloat32);
+ assert(tensor_ptr->dims->size == 4);
+ assert(tensor_ptr->dims->data[0] == 1);
+
+ _shape.C = tensor_ptr->dims->data[3];
+ _shape.H = tensor_ptr->dims->data[1];
+ _shape.W = tensor_ptr->dims->data[2];
+
+ _base = interp.typed_tensor<float>(tensor_index);
+}
+
+float TfLiteFeatureView<float>::at(uint32_t ch, uint32_t row, uint32_t col) const
+{
+ uint32_t element_offset = 0;
+
+ // TensorFlow Lite assumes that NHWC ordering for tessor
+ element_offset += row * _shape.W * _shape.C;
+ element_offset += col * _shape.C;
+ element_offset += ch;
+
+ return *(_base + element_offset);
+}
+
int main(int argc, char **argv)
{
#define INT_VALUE(NAME, VALUE) IntVar NAME##_Value(#NAME, VALUE);
// Compare OFM
{
- uint32_t off = 0;
+ const TfLiteFeatureView<float> interp_output{pure, TfLiteOutputIndex{0}};
+ const TfLiteFeatureView<float> nnapi_output{delegated, TfLiteOutputIndex{0}};
for (uint32_t row = 0; row < OFM_H; ++row)
{
{
for (uint32_t ch = 0; ch < kernel.shape().N; ++ch)
{
- const auto value_from_interp = pure.typed_output_tensor<float>(0)[off];
- const auto value_from_NNAPI = delegated.typed_output_tensor<float>(0)[off];
+ const auto value_from_interp = interp_output.at(ch, row, col);
+ const auto value_from_NNAPI = nnapi_output.at(ch, row, col);
if (value_from_interp != value_from_NNAPI)
{
std::cerr << " Value from interpreter: " << value_from_interp << std::endl;
std::cerr << " Value from NNAPI: " << value_from_NNAPI << std::endl;
}
-
- off += 1;
}
}
}