GNU Radio 3.6.5.1 C++ API
gr_block.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004,2007,2009,2010 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #ifndef INCLUDED_GR_BLOCK_H
24 #define INCLUDED_GR_BLOCK_H
25 
26 #include <gr_core_api.h>
27 #include <gr_basic_block.h>
28 #include <gr_tags.h>
29 #include <gr_logger.h>
30 
31 /*!
32  * \brief The abstract base class for all 'terminal' processing blocks.
33  * \ingroup base_blk
34  *
35  * A signal processing flow is constructed by creating a tree of
36  * hierarchical blocks, which at any level may also contain terminal nodes
37  * that actually implement signal processing functions. This is the base
38  * class for all such leaf nodes.
39 
40  * Blocks have a set of input streams and output streams. The
41  * input_signature and output_signature define the number of input
42  * streams and output streams respectively, and the type of the data
43  * items in each stream.
44  *
45  * Although blocks may consume data on each input stream at a
46  * different rate, all outputs streams must produce data at the same
47  * rate. That rate may be different from any of the input rates.
48  *
49  * User derived blocks override two methods, forecast and general_work,
50  * to implement their signal processing behavior. forecast is called
51  * by the system scheduler to determine how many items are required on
52  * each input stream in order to produce a given number of output
53  * items.
54  *
55  * general_work is called to perform the signal processing in the block.
56  * It reads the input items and writes the output items.
57  */
58 
60 
61  public:
62 
63  //! Magic return values from general_work
64  enum {
65  WORK_CALLED_PRODUCE = -2,
66  WORK_DONE = -1
67  };
68 
70  TPP_DONT = 0,
71  TPP_ALL_TO_ALL = 1,
72  TPP_ONE_TO_ONE = 2
73  };
74 
75  virtual ~gr_block ();
76 
77  /*!
78  * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...)
79  * History is the number of x_i's that are examined to produce one y_i.
80  * This comes in handy for FIR filters, where we use history to
81  * ensure that our input contains the appropriate "history" for the
82  * filter. History should be equal to the number of filter taps.
83  */
84  unsigned history () const { return d_history; }
85  void set_history (unsigned history) { d_history = history; }
86 
87  /*!
88  * \brief Return true if this block has a fixed input to output rate.
89  *
90  * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called.
91  */
92  bool fixed_rate() const { return d_fixed_rate; }
93 
94  // ----------------------------------------------------------------
95  // override these to define your behavior
96  // ----------------------------------------------------------------
97 
98  /*!
99  * \brief Estimate input requirements given output request
100  *
101  * \param noutput_items number of output items to produce
102  * \param ninput_items_required number of input items required on each input stream
103  *
104  * Given a request to product \p noutput_items, estimate the number of
105  * data items required on each input stream. The estimate doesn't have
106  * to be exact, but should be close.
107  */
108  virtual void forecast (int noutput_items,
109  gr_vector_int &ninput_items_required);
110 
111  /*!
112  * \brief compute output items from input items
113  *
114  * \param noutput_items number of output items to write on each output stream
115  * \param ninput_items number of input items available on each input stream
116  * \param input_items vector of pointers to the input items, one entry per input stream
117  * \param output_items vector of pointers to the output items, one entry per output stream
118  *
119  * \returns number of items actually written to each output stream, or -1 on EOF.
120  * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items
121  *
122  * general_work must call consume or consume_each to indicate how many items
123  * were consumed on each input stream.
124  */
125  virtual int general_work (int noutput_items,
126  gr_vector_int &ninput_items,
127  gr_vector_const_void_star &input_items,
128  gr_vector_void_star &output_items);
129 
130  /*!
131  * \brief Called to enable drivers, etc for i/o devices.
132  *
133  * This allows a block to enable an associated driver to begin
134  * transfering data just before we start to execute the scheduler.
135  * The end result is that this reduces latency in the pipeline when
136  * dealing with audio devices, usrps, etc.
137  */
138  virtual bool start();
139 
140  /*!
141  * \brief Called to disable drivers, etc for i/o devices.
142  */
143  virtual bool stop();
144 
145  // ----------------------------------------------------------------
146 
147  /*!
148  * \brief Constrain the noutput_items argument passed to forecast and general_work
149  *
150  * set_output_multiple causes the scheduler to ensure that the noutput_items
151  * argument passed to forecast and general_work will be an integer multiple
152  * of \param multiple The default value of output multiple is 1.
153  */
154  void set_output_multiple (int multiple);
155  int output_multiple () const { return d_output_multiple; }
156  bool output_multiple_set () const { return d_output_multiple_set; }
157 
158  /*!
159  * \brief Constrains buffers to work on a set item alignment (for SIMD)
160  *
161  * set_alignment_multiple causes the scheduler to ensure that the noutput_items
162  * argument passed to forecast and general_work will be an integer multiple
163  * of \param multiple The default value is 1.
164  *
165  * This control is similar to the output_multiple setting, except
166  * that if the number of items passed to the block is less than the
167  * output_multiple, this value is ignored and the block can produce
168  * like normal. The d_unaligned value is set to the number of items
169  * the block is off by. In the next call to general_work, the
170  * noutput_items is set to d_unaligned or less until
171  * d_unaligned==0. The buffers are now aligned again and the aligned
172  * calls can be performed again.
173  */
174  void set_alignment (int multiple);
175  int alignment () const { return d_output_multiple; }
176 
177  void set_unaligned (int na);
178  int unaligned () const { return d_unaligned; }
179  void set_is_unaligned (bool u);
180  bool is_unaligned () const { return d_is_unaligned; }
181 
182  /*!
183  * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed.
184  */
185  void consume (int which_input, int how_many_items);
186 
187  /*!
188  * \brief Tell the scheduler \p how_many_items were consumed on each input stream.
189  */
190  void consume_each (int how_many_items);
191 
192  /*!
193  * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output.
194  *
195  * If the block's general_work method calls produce, \p general_work must return WORK_CALLED_PRODUCE.
196  */
197  void produce (int which_output, int how_many_items);
198 
199  /*!
200  * \brief Set the approximate output rate / input rate
201  *
202  * Provide a hint to the buffer allocator and scheduler.
203  * The default relative_rate is 1.0
204  *
205  * decimators have relative_rates < 1.0
206  * interpolators have relative_rates > 1.0
207  */
208  void set_relative_rate (double relative_rate);
209 
210  /*!
211  * \brief return the approximate output rate / input rate
212  */
213  double relative_rate () const { return d_relative_rate; }
214 
215  /*
216  * The following two methods provide special case info to the
217  * scheduler in the event that a block has a fixed input to output
218  * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator
219  * override these. If you're fixed rate, subclass one of those.
220  */
221  /*!
222  * \brief Given ninput samples, return number of output samples that will be produced.
223  * N.B. this is only defined if fixed_rate returns true.
224  * Generally speaking, you don't need to override this.
225  */
226  virtual int fixed_rate_ninput_to_noutput(int ninput);
227 
228  /*!
229  * \brief Given noutput samples, return number of input samples required to produce noutput.
230  * N.B. this is only defined if fixed_rate returns true.
231  * Generally speaking, you don't need to override this.
232  */
233  virtual int fixed_rate_noutput_to_ninput(int noutput);
234 
235  /*!
236  * \brief Return the number of items read on input stream which_input
237  */
238  uint64_t nitems_read(unsigned int which_input);
239 
240  /*!
241  * \brief Return the number of items written on output stream which_output
242  */
243  uint64_t nitems_written(unsigned int which_output);
244 
245  /*!
246  * \brief Asks for the policy used by the scheduler to moved tags downstream.
247  */
248  tag_propagation_policy_t tag_propagation_policy();
249 
250  /*!
251  * \brief Set the policy by the scheduler to determine how tags are moved downstream.
252  */
253  void set_tag_propagation_policy(tag_propagation_policy_t p);
254 
255  /*!
256  * \brief Return the minimum number of output items this block can
257  * produce during a call to work.
258  *
259  * Should be 0 for most blocks. Useful if we're dealing with packets and
260  * the block produces one packet per call to work.
261  */
262  int min_noutput_items() const { return d_min_noutput_items; }
263 
264  /*!
265  * \brief Set the minimum number of output items this block can
266  * produce during a call to work.
267  *
268  * \param m the minimum noutput_items this block can produce.
269  */
270  void set_min_noutput_items(int m) { d_min_noutput_items = m; }
271 
272  /*!
273  * \brief Return the maximum number of output items this block will
274  * handle during a call to work.
275  */
276  int max_noutput_items();
277 
278  /*!
279  * \brief Set the maximum number of output items this block will
280  * handle during a call to work.
281  *
282  * \param m the maximum noutput_items this block will handle.
283  */
284  void set_max_noutput_items(int m);
285 
286  /*!
287  * \brief Clear the switch for using the max_noutput_items value of this block.
288  *
289  * When is_set_max_noutput_items() returns 'true', the scheduler
290  * will use the value returned by max_noutput_items() to limit the
291  * size of the number of items possible for this block's work
292  * function. If is_set_max_notput_items() returns 'false', then the
293  * scheduler ignores the internal value and uses the value set
294  * globally in the top_block.
295  *
296  * Use this value to clear the 'is_set' flag so the scheduler will
297  * ignore this. Use the set_max_noutput_items(m) call to both set a
298  * new value for max_noutput_items and to reenable its use in the
299  * scheduler.
300  */
301  void unset_max_noutput_items();
302 
303  /*!
304  * \brief Ask the block if the flag is or is not set to use the
305  * internal value of max_noutput_items during a call to work.
306  */
307  bool is_set_max_noutput_items();
308 
309  /*
310  * Used to expand the vectors that hold the min/max buffer sizes.
311  *
312  * Specifically, when -1 is used, the vectors are just initialized
313  * with 1 value; this is used by the flat_flowgraph to expand when
314  * required to add a new value for new ports on these blocks.
315  */
316  void expand_minmax_buffer(int port) {
317  if((size_t)port >= d_max_output_buffer.size())
318  set_max_output_buffer(port, -1);
319  if((size_t)port >= d_min_output_buffer.size())
320  set_min_output_buffer(port, -1);
321  }
322 
323  /*!
324  * \brief Returns max buffer size on output port \p i.
325  */
326  long max_output_buffer(size_t i) {
327  if(i >= d_max_output_buffer.size())
328  throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range.");
329  return d_max_output_buffer[i];
330  }
331 
332  /*!
333  * \brief Sets max buffer size on all output ports.
334  */
335  void set_max_output_buffer(long max_output_buffer) {
336  for(int i = 0; i < output_signature()->max_streams(); i++) {
337  set_max_output_buffer(i, max_output_buffer);
338  }
339  }
340 
341  /*!
342  * \brief Sets max buffer size on output port \p port.
343  */
344  void set_max_output_buffer(int port, long max_output_buffer) {
345  if((size_t)port >= d_max_output_buffer.size())
346  d_max_output_buffer.push_back(max_output_buffer);
347  else
348  d_max_output_buffer[port] = max_output_buffer;
349  }
350 
351  /*!
352  * \brief Returns min buffer size on output port \p i.
353  */
354  long min_output_buffer(size_t i) {
355  if(i >= d_min_output_buffer.size())
356  throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range.");
357  return d_min_output_buffer[i];
358  }
359 
360  /*!
361  * \brief Sets min buffer size on all output ports.
362  */
363  void set_min_output_buffer(long min_output_buffer) {
364  for(int i=0; i<output_signature()->max_streams(); i++) {
365  set_min_output_buffer(i, min_output_buffer);
366  }
367  }
368 
369  /*!
370  * \brief Sets min buffer size on output port \p port.
371  */
372  void set_min_output_buffer(int port, long min_output_buffer) {
373  if((size_t)port >= d_min_output_buffer.size())
374  d_min_output_buffer.push_back(min_output_buffer);
375  else
376  d_min_output_buffer[port] = min_output_buffer;
377  }
378 
379  // --------------- Performance counter functions -------------
380 
381  /*!
382  * \brief Gets average noutput_items performance counter.
383  */
384  float pc_noutput_items();
385 
386  /*!
387  * \brief Gets variance of noutput_items performance counter.
388  */
389  float pc_noutput_items_var();
390 
391  /*!
392  * \brief Gets average num items produced performance counter.
393  */
394  float pc_nproduced();
395 
396  /*!
397  * \brief Gets variance of num items produced performance counter.
398  */
399  float pc_nproduced_var();
400 
401  /*!
402  * \brief Gets average fullness of \p which input buffer.
403  */
404  float pc_input_buffers_full(int which);
405 
406  /*!
407  * \brief Gets variance of fullness of \p which input buffer.
408  */
409  float pc_input_buffers_full_var(int which);
410 
411  /*!
412  * \brief Gets average fullness of all input buffers.
413  */
414  std::vector<float> pc_input_buffers_full();
415 
416  /*!
417  * \brief Gets variance of fullness of all input buffers.
418  */
419  std::vector<float> pc_input_buffers_full_var();
420 
421  /*!
422  * \brief Gets average fullness of \p which input buffer.
423  */
424  float pc_output_buffers_full(int which);
425 
426  /*!
427  * \brief Gets variance of fullness of \p which input buffer.
428  */
429  float pc_output_buffers_full_var(int which);
430 
431  /*!
432  * \brief Gets average fullness of all output buffers.
433  */
434  std::vector<float> pc_output_buffers_full();
435  /*!
436  * \brief Gets variance of fullness of all output buffers.
437  */
438  std::vector<float> pc_output_buffers_full_var();
439 
440  /*!
441  * \brief Gets average clock cycles spent in work.
442  */
443  float pc_work_time();
444 
445  /*!
446  * \brief Gets average clock cycles spent in work.
447  */
448  float pc_work_time_var();
449 
450  /*!
451  * \brief Resets the performance counters
452  */
453  void reset_perf_counters();
454 
455 
456  // ----------------------------------------------------------------------------
457  // Functions to handle thread affinity
458 
459  /*!
460  * \brief Set the thread's affinity to processor core \p n.
461  *
462  * \param mask a vector of ints of the core numbers available to this block.
463  */
464  void set_processor_affinity(const std::vector<int> &mask);
465 
466  /*!
467  * \brief Remove processor affinity to a specific core.
468  */
469  void unset_processor_affinity();
470 
471  /*!
472  * \brief Get the current processor affinity.
473  */
474  std::vector<int> processor_affinity() { return d_affinity; }
475 
476  // ----------------------------------------------------------------------------
477 
478  private:
479 
480  int d_output_multiple;
481  bool d_output_multiple_set;
482  int d_unaligned;
483  bool d_is_unaligned;
484  double d_relative_rate; // approx output_rate / input_rate
485  gr_block_detail_sptr d_detail; // implementation details
486  unsigned d_history;
487  bool d_fixed_rate;
488  bool d_max_noutput_items_set; // if d_max_noutput_items is valid
489  int d_max_noutput_items; // value of max_noutput_items for this block
490  int d_min_noutput_items;
491  tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream
492  std::vector<int> d_affinity; // thread affinity proc. mask
493 
494  protected:
495  gr_block (void){} //allows pure virtual interface sub-classes
496  gr_block (const std::string &name,
497  gr_io_signature_sptr input_signature,
498  gr_io_signature_sptr output_signature);
499 
500  void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; }
501 
502 
503  /*!
504  * \brief Adds a new tag onto the given output buffer.
505  *
506  * \param which_output an integer of which output stream to attach the tag
507  * \param abs_offset a uint64 number of the absolute item number
508  * assicated with the tag. Can get from nitems_written.
509  * \param key the tag key as a PMT symbol
510  * \param value any PMT holding any value for the given key
511  * \param srcid optional source ID specifier; defaults to PMT_F
512  */
513  inline void add_item_tag(unsigned int which_output,
514  uint64_t abs_offset,
515  const pmt::pmt_t &key,
516  const pmt::pmt_t &value,
517  const pmt::pmt_t &srcid=pmt::PMT_F)
518  {
519  gr_tag_t tag;
520  tag.offset = abs_offset;
521  tag.key = key;
522  tag.value = value;
523  tag.srcid = srcid;
524  this->add_item_tag(which_output, tag);
525  }
526 
527  /*!
528  * \brief Adds a new tag onto the given output buffer.
529  *
530  * \param which_output an integer of which output stream to attach the tag
531  * \param tag the tag object to add
532  */
533  void add_item_tag(unsigned int which_output, const gr_tag_t &tag);
534 
535  /*!
536  * \brief Removes a tag from the given input buffer.
537  *
538  * \param which_input an integer of which input stream to remove the tag from
539  * \param abs_offset a uint64 number of the absolute item number
540  * assicated with the tag. Can get from nitems_written.
541  * \param key the tag key as a PMT symbol
542  * \param value any PMT holding any value for the given key
543  * \param srcid optional source ID specifier; defaults to PMT_F
544  *
545  * If no such tag is found, does nothing.
546  */
547  inline void remove_item_tag(unsigned int which_input,
548  uint64_t abs_offset,
549  const pmt::pmt_t &key,
550  const pmt::pmt_t &value,
551  const pmt::pmt_t &srcid=pmt::PMT_F)
552  {
553  gr_tag_t tag;
554  tag.offset = abs_offset;
555  tag.key = key;
556  tag.value = value;
557  tag.srcid = srcid;
558  this->remove_item_tag(which_input, tag);
559  }
560 
561  /*!
562  * \brief Removes a tag from the given input buffer.
563  *
564  * If no such tag is found, does nothing.
565  *
566  * \param which_input an integer of which input stream to remove the tag from
567  * \param tag the tag object to remove
568  */
569  void remove_item_tag(unsigned int which_input, const gr_tag_t &tag);
570 
571  /*!
572  * \brief Given a [start,end), returns a vector of all tags in the range.
573  *
574  * Range of counts is from start to end-1.
575  *
576  * Tags are tuples of:
577  * (item count, source id, key, value)
578  *
579  * \param v a vector reference to return tags into
580  * \param which_input an integer of which input stream to pull from
581  * \param abs_start a uint64 count of the start of the range of interest
582  * \param abs_end a uint64 count of the end of the range of interest
583  */
584  void get_tags_in_range(std::vector<gr_tag_t> &v,
585  unsigned int which_input,
586  uint64_t abs_start,
587  uint64_t abs_end);
588 
589  /*!
590  * \brief Given a [start,end), returns a vector of all tags in the range
591  * with a given key.
592  *
593  * Range of counts is from start to end-1.
594  *
595  * Tags are tuples of:
596  * (item count, source id, key, value)
597  *
598  * \param v a vector reference to return tags into
599  * \param which_input an integer of which input stream to pull from
600  * \param abs_start a uint64 count of the start of the range of interest
601  * \param abs_end a uint64 count of the end of the range of interest
602  * \param key a PMT symbol key to filter only tags of this key
603  */
604  void get_tags_in_range(std::vector<gr_tag_t> &v,
605  unsigned int which_input,
606  uint64_t abs_start,
607  uint64_t abs_end,
608  const pmt::pmt_t &key);
609 
610  std::vector<long> d_max_output_buffer;
611  std::vector<long> d_min_output_buffer;
612 
613  /*! Used by block's setters and work functions to make
614  * setting/resetting of parameters thread-safe.
615  *
616  * Used by calling gruel::scoped_lock l(d_setlock);
617  */
619 
620  /*! Used by blocks to access the logger system.
621  */
624 
625  // These are really only for internal use, but leaving them public avoids
626  // having to work up an ever-varying list of friend GR_CORE_APIs
627 
628  public:
629  gr_block_detail_sptr detail () const { return d_detail; }
630  void set_detail (gr_block_detail_sptr detail) { d_detail = detail; }
631 };
632 
633 typedef std::vector<gr_block_sptr> gr_block_vector_t;
634 typedef std::vector<gr_block_sptr>::iterator gr_block_viter_t;
635 
636 inline gr_block_sptr cast_to_block_sptr(gr_basic_block_sptr p)
637 {
638  return boost::dynamic_pointer_cast<gr_block, gr_basic_block>(p);
639 }
640 
641 
642 std::ostream&
643 operator << (std::ostream& os, const gr_block *m);
644 
645 #endif /* INCLUDED_GR_BLOCK_H */