summaryrefslogtreecommitdiff
path: root/compiler/luci-interpreter/src/Interpreter.cpp
blob: 639ffc1f0ca689326a81271453089a1552283bce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "luci_interpreter/Interpreter.h"

#include "loader/ModuleLoader.h"

#include <stdexcept>

namespace luci_interpreter
{

namespace
{

class EventNotifierImpl final : public EventNotifier
{
public:
  EventNotifierImpl(const RuntimeToIR &runtime_to_ir,
                    const std::vector<ExecutionObserver *> &observers)
      : _runtime_to_ir(runtime_to_ir), _observers(observers)
  {
  }

  void postTensorWrite(const Tensor *tensor) override
  {
    assert(tensor != nullptr);
    for (const auto &observer : _observers)
    {
      observer->postTensorWrite(_runtime_to_ir.tensor_to_node.at(tensor), tensor);
    }
  }

  void preOperatorExecute(const Kernel *kernel) override
  {
    assert(kernel != nullptr);
    for (const auto &observer : _observers)
    {
      observer->preOperatorExecute(_runtime_to_ir.kernel_to_node.at(kernel));
    }
  }

  void postOperatorExecute(const Kernel *kernel) override
  {
    assert(kernel != nullptr);
    for (const auto &observer : _observers)
    {
      observer->postOperatorExecute(_runtime_to_ir.kernel_to_node.at(kernel));
    }
  }

private:
  const RuntimeToIR &_runtime_to_ir;
  const std::vector<ExecutionObserver *> &_observers;
};

} // namespace

Interpreter::Interpreter(const luci::Module *module)
{
  _runtime_to_ir = std::make_unique<RuntimeToIR>();
  _event_notifier = std::make_unique<EventNotifierImpl>(*_runtime_to_ir, _observers);
  _runtime_module = std::make_unique<RuntimeModule>(_event_notifier.get());
  ModuleLoader loader(module, _runtime_module.get(), *_runtime_to_ir, _node_to_tensor);
  loader.load();
}

Interpreter::~Interpreter() = default;

void Interpreter::writeInputTensor(const luci::CircleInput *input_node, const void *data,
                                   size_t data_size)
{
  Tensor *tensor = _runtime_module->getInputTensors()[input_node->index()];
  if (tensor == nullptr)
  {
    const std::string &name = input_node->name();
    throw std::runtime_error("Cannot find tensor for input node named \"" + name + "\".");
  }
  if (data != nullptr)
    tensor->writeData(data, data_size);
}

void Interpreter::readOutputTensor(const luci::CircleOutput *output_node, void *data,
                                   size_t data_size)
{
  Tensor *tensor = _runtime_module->getOutputTensors()[output_node->index()];
  if (tensor == nullptr)
  {
    const std::string &name = output_node->name();
    throw std::runtime_error("Cannot find tensor for output node named \"" + name + "\".");
  }
  if (data != nullptr)
    tensor->readData(data, data_size);
}

void Interpreter::interpret() { _runtime_module->execute(); }

void Interpreter::attachObserver(ExecutionObserver *observer)
{
  if (std::find(_observers.cbegin(), _observers.cend(), observer) != _observers.cend())
    throw std::runtime_error("Observer is already attached.");
  _observers.push_back(observer);
}

ExecutionObserver::~ExecutionObserver() = default;

void ExecutionObserver::postTensorWrite(const luci::CircleNode *, const Tensor *) {}

void ExecutionObserver::preOperatorExecute(const luci::CircleNode *) {}

void ExecutionObserver::postOperatorExecute(const luci::CircleNode *) {}

} // namespace luci_interpreter