1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004,2009,2010,2013 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 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <gnuradio/block.h>
28 #include <gnuradio/block_detail.h>
29 #include <gnuradio/block_registry.h>
30 #include <gnuradio/buffer.h>
31 #include <gnuradio/prefs.h>
32 #include <iostream>
33 #include <stdexcept>
34 
35 namespace gr {
36 
block(const std::string & name,io_signature::sptr input_signature,io_signature::sptr output_signature)37 block::block(const std::string& name,
38              io_signature::sptr input_signature,
39              io_signature::sptr output_signature)
40     : basic_block(name, input_signature, output_signature),
41       d_output_multiple(1),
42       d_output_multiple_set(false),
43       d_unaligned(0),
44       d_is_unaligned(false),
45       d_relative_rate(1.0),
46       d_mp_relative_rate(1.0),
47       d_history(1),
48       d_attr_delay(0),
49       d_fixed_rate(false),
50       d_max_noutput_items_set(false),
51       d_max_noutput_items(0),
52       d_min_noutput_items(0),
53       d_tag_propagation_policy(TPP_ALL_TO_ALL),
54       d_priority(-1),
55       d_pc_rpc_set(false),
56       d_update_rate(false),
57       d_max_output_buffer(std::max(output_signature->max_streams(), 1), -1),
58       d_min_output_buffer(std::max(output_signature->max_streams(), 1), -1),
59       d_pmt_done(pmt::intern("done")),
60       d_system_port(pmt::intern("system"))
61 {
62     global_block_registry.register_primitive(d_symbol_name, this);
63     message_port_register_in(d_system_port);
64     configure_default_loggers(d_logger, d_debug_logger, symbol_name());
65     set_msg_handler(d_system_port, [this](pmt::pmt_t msg) { this->system_handler(msg); });
66 }
67 
~block()68 block::~block() { global_block_registry.unregister_primitive(symbol_name()); }
69 
history() const70 unsigned block::history() const { return d_history; }
71 
set_history(unsigned history)72 void block::set_history(unsigned history) { d_history = history; }
73 
declare_sample_delay(unsigned delay)74 void block::declare_sample_delay(unsigned delay)
75 {
76     d_attr_delay = delay;
77     if (d_detail) {
78         unsigned int nins = static_cast<unsigned int>(d_detail->ninputs());
79         for (unsigned int n = 0; n < nins; n++) {
80             d_detail->input(n)->declare_sample_delay(d_attr_delay);
81         }
82     }
83 }
84 
declare_sample_delay(int which,unsigned delay)85 void block::declare_sample_delay(int which, unsigned delay)
86 {
87     d_attr_delay = delay;
88     if (d_detail) {
89         d_detail->input(which)->declare_sample_delay(d_attr_delay);
90     }
91 }
92 
sample_delay(int which) const93 unsigned block::sample_delay(int which) const { return d_attr_delay; }
94 
95 // stub implementation:  1:1
96 
forecast(int noutput_items,gr_vector_int & ninput_items_required)97 void block::forecast(int noutput_items, gr_vector_int& ninput_items_required)
98 {
99     unsigned ninputs = ninput_items_required.size();
100     for (unsigned i = 0; i < ninputs; i++)
101         ninput_items_required[i] = noutput_items + history() - 1;
102 }
103 
104 // default implementation
105 
start()106 bool block::start() { return true; }
107 
stop()108 bool block::stop() { return true; }
109 
set_output_multiple(int multiple)110 void block::set_output_multiple(int multiple)
111 {
112     if (multiple < 1)
113         throw std::invalid_argument("block::set_output_multiple");
114 
115     d_output_multiple_set = true;
116     d_output_multiple = multiple;
117 }
118 
set_alignment(int multiple)119 void block::set_alignment(int multiple)
120 {
121     if (multiple < 1)
122         throw std::invalid_argument("block::set_alignment_multiple");
123 
124     d_output_multiple = multiple;
125 }
126 
set_unaligned(int na)127 void block::set_unaligned(int na)
128 {
129     // unaligned value must be less than 0 and it doesn't make sense
130     // that it's larger than the alignment value.
131     if ((na < 0) || (na > d_output_multiple))
132         throw std::invalid_argument("block::set_unaligned");
133 
134     d_unaligned = na;
135 }
136 
set_is_unaligned(bool u)137 void block::set_is_unaligned(bool u) { d_is_unaligned = u; }
138 
set_relative_rate(double relative_rate)139 void block::set_relative_rate(double relative_rate)
140 {
141     if (relative_rate <= 0.0)
142         throw std::invalid_argument(
143             "block::set_relative_rate: relative rate must be > 0.0");
144 
145     d_relative_rate = relative_rate;
146     d_mp_relative_rate = mpq_class(relative_rate);
147 }
148 
set_inverse_relative_rate(double inverse_relative_rate)149 void block::set_inverse_relative_rate(double inverse_relative_rate)
150 {
151     if (inverse_relative_rate <= 0.0)
152         throw std::invalid_argument(
153             "block::set_inverse_relative_rate: inverse relative rate must be > 0.0");
154 
155     mpq_class inv_rr_q(inverse_relative_rate);
156     set_relative_rate((uint64_t)inv_rr_q.get_den().get_ui(),
157                       (uint64_t)inv_rr_q.get_num().get_ui());
158 }
159 
set_relative_rate(uint64_t interpolation,uint64_t decimation)160 void block::set_relative_rate(uint64_t interpolation, uint64_t decimation)
161 {
162     mpz_class interp, decim;
163     if (interpolation < 1)
164         throw std::invalid_argument(
165             "block::set_relative_rate: interpolation rate cannot be 0");
166 
167     if (decimation < 1)
168         throw std::invalid_argument(
169             "block::set_relative_rate: decimation rate cannot be 0");
170 
171     mpz_import(interp.get_mpz_t(), 1, 1, sizeof(interpolation), 0, 0, &interpolation);
172     mpz_import(decim.get_mpz_t(), 1, 1, sizeof(decimation), 0, 0, &decimation);
173     d_mp_relative_rate = mpq_class(interp, decim);
174     d_mp_relative_rate.canonicalize();
175     d_relative_rate = d_mp_relative_rate.get_d();
176 }
177 
consume(int which_input,int how_many_items)178 void block::consume(int which_input, int how_many_items)
179 {
180     d_detail->consume(which_input, how_many_items);
181 }
182 
consume_each(int how_many_items)183 void block::consume_each(int how_many_items) { d_detail->consume_each(how_many_items); }
184 
produce(int which_output,int how_many_items)185 void block::produce(int which_output, int how_many_items)
186 {
187     d_detail->produce(which_output, how_many_items);
188 }
189 
fixed_rate_ninput_to_noutput(int ninput)190 int block::fixed_rate_ninput_to_noutput(int ninput)
191 {
192     throw std::runtime_error("Unimplemented");
193 }
194 
fixed_rate_noutput_to_ninput(int noutput)195 int block::fixed_rate_noutput_to_ninput(int noutput)
196 {
197     throw std::runtime_error("Unimplemented");
198 }
199 
nitems_read(unsigned int which_input)200 uint64_t block::nitems_read(unsigned int which_input)
201 {
202     if (d_detail) {
203         return d_detail->nitems_read(which_input);
204     } else {
205         // throw std::runtime_error("No block_detail associated with block yet");
206         return 0;
207     }
208 }
209 
nitems_written(unsigned int which_output)210 uint64_t block::nitems_written(unsigned int which_output)
211 {
212     if (d_detail) {
213         return d_detail->nitems_written(which_output);
214     } else {
215         // throw std::runtime_error("No block_detail associated with block yet");
216         return 0;
217     }
218 }
219 
add_item_tag(unsigned int which_output,const tag_t & tag)220 void block::add_item_tag(unsigned int which_output, const tag_t& tag)
221 {
222     d_detail->add_item_tag(which_output, tag);
223 }
224 
remove_item_tag(unsigned int which_input,const tag_t & tag)225 void block::remove_item_tag(unsigned int which_input, const tag_t& tag)
226 {
227     d_detail->remove_item_tag(which_input, tag, unique_id());
228 }
229 
get_tags_in_range(std::vector<tag_t> & v,unsigned int which_input,uint64_t start,uint64_t end)230 void block::get_tags_in_range(std::vector<tag_t>& v,
231                               unsigned int which_input,
232                               uint64_t start,
233                               uint64_t end)
234 {
235     d_detail->get_tags_in_range(v, which_input, start, end, unique_id());
236 }
237 
get_tags_in_range(std::vector<tag_t> & v,unsigned int which_input,uint64_t start,uint64_t end,const pmt::pmt_t & key)238 void block::get_tags_in_range(std::vector<tag_t>& v,
239                               unsigned int which_input,
240                               uint64_t start,
241                               uint64_t end,
242                               const pmt::pmt_t& key)
243 {
244     d_detail->get_tags_in_range(v, which_input, start, end, key, unique_id());
245 }
246 
get_tags_in_window(std::vector<tag_t> & v,unsigned int which_input,uint64_t start,uint64_t end)247 void block::get_tags_in_window(std::vector<tag_t>& v,
248                                unsigned int which_input,
249                                uint64_t start,
250                                uint64_t end)
251 {
252     d_detail->get_tags_in_range(v,
253                                 which_input,
254                                 nitems_read(which_input) + start,
255                                 nitems_read(which_input) + end,
256                                 unique_id());
257 }
258 
get_tags_in_window(std::vector<tag_t> & v,unsigned int which_input,uint64_t start,uint64_t end,const pmt::pmt_t & key)259 void block::get_tags_in_window(std::vector<tag_t>& v,
260                                unsigned int which_input,
261                                uint64_t start,
262                                uint64_t end,
263                                const pmt::pmt_t& key)
264 {
265     d_detail->get_tags_in_range(v,
266                                 which_input,
267                                 nitems_read(which_input) + start,
268                                 nitems_read(which_input) + end,
269                                 key,
270                                 unique_id());
271 }
272 
tag_propagation_policy()273 block::tag_propagation_policy_t block::tag_propagation_policy()
274 {
275     return d_tag_propagation_policy;
276 }
277 
set_tag_propagation_policy(tag_propagation_policy_t p)278 void block::set_tag_propagation_policy(tag_propagation_policy_t p)
279 {
280     d_tag_propagation_policy = p;
281 }
282 
max_noutput_items()283 int block::max_noutput_items() { return d_max_noutput_items; }
284 
set_max_noutput_items(int m)285 void block::set_max_noutput_items(int m)
286 {
287     if (m <= 0)
288         throw std::runtime_error("block::set_max_noutput_items: value for "
289                                  "max_noutput_items must be greater than 0.\n");
290 
291     d_max_noutput_items = m;
292     d_max_noutput_items_set = true;
293 }
294 
unset_max_noutput_items()295 void block::unset_max_noutput_items() { d_max_noutput_items_set = false; }
296 
is_set_max_noutput_items()297 bool block::is_set_max_noutput_items() { return d_max_noutput_items_set; }
298 
set_processor_affinity(const std::vector<int> & mask)299 void block::set_processor_affinity(const std::vector<int>& mask)
300 {
301     d_affinity = mask;
302     if (d_detail) {
303         d_detail->set_processor_affinity(d_affinity);
304     }
305 }
306 
unset_processor_affinity()307 void block::unset_processor_affinity()
308 {
309     d_affinity.clear();
310     if (d_detail) {
311         d_detail->unset_processor_affinity();
312     }
313 }
314 
active_thread_priority()315 int block::active_thread_priority()
316 {
317     if (d_detail) {
318         return d_detail->thread_priority();
319     }
320     return -1;
321 }
322 
thread_priority()323 int block::thread_priority() { return d_priority; }
324 
set_thread_priority(int priority)325 int block::set_thread_priority(int priority)
326 {
327     d_priority = priority;
328     if (d_detail) {
329         return d_detail->set_thread_priority(priority);
330     }
331     return d_priority;
332 }
333 
expand_minmax_buffer(int port)334 void block::expand_minmax_buffer(int port)
335 {
336     if ((size_t)port >= d_max_output_buffer.size())
337         set_max_output_buffer(port, -1);
338     if ((size_t)port >= d_min_output_buffer.size())
339         set_min_output_buffer(port, -1);
340 }
341 
max_output_buffer(size_t i)342 long block::max_output_buffer(size_t i)
343 {
344     if (i >= d_max_output_buffer.size())
345         throw std::invalid_argument("basic_block::max_output_buffer: port out of range.");
346     return d_max_output_buffer[i];
347 }
348 
set_max_output_buffer(long max_output_buffer)349 void block::set_max_output_buffer(long max_output_buffer)
350 {
351     for (int i = 0; i < output_signature()->max_streams(); i++) {
352         set_max_output_buffer(i, max_output_buffer);
353     }
354 }
355 
set_max_output_buffer(int port,long max_output_buffer)356 void block::set_max_output_buffer(int port, long max_output_buffer)
357 {
358     if ((size_t)port >= d_max_output_buffer.size())
359         d_max_output_buffer.push_back(max_output_buffer);
360     else
361         d_max_output_buffer[port] = max_output_buffer;
362 }
363 
min_output_buffer(size_t i)364 long block::min_output_buffer(size_t i)
365 {
366     if (i >= d_min_output_buffer.size())
367         throw std::invalid_argument("basic_block::min_output_buffer: port out of range.");
368     return d_min_output_buffer[i];
369 }
370 
set_min_output_buffer(long min_output_buffer)371 void block::set_min_output_buffer(long min_output_buffer)
372 {
373     std::cout << "set_min_output_buffer on block " << unique_id() << " to "
374               << min_output_buffer << std::endl;
375     for (int i = 0; i < output_signature()->max_streams(); i++) {
376         set_min_output_buffer(i, min_output_buffer);
377     }
378 }
379 
set_min_output_buffer(int port,long min_output_buffer)380 void block::set_min_output_buffer(int port, long min_output_buffer)
381 {
382     if ((size_t)port >= d_min_output_buffer.size())
383         d_min_output_buffer.push_back(min_output_buffer);
384     else
385         d_min_output_buffer[port] = min_output_buffer;
386 }
387 
388 
update_rate() const389 bool block::update_rate() const { return d_update_rate; }
390 
enable_update_rate(bool en)391 void block::enable_update_rate(bool en) { d_update_rate = en; }
392 
pc_noutput_items()393 float block::pc_noutput_items()
394 {
395     if (d_detail) {
396         return d_detail->pc_noutput_items();
397     } else {
398         return 0;
399     }
400 }
401 
pc_noutput_items_avg()402 float block::pc_noutput_items_avg()
403 {
404     if (d_detail) {
405         return d_detail->pc_noutput_items_avg();
406     } else {
407         return 0;
408     }
409 }
410 
pc_noutput_items_var()411 float block::pc_noutput_items_var()
412 {
413     if (d_detail) {
414         return d_detail->pc_noutput_items_var();
415     } else {
416         return 0;
417     }
418 }
419 
pc_nproduced()420 float block::pc_nproduced()
421 {
422     if (d_detail) {
423         return d_detail->pc_nproduced();
424     } else {
425         return 0;
426     }
427 }
428 
pc_nproduced_avg()429 float block::pc_nproduced_avg()
430 {
431     if (d_detail) {
432         return d_detail->pc_nproduced_avg();
433     } else {
434         return 0;
435     }
436 }
437 
pc_nproduced_var()438 float block::pc_nproduced_var()
439 {
440     if (d_detail) {
441         return d_detail->pc_nproduced_var();
442     } else {
443         return 0;
444     }
445 }
446 
pc_input_buffers_full(int which)447 float block::pc_input_buffers_full(int which)
448 {
449     if (d_detail) {
450         return d_detail->pc_input_buffers_full(static_cast<size_t>(which));
451     } else {
452         return 0;
453     }
454 }
455 
pc_input_buffers_full_avg(int which)456 float block::pc_input_buffers_full_avg(int which)
457 {
458     if (d_detail) {
459         return d_detail->pc_input_buffers_full_avg(static_cast<size_t>(which));
460     } else {
461         return 0;
462     }
463 }
464 
pc_input_buffers_full_var(int which)465 float block::pc_input_buffers_full_var(int which)
466 {
467     if (d_detail) {
468         return d_detail->pc_input_buffers_full_var(static_cast<size_t>(which));
469     } else {
470         return 0;
471     }
472 }
473 
pc_input_buffers_full()474 std::vector<float> block::pc_input_buffers_full()
475 {
476     if (d_detail) {
477         return d_detail->pc_input_buffers_full();
478     } else {
479         return std::vector<float>(1, 0);
480     }
481 }
482 
pc_input_buffers_full_avg()483 std::vector<float> block::pc_input_buffers_full_avg()
484 {
485     if (d_detail) {
486         return d_detail->pc_input_buffers_full_avg();
487     } else {
488         return std::vector<float>(1, 0);
489     }
490 }
491 
pc_input_buffers_full_var()492 std::vector<float> block::pc_input_buffers_full_var()
493 {
494     if (d_detail) {
495         return d_detail->pc_input_buffers_full_var();
496     } else {
497         return std::vector<float>(1, 0);
498     }
499 }
500 
pc_output_buffers_full(int which)501 float block::pc_output_buffers_full(int which)
502 {
503     if (d_detail) {
504         return d_detail->pc_output_buffers_full(static_cast<size_t>(which));
505     } else {
506         return 0;
507     }
508 }
509 
pc_output_buffers_full_avg(int which)510 float block::pc_output_buffers_full_avg(int which)
511 {
512     if (d_detail) {
513         return d_detail->pc_output_buffers_full_avg(static_cast<size_t>(which));
514     } else {
515         return 0;
516     }
517 }
518 
pc_output_buffers_full_var(int which)519 float block::pc_output_buffers_full_var(int which)
520 {
521     if (d_detail) {
522         return d_detail->pc_output_buffers_full_var(static_cast<size_t>(which));
523     } else {
524         return 0;
525     }
526 }
527 
pc_output_buffers_full()528 std::vector<float> block::pc_output_buffers_full()
529 {
530     if (d_detail) {
531         return d_detail->pc_output_buffers_full();
532     } else {
533         return std::vector<float>(1, 0);
534     }
535 }
536 
pc_output_buffers_full_avg()537 std::vector<float> block::pc_output_buffers_full_avg()
538 {
539     if (d_detail) {
540         return d_detail->pc_output_buffers_full_avg();
541     } else {
542         return std::vector<float>(1, 0);
543     }
544 }
545 
pc_output_buffers_full_var()546 std::vector<float> block::pc_output_buffers_full_var()
547 {
548     if (d_detail) {
549         return d_detail->pc_output_buffers_full_var();
550     } else {
551         return std::vector<float>(1, 0);
552     }
553 }
554 
pc_work_time()555 float block::pc_work_time()
556 {
557     if (d_detail) {
558         return d_detail->pc_work_time();
559     } else {
560         return 0;
561     }
562 }
563 
pc_work_time_avg()564 float block::pc_work_time_avg()
565 {
566     if (d_detail) {
567         return d_detail->pc_work_time_avg();
568     } else {
569         return 0;
570     }
571 }
572 
pc_work_time_var()573 float block::pc_work_time_var()
574 {
575     if (d_detail) {
576         return d_detail->pc_work_time_var();
577     } else {
578         return 0;
579     }
580 }
581 
pc_work_time_total()582 float block::pc_work_time_total()
583 {
584     if (d_detail) {
585         return d_detail->pc_work_time_total();
586     } else {
587         return 0;
588     }
589 }
590 
pc_throughput_avg()591 float block::pc_throughput_avg()
592 {
593     if (d_detail) {
594         return d_detail->pc_throughput_avg();
595     } else {
596         return 0;
597     }
598 }
599 
reset_perf_counters()600 void block::reset_perf_counters()
601 {
602     if (d_detail) {
603         d_detail->reset_perf_counters();
604     }
605 }
606 
607 
system_handler(pmt::pmt_t msg)608 void block::system_handler(pmt::pmt_t msg)
609 {
610     // std::cout << "system_handler " << msg << "\n";
611     pmt::pmt_t op = pmt::car(msg);
612     if (pmt::eqv(op, d_pmt_done)) {
613         d_finished = pmt::to_long(pmt::cdr(msg));
614         global_block_registry.notify_blk(d_symbol_name);
615     } else {
616         std::cout << "WARNING: bad message op on system port!\n";
617         pmt::print(msg);
618     }
619 }
620 
set_log_level(std::string level)621 void block::set_log_level(std::string level) { logger_set_level(d_logger, level); }
622 
log_level()623 std::string block::log_level()
624 {
625     std::string level;
626     logger_get_level(d_logger, level);
627     return level;
628 }
629 
notify_msg_neighbors()630 void block::notify_msg_neighbors()
631 {
632     size_t len = pmt::length(d_message_subscribers);
633     pmt::pmt_t port_names = pmt::make_vector(len, pmt::PMT_NIL);
634     pmt::pmt_t keys = pmt::dict_keys(d_message_subscribers);
635     for (size_t i = 0; i < len; i++) {
636         // for each output port
637         pmt::pmt_t oport = pmt::nth(i, keys);
638 
639         // for each subscriber on this port
640         pmt::pmt_t currlist = pmt::dict_ref(d_message_subscribers, oport, pmt::PMT_NIL);
641 
642         // iterate through subscribers on port
643         while (pmt::is_pair(currlist)) {
644             pmt::pmt_t target = pmt::car(currlist);
645 
646             pmt::pmt_t block = pmt::car(target);
647 
648             currlist = pmt::cdr(currlist);
649             basic_block_sptr blk = global_block_registry.block_lookup(block);
650             blk->post(d_system_port, pmt::cons(d_pmt_done, pmt::mp(true)));
651         }
652     }
653 }
654 
finished()655 bool block::finished()
656 {
657     if (detail()->ninputs() != 0)
658         return false;
659     else
660         return d_finished;
661 }
662 
663 
setup_pc_rpc()664 void block::setup_pc_rpc()
665 {
666     d_pc_rpc_set = true;
667 #if defined(GR_CTRLPORT) && defined(GR_PERFORMANCE_COUNTERS)
668 #include <gnuradio/rpcregisterhelpers.h>
669     d_rpc_vars.emplace_back(
670         new rpcbasic_register_trigger<block>(alias(),
671                                              "reset_perf_counters",
672                                              &block::reset_perf_counters,
673                                              "Reset the Performance Counters",
674                                              RPC_PRIVLVL_MIN));
675 
676     d_rpc_vars.emplace_back(
677         new rpcbasic_register_get<block, float>(alias(),
678                                                 "noutput_items",
679                                                 &block::pc_noutput_items,
680                                                 pmt::mp(0),
681                                                 pmt::mp(32768),
682                                                 pmt::mp(0),
683                                                 "",
684                                                 "noutput items",
685                                                 RPC_PRIVLVL_MIN,
686                                                 DISPTIME | DISPOPTSTRIP));
687 
688     d_rpc_vars.emplace_back(
689         new rpcbasic_register_get<block, float>(alias(),
690                                                 "avg noutput_items",
691                                                 &block::pc_noutput_items_avg,
692                                                 pmt::mp(0),
693                                                 pmt::mp(32768),
694                                                 pmt::mp(0),
695                                                 "",
696                                                 "Average noutput items",
697                                                 RPC_PRIVLVL_MIN,
698                                                 DISPTIME | DISPOPTSTRIP));
699 
700     d_rpc_vars.emplace_back(
701         new rpcbasic_register_get<block, float>(alias(),
702                                                 "var noutput_items",
703                                                 &block::pc_noutput_items_var,
704                                                 pmt::mp(0),
705                                                 pmt::mp(32768),
706                                                 pmt::mp(0),
707                                                 "",
708                                                 "Var. noutput items",
709                                                 RPC_PRIVLVL_MIN,
710                                                 DISPTIME | DISPOPTSTRIP));
711 
712     d_rpc_vars.emplace_back(
713         new rpcbasic_register_get<block, float>(alias(),
714                                                 "nproduced",
715                                                 &block::pc_nproduced,
716                                                 pmt::mp(0),
717                                                 pmt::mp(32768),
718                                                 pmt::mp(0),
719                                                 "",
720                                                 "items produced",
721                                                 RPC_PRIVLVL_MIN,
722                                                 DISPTIME | DISPOPTSTRIP));
723 
724     d_rpc_vars.emplace_back(
725         new rpcbasic_register_get<block, float>(alias(),
726                                                 "avg nproduced",
727                                                 &block::pc_nproduced_avg,
728                                                 pmt::mp(0),
729                                                 pmt::mp(32768),
730                                                 pmt::mp(0),
731                                                 "",
732                                                 "Average items produced",
733                                                 RPC_PRIVLVL_MIN,
734                                                 DISPTIME | DISPOPTSTRIP));
735 
736     d_rpc_vars.emplace_back(
737         new rpcbasic_register_get<block, float>(alias(),
738                                                 "var nproduced",
739                                                 &block::pc_nproduced_var,
740                                                 pmt::mp(0),
741                                                 pmt::mp(32768),
742                                                 pmt::mp(0),
743                                                 "",
744                                                 "Var. items produced",
745                                                 RPC_PRIVLVL_MIN,
746                                                 DISPTIME | DISPOPTSTRIP));
747 
748     d_rpc_vars.emplace_back(
749         new rpcbasic_register_get<block, float>(alias(),
750                                                 "work time",
751                                                 &block::pc_work_time,
752                                                 pmt::mp(0),
753                                                 pmt::mp(1e9),
754                                                 pmt::mp(0),
755                                                 "",
756                                                 "clock cycles in call to work",
757                                                 RPC_PRIVLVL_MIN,
758                                                 DISPTIME | DISPOPTSTRIP));
759 
760     d_rpc_vars.emplace_back(
761         new rpcbasic_register_get<block, float>(alias(),
762                                                 "avg work time",
763                                                 &block::pc_work_time_avg,
764                                                 pmt::mp(0),
765                                                 pmt::mp(1e9),
766                                                 pmt::mp(0),
767                                                 "",
768                                                 "Average clock cycles in call to work",
769                                                 RPC_PRIVLVL_MIN,
770                                                 DISPTIME | DISPOPTSTRIP));
771 
772     d_rpc_vars.emplace_back(
773         new rpcbasic_register_get<block, float>(alias(),
774                                                 "var work time",
775                                                 &block::pc_work_time_var,
776                                                 pmt::mp(0),
777                                                 pmt::mp(1e9),
778                                                 pmt::mp(0),
779                                                 "",
780                                                 "Var. clock cycles in call to work",
781                                                 RPC_PRIVLVL_MIN,
782                                                 DISPTIME | DISPOPTSTRIP));
783 
784     d_rpc_vars.emplace_back(
785         new rpcbasic_register_get<block, float>(alias(),
786                                                 "total work time",
787                                                 &block::pc_work_time_total,
788                                                 pmt::mp(0),
789                                                 pmt::mp(1e9),
790                                                 pmt::mp(0),
791                                                 "",
792                                                 "Total clock cycles in calls to work",
793                                                 RPC_PRIVLVL_MIN,
794                                                 DISPTIME | DISPOPTSTRIP));
795 
796     d_rpc_vars.emplace_back(new rpcbasic_register_get<block, float>(
797         alias(),
798         "avg throughput",
799         &block::pc_throughput_avg,
800         pmt::mp(0),
801         pmt::mp(1e9),
802         pmt::mp(0),
803         "items/s",
804         "Average items throughput in call to work",
805         RPC_PRIVLVL_MIN,
806         DISPTIME | DISPOPTSTRIP));
807 
808     d_rpc_vars.emplace_back(new rpcbasic_register_get<block, std::vector<float>>(
809         alias(),
810         "input \% full",
811         &block::pc_input_buffers_full,
812         pmt::make_f32vector(0, 0),
813         pmt::make_f32vector(0, 1),
814         pmt::make_f32vector(0, 0),
815         "",
816         "how full input buffers are",
817         RPC_PRIVLVL_MIN,
818         DISPTIME | DISPOPTSTRIP));
819 
820     d_rpc_vars.emplace_back(new rpcbasic_register_get<block, std::vector<float>>(
821         alias(),
822         "avg input \% full",
823         &block::pc_input_buffers_full_avg,
824         pmt::make_f32vector(0, 0),
825         pmt::make_f32vector(0, 1),
826         pmt::make_f32vector(0, 0),
827         "",
828         "Average of how full input buffers are",
829         RPC_PRIVLVL_MIN,
830         DISPTIME | DISPOPTSTRIP));
831 
832     d_rpc_vars.emplace_back(new rpcbasic_register_get<block, std::vector<float>>(
833         alias(),
834         "var input \% full",
835         &block::pc_input_buffers_full_var,
836         pmt::make_f32vector(0, 0),
837         pmt::make_f32vector(0, 1),
838         pmt::make_f32vector(0, 0),
839         "",
840         "Var. of how full input buffers are",
841         RPC_PRIVLVL_MIN,
842         DISPTIME | DISPOPTSTRIP));
843 
844     d_rpc_vars.emplace_back(new rpcbasic_register_get<block, std::vector<float>>(
845         alias(),
846         "output \% full",
847         &block::pc_output_buffers_full,
848         pmt::make_f32vector(0, 0),
849         pmt::make_f32vector(0, 1),
850         pmt::make_f32vector(0, 0),
851         "",
852         "how full output buffers are",
853         RPC_PRIVLVL_MIN,
854         DISPTIME | DISPOPTSTRIP));
855 
856     d_rpc_vars.emplace_back(new rpcbasic_register_get<block, std::vector<float>>(
857         alias(),
858         "avg output \% full",
859         &block::pc_output_buffers_full_avg,
860         pmt::make_f32vector(0, 0),
861         pmt::make_f32vector(0, 1),
862         pmt::make_f32vector(0, 0),
863         "",
864         "Average of how full output buffers are",
865         RPC_PRIVLVL_MIN,
866         DISPTIME | DISPOPTSTRIP));
867 
868     d_rpc_vars.emplace_back(new rpcbasic_register_get<block, std::vector<float>>(
869         alias(),
870         "var output \% full",
871         &block::pc_output_buffers_full_var,
872         pmt::make_f32vector(0, 0),
873         pmt::make_f32vector(0, 1),
874         pmt::make_f32vector(0, 0),
875         "",
876         "Var. of how full output buffers are",
877         RPC_PRIVLVL_MIN,
878         DISPTIME | DISPOPTSTRIP));
879 #endif /* defined(GR_CTRLPORT) && defined(GR_PERFORMANCE_COUNTERS) */
880 }
881 
identifier() const882 std::string block::identifier() const
883 {
884     return d_name + "(" + std::to_string(d_unique_id) + ")";
885 }
886 
operator <<(std::ostream & os,const block * m)887 std::ostream& operator<<(std::ostream& os, const block* m)
888 {
889     os << "<block " << m->identifier() << ">";
890     return os;
891 }
892 
general_work(int noutput_items,gr_vector_int & ninput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)893 int block::general_work(int noutput_items,
894                         gr_vector_int& ninput_items,
895                         gr_vector_const_void_star& input_items,
896                         gr_vector_void_star& output_items)
897 {
898     throw std::runtime_error("block::general_work() not implemented");
899     return 0;
900 }
901 
902 } /* namespace gr */
903