⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gr_flowgraph.cc

📁 这是用python语言写的一个数字广播的信号处理工具包。利用它
💻 CC
字号:
/* -*- c++ -*- *//* * Copyright 2007 Free Software Foundation, Inc. *  * This file is part of GNU Radio *  * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. *  * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <gr_flowgraph.h>#include <gr_io_signature.h>#include <stdexcept>#include <sstream>#define GR_FLOWGRAPH_DEBUG 0gr_edge::~gr_edge(){}gr_flowgraph_sptr gr_make_flowgraph(){  return gr_flowgraph_sptr(new gr_flowgraph());}gr_flowgraph::gr_flowgraph(){}  gr_flowgraph::~gr_flowgraph(){}// FIXME: move to libgruel as a utility functiontemplate<class T>staticstd::vector<T>unique_vector(std::vector<T> v){  std::vector<T> result;  std::insert_iterator<std::vector<T> > inserter(result, result.begin());    sort(v.begin(), v.end());  unique_copy(v.begin(), v.end(), inserter);  return result;}voidgr_flowgraph::connect(const gr_endpoint &src, const gr_endpoint &dst){  check_valid_port(src.block()->output_signature(), src.port());  check_valid_port(dst.block()->input_signature(), dst.port());  check_dst_not_used(dst);  check_type_match(src, dst);  // All ist klar, Herr Kommisar  d_edges.push_back(gr_edge(src,dst));}voidgr_flowgraph::disconnect(const gr_endpoint &src, const gr_endpoint &dst){  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {    if (src == p->src() && dst == p->dst()) {      d_edges.erase(p);      return;    }  }  std::stringstream msg;  msg << "cannot disconnect edge " << gr_edge(src, dst) << ", not found";  throw std::invalid_argument(msg.str());}voidgr_flowgraph::validate(){  d_blocks = calc_used_blocks();  for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) {    std::vector<int> used_ports;    int ninputs, noutputs;    if (GR_FLOWGRAPH_DEBUG)      std::cout << "Validating block: " << (*p) << std::endl;    used_ports = calc_used_ports(*p, true); // inputs    ninputs = used_ports.size();    check_contiguity(*p, used_ports, true); // inputs    used_ports = calc_used_ports(*p, false); // outputs    noutputs = used_ports.size();    check_contiguity(*p, used_ports, false); // outputs    if (!((*p)->check_topology(ninputs, noutputs))) {      std::stringstream msg;      msg << "check topology failed on " << (*p)	  << " using ninputs=" << ninputs 	  << ", noutputs=" << noutputs;      throw std::runtime_error(msg.str());    }  }}voidgr_flowgraph::clear(){  // Boost shared pointers will deallocate as needed  d_blocks.clear();  d_edges.clear();}voidgr_flowgraph::check_valid_port(gr_io_signature_sptr sig, int port){  std::stringstream msg;  if (port < 0) {    msg << "negative port number " << port << " is invalid";    throw std::invalid_argument(msg.str());  }  int max = sig->max_streams();  if (max != gr_io_signature::IO_INFINITE && port >= max) {    msg << "port number " << port << " exceeds max of ";    if (max == 0)      msg << "(none)";    else      msg << max-1;    throw std::invalid_argument(msg.str());  }}voidgr_flowgraph::check_dst_not_used(const gr_endpoint &dst){  // A destination is in use if it is already on the edge list  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)    if (p->dst() == dst) {      std::stringstream msg;      msg << "destination already in use by edge " << (*p);      throw std::invalid_argument(msg.str());    }}voidgr_flowgraph::check_type_match(const gr_endpoint &src, const gr_endpoint &dst){  int src_size = src.block()->output_signature()->sizeof_stream_item(src.port());  int dst_size = dst.block()->input_signature()->sizeof_stream_item(dst.port());  if (src_size != dst_size) {    std::stringstream msg;    msg << "itemsize mismatch: " << src << " using " << src_size        << ", " << dst << " using " << dst_size;    throw std::invalid_argument(msg.str());  }}gr_basic_block_vector_tgr_flowgraph::calc_used_blocks(){  gr_basic_block_vector_t tmp;  // Collect all blocks in the edge list  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {    tmp.push_back(p->src().block());    tmp.push_back(p->dst().block());  }  return unique_vector<gr_basic_block_sptr>(tmp);}std::vector<int>gr_flowgraph::calc_used_ports(gr_basic_block_sptr block, bool check_inputs){  std::vector<int> tmp;  // Collect all seen ports   gr_edge_vector_t edges = calc_connections(block, check_inputs);  for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) {    if (check_inputs == true)      tmp.push_back(p->dst().port());    else      tmp.push_back(p->src().port());  }  return unique_vector<int>(tmp);}gr_edge_vector_tgr_flowgraph::calc_connections(gr_basic_block_sptr block, bool check_inputs){  gr_edge_vector_t result;  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {    if (check_inputs) {      if (p->dst().block() == block)	result.push_back(*p);    }    else {      if (p->src().block() == block)	result.push_back(*p);    }  }  return result; // assumes no duplicates}voidgr_flowgraph::check_contiguity(gr_basic_block_sptr block,			       const std::vector<int> &used_ports,			       bool check_inputs){  std::stringstream msg;  gr_io_signature_sptr sig =    check_inputs ? block->input_signature() : block->output_signature();  int nports = used_ports.size();  int min_ports = sig->min_streams();  int max_ports = sig->max_streams();  if (nports == 0 && min_ports == 0)    return;  if (nports < min_ports) {    msg << block << ": insufficient connected "       << (check_inputs ? "input ports " : "output ports ")       << "(" << min_ports << " needed, " << nports << " connected)";    throw std::runtime_error(msg.str());  }  if (nports > max_ports && max_ports != gr_io_signature::IO_INFINITE) {    msg << block << ": too many connected "       << (check_inputs ? "input ports " : "output ports ")       << "(" << max_ports << " allowed, " << nports << " connected)";    throw std::runtime_error(msg.str());  }  if (used_ports[nports-1]+1 != nports) {    for (int i = 0; i < nports; i++) {      if (used_ports[i] != i) {	msg << block << ": missing connection " 	    << (check_inputs ? "to input port " : "from output port ")	    << i;	throw std::runtime_error(msg.str());      }    }  }}gr_basic_block_vector_tgr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block, int port){  gr_basic_block_vector_t tmp;  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)    if (p->src() == gr_endpoint(block, port))      tmp.push_back(p->dst().block());  return unique_vector<gr_basic_block_sptr>(tmp);}gr_basic_block_vector_tgr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block){  gr_basic_block_vector_t tmp;  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)    if (p->src().block() == block)      tmp.push_back(p->dst().block());  return unique_vector<gr_basic_block_sptr>(tmp);}gr_edge_vector_tgr_flowgraph::calc_upstream_edges(gr_basic_block_sptr block){  gr_edge_vector_t result;  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++)    if (p->dst().block() == block)      result.push_back(*p);  return result; // Assume no duplicates}boolgr_flowgraph::has_block_p(gr_basic_block_sptr block){  gr_basic_block_viter_t result;  result = std::find(d_blocks.begin(), d_blocks.end(), block);  return (result != d_blocks.end());}gr_edgegr_flowgraph::calc_upstream_edge(gr_basic_block_sptr block, int port){  gr_edge result;  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {    if (p->dst() == gr_endpoint(block, port)) {      result = (*p);      break;    }  }  return result;}std::vector<gr_basic_block_vector_t>gr_flowgraph::partition(){  std::vector<gr_basic_block_vector_t> result;  gr_basic_block_vector_t blocks = calc_used_blocks();  gr_basic_block_vector_t graph;  while (blocks.size() > 0) {    graph = calc_reachable_blocks(blocks[0], blocks);    assert(graph.size());    result.push_back(topological_sort(graph));    for (gr_basic_block_viter_t p = graph.begin(); p != graph.end(); p++)      blocks.erase(find(blocks.begin(), blocks.end(), *p));  }  return result;}gr_basic_block_vector_tgr_flowgraph::calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks){  gr_basic_block_vector_t result;  // Mark all blocks as unvisited  for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++)    (*p)->set_color(gr_basic_block::WHITE);  // Recursively mark all reachable blocks  reachable_dfs_visit(block, blocks);  // Collect all the blocks that have been visited  for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++)    if ((*p)->color() == gr_basic_block::BLACK)      result.push_back(*p);  return result;}// Recursively mark all reachable blocks from given block and block listvoid gr_flowgraph::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks){  // Mark the current one as visited  block->set_color(gr_basic_block::BLACK);  // Recurse into adjacent vertices  gr_basic_block_vector_t adjacent = calc_adjacent_blocks(block, blocks);  for (gr_basic_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++)    if ((*p)->color() == gr_basic_block::WHITE)      reachable_dfs_visit(*p, blocks);}// Return a list of block adjacent to a given block along any edgegr_basic_block_vector_t gr_flowgraph::calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks){  gr_basic_block_vector_t tmp;      // Find any blocks that are inputs or outputs  for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) {    if (p->src().block() == block)      tmp.push_back(p->dst().block());    if (p->dst().block() == block)      tmp.push_back(p->src().block());  }      return unique_vector<gr_basic_block_sptr>(tmp);}gr_basic_block_vector_tgr_flowgraph::topological_sort(gr_basic_block_vector_t &blocks){  gr_basic_block_vector_t tmp;  gr_basic_block_vector_t result;  tmp = sort_sources_first(blocks);  // Start 'em all white  for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++)    (*p)->set_color(gr_basic_block::WHITE);  for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) {    if ((*p)->color() == gr_basic_block::WHITE)      topological_dfs_visit(*p, result);  }      reverse(result.begin(), result.end());  return result;}gr_basic_block_vector_tgr_flowgraph::sort_sources_first(gr_basic_block_vector_t &blocks){  gr_basic_block_vector_t sources, nonsources, result;  for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {    if (source_p(*p))      sources.push_back(*p);    else      nonsources.push_back(*p);  }  for (gr_basic_block_viter_t p = sources.begin(); p != sources.end(); p++)    result.push_back(*p);  for (gr_basic_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++)    result.push_back(*p);  return result;}boolgr_flowgraph::source_p(gr_basic_block_sptr block){  return (calc_upstream_edges(block).size() == 0);}voidgr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &output){  block->set_color(gr_basic_block::GREY);  gr_basic_block_vector_t blocks(calc_downstream_blocks(block));  for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {    switch ((*p)->color()) {    case gr_basic_block::WHITE:                 topological_dfs_visit(*p, output);      break;    case gr_basic_block::GREY:                  throw std::runtime_error("flow graph has loops!");    case gr_basic_block::BLACK:      continue;    default:      throw std::runtime_error("invalid color on block!");    }  }  block->set_color(gr_basic_block::BLACK);  output.push_back(block);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -