GNU Radio 3.7.1 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2006,2007,2013 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #ifndef INCLUDED_GR_RUNTIME_FLOWGRAPH_H 00024 #define INCLUDED_GR_RUNTIME_FLOWGRAPH_H 00025 00026 #include <gnuradio/api.h> 00027 #include <gnuradio/basic_block.h> 00028 #include <gnuradio/io_signature.h> 00029 #include <iostream> 00030 00031 namespace gr { 00032 00033 /*! 00034 * \brief Class representing a specific input or output graph endpoint 00035 * \ingroup internal 00036 */ 00037 class GR_RUNTIME_API endpoint 00038 { 00039 private: 00040 basic_block_sptr d_basic_block; 00041 int d_port; 00042 00043 public: 00044 endpoint() : d_basic_block(), d_port(0) { } 00045 endpoint(basic_block_sptr block, int port) { d_basic_block = block; d_port = port; } 00046 basic_block_sptr block() const { return d_basic_block; } 00047 int port() const { return d_port; } 00048 00049 bool operator==(const endpoint &other) const; 00050 }; 00051 00052 inline bool endpoint::operator==(const endpoint &other) const 00053 { 00054 return (d_basic_block == other.d_basic_block && 00055 d_port == other.d_port); 00056 } 00057 00058 class GR_RUNTIME_API msg_endpoint 00059 { 00060 private: 00061 basic_block_sptr d_basic_block; 00062 pmt::pmt_t d_port; 00063 bool d_is_hier; 00064 00065 public: 00066 msg_endpoint() : d_basic_block(), d_port(pmt::PMT_NIL) { } 00067 msg_endpoint(basic_block_sptr block, pmt::pmt_t port, bool is_hier=false) { 00068 d_basic_block = block; d_port = port; d_is_hier = is_hier; 00069 } 00070 basic_block_sptr block() const { return d_basic_block; } 00071 pmt::pmt_t port() const { return d_port; } 00072 bool is_hier() const { return d_is_hier; } 00073 void set_hier(bool h) { d_is_hier = h; } 00074 00075 bool operator==(const msg_endpoint &other) const; 00076 }; 00077 00078 inline bool 00079 msg_endpoint::operator==(const msg_endpoint &other) const 00080 { 00081 return (d_basic_block == other.d_basic_block && 00082 pmt::equal(d_port, other.d_port)); 00083 } 00084 00085 // Hold vectors of gr::endpoint objects 00086 typedef std::vector<endpoint> endpoint_vector_t; 00087 typedef std::vector<endpoint>::iterator endpoint_viter_t; 00088 00089 /*! 00090 *\brief Class representing a connection between to graph endpoints 00091 */ 00092 class GR_RUNTIME_API edge 00093 { 00094 public: 00095 edge() : d_src(), d_dst() { }; 00096 edge(const endpoint &src, const endpoint &dst) 00097 : d_src(src), d_dst(dst) { } 00098 ~edge(); 00099 00100 const endpoint &src() const { return d_src; } 00101 const endpoint &dst() const { return d_dst; } 00102 00103 private: 00104 endpoint d_src; 00105 endpoint d_dst; 00106 }; 00107 00108 // Hold vectors of gr::edge objects 00109 typedef std::vector<edge> edge_vector_t; 00110 typedef std::vector<edge>::iterator edge_viter_t; 00111 00112 00113 /*! 00114 *\brief Class representing a msg connection between to graph msg endpoints 00115 */ 00116 class GR_RUNTIME_API msg_edge 00117 { 00118 public: 00119 msg_edge() : d_src(), d_dst() { }; 00120 msg_edge(const msg_endpoint &src, const msg_endpoint &dst) 00121 : d_src(src), d_dst(dst) { } 00122 ~msg_edge() {} 00123 00124 const msg_endpoint &src() const { return d_src; } 00125 const msg_endpoint &dst() const { return d_dst; } 00126 00127 private: 00128 msg_endpoint d_src; 00129 msg_endpoint d_dst; 00130 }; 00131 00132 // Hold vectors of gr::msg_edge objects 00133 typedef std::vector<msg_edge> msg_edge_vector_t; 00134 typedef std::vector<msg_edge>::iterator msg_edge_viter_t; 00135 00136 // Create a shared pointer to a heap allocated flowgraph 00137 // (types defined in runtime_types.h) 00138 GR_RUNTIME_API flowgraph_sptr make_flowgraph(); 00139 00140 /*! 00141 * \brief Class representing a directed, acyclic graph of basic blocks 00142 * \ingroup internal 00143 */ 00144 class GR_RUNTIME_API flowgraph 00145 { 00146 public: 00147 friend GR_RUNTIME_API flowgraph_sptr make_flowgraph(); 00148 00149 // Destruct an arbitrary flowgraph 00150 ~flowgraph(); 00151 00152 // Connect two endpoints 00153 void connect(const endpoint &src, const endpoint &dst); 00154 00155 // Disconnect two endpoints 00156 void disconnect(const endpoint &src, const endpoint &dst); 00157 00158 // Connect an output port to an input port (convenience) 00159 void connect(basic_block_sptr src_block, int src_port, 00160 basic_block_sptr dst_block, int dst_port); 00161 00162 // Disconnect an input port from an output port (convenience) 00163 void disconnect(basic_block_sptr src_block, int src_port, 00164 basic_block_sptr dst_block, int dst_port); 00165 00166 // Connect two msg endpoints 00167 void connect(const msg_endpoint &src, const msg_endpoint &dst); 00168 00169 // Disconnect two msg endpoints 00170 void disconnect(const msg_endpoint &src, const msg_endpoint &dst); 00171 00172 // Validate connectivity, raise exception if invalid 00173 void validate(); 00174 00175 // Clear existing flowgraph 00176 void clear(); 00177 00178 // Return vector of edges 00179 const edge_vector_t &edges() const { return d_edges; } 00180 00181 // Return vector of msg edges 00182 const msg_edge_vector_t &msg_edges() const { return d_msg_edges; } 00183 00184 // Return vector of connected blocks 00185 basic_block_vector_t calc_used_blocks(); 00186 00187 // Return toplogically sorted vector of blocks. All the sources come first. 00188 basic_block_vector_t topological_sort(basic_block_vector_t &blocks); 00189 00190 // Return vector of vectors of disjointly connected blocks, 00191 // topologically sorted. 00192 std::vector<basic_block_vector_t> partition(); 00193 00194 protected: 00195 basic_block_vector_t d_blocks; 00196 edge_vector_t d_edges; 00197 msg_edge_vector_t d_msg_edges; 00198 00199 flowgraph(); 00200 std::vector<int> calc_used_ports(basic_block_sptr block, bool check_inputs); 00201 basic_block_vector_t calc_downstream_blocks(basic_block_sptr block, int port); 00202 edge_vector_t calc_upstream_edges(basic_block_sptr block); 00203 bool has_block_p(basic_block_sptr block); 00204 edge calc_upstream_edge(basic_block_sptr block, int port); 00205 00206 private: 00207 void check_valid_port(gr::io_signature::sptr sig, int port); 00208 void check_valid_port(const msg_endpoint &e); 00209 void check_dst_not_used(const endpoint &dst); 00210 void check_type_match(const endpoint &src, const endpoint &dst); 00211 edge_vector_t calc_connections(basic_block_sptr block, bool check_inputs); // false=use outputs 00212 void check_contiguity(basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs); 00213 00214 basic_block_vector_t calc_downstream_blocks(basic_block_sptr block); 00215 basic_block_vector_t calc_reachable_blocks(basic_block_sptr block, basic_block_vector_t &blocks); 00216 void reachable_dfs_visit(basic_block_sptr block, basic_block_vector_t &blocks); 00217 basic_block_vector_t calc_adjacent_blocks(basic_block_sptr block, basic_block_vector_t &blocks); 00218 basic_block_vector_t sort_sources_first(basic_block_vector_t &blocks); 00219 bool source_p(basic_block_sptr block); 00220 void topological_dfs_visit(basic_block_sptr block, basic_block_vector_t &output); 00221 }; 00222 00223 // Convenience functions 00224 inline 00225 void flowgraph::connect(basic_block_sptr src_block, int src_port, 00226 basic_block_sptr dst_block, int dst_port) 00227 { 00228 connect(endpoint(src_block, src_port), 00229 endpoint(dst_block, dst_port)); 00230 } 00231 00232 inline 00233 void flowgraph::disconnect(basic_block_sptr src_block, int src_port, 00234 basic_block_sptr dst_block, int dst_port) 00235 { 00236 disconnect(endpoint(src_block, src_port), 00237 endpoint(dst_block, dst_port)); 00238 } 00239 00240 inline std::ostream& 00241 operator <<(std::ostream &os, const endpoint endp) 00242 { 00243 os << endp.block()->alias() << ":" << endp.port(); 00244 return os; 00245 } 00246 00247 inline std::ostream& 00248 operator <<(std::ostream &os, const edge edge) 00249 { 00250 os << edge.src() << "->" << edge.dst(); 00251 return os; 00252 } 00253 00254 inline std::ostream& 00255 operator <<(std::ostream &os, const msg_endpoint endp) 00256 { 00257 os << endp.block()->alias() << ":" << pmt::symbol_to_string(endp.port()); 00258 return os; 00259 } 00260 00261 inline std::ostream& 00262 operator <<(std::ostream &os, const msg_edge edge) 00263 { 00264 os << edge.src() << "->" << edge.dst(); 00265 return os; 00266 } 00267 00268 } /* namespace gr */ 00269 00270 #endif /* INCLUDED_GR_RUNTIME_FLOWGRAPH_H */