1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 //
5 // Copyright (C) 2019 Intel Corporation
6 
7 #include "precomp.hpp"
8 
9 #include <iostream>                              // cout
10 #include <sstream>                               // stringstream
11 #include <fstream>                               // ofstream
12 #include <map>
13 
14 #include <ade/passes/check_cycles.hpp>
15 #include <ade/util/zip_range.hpp>                // indexed()
16 
17 #include <opencv2/gapi/gproto.hpp>
18 #include "compiler/gmodel.hpp"
19 #include "compiler/gislandmodel.hpp"
20 #include "compiler/passes/passes.hpp"
21 
22 namespace cv { namespace gimpl { namespace passes {
23 
24 /**
25  * This pass extends a GIslandModel with streaming-oriented
26  * information.
27  *
28  * Every input data object (according to the protocol) is connected to
29  * a new "Emitter" node which becomes its _consumer_.
30  *
31  * Every output data object (again, according to the protocol) is
32  * connected to a new "Sink" node which becomes its _consumer_.
33  *
34  * These extra nodes are required to streamline the queues
35  * initialization by the GStreamingIntrinExecutable and its derivatives.
36  */
addStreaming(ade::passes::PassContext & ctx)37 void addStreaming(ade::passes::PassContext &ctx)
38 {
39     GModel::Graph gm(ctx.graph);
40     if (!gm.metadata().contains<Streaming>()) {
41         return;
42     }
43 
44     // Note: This pass is working on a GIslandModel.
45     // FIXME: May be introduce a new variant of GIslandModel to
46     // deal with streams?
47     auto igr = gm.metadata().get<IslandModel>().model;
48     GIslandModel::Graph igm(*igr);
49 
50     // First collect all data slots & their respective original
51     // data objects
52     using M = std::unordered_map
53         < ade::NodeHandle  // key: a GModel's data object node
54         , ade::NodeHandle // value: an appropriate GIslandModel's slot node
55         , ade::HandleHasher<ade::Node>
56         >;
57     M orig_to_isl;
58     for (auto &&nh : igm.nodes()) {
59         if (igm.metadata(nh).get<NodeKind>().k == NodeKind::SLOT) {
60             const auto &orig_nh = igm.metadata(nh).get<DataSlot>().original_data_node;
61             orig_to_isl[orig_nh] = nh;
62         }
63     }
64 
65     // Now walk through the list of input slots and connect those
66     // to a Streaming source.
67     const auto proto = gm.metadata().get<Protocol>();
68     for (auto &&it : ade::util::indexed(proto.in_nhs)) {
69         const auto in_idx = ade::util::index(it);
70         const auto in_nh  = ade::util::value(it);
71         auto emit_nh = GIslandModel::mkEmitNode(igm, in_idx);
72         igm.link(emit_nh, orig_to_isl.at(in_nh));
73     }
74 
75     // Same for output slots
76     for (auto &&it : ade::util::indexed(proto.out_nhs)) {
77         const auto out_idx = ade::util::index(it);
78         const auto out_nh  = ade::util::value(it);
79         auto sink_nh = GIslandModel::mkSinkNode(igm, out_idx);
80         igm.link(orig_to_isl.at(out_nh), sink_nh);
81     }
82 }
83 
84 }}} // cv::gimpl::passes
85