summaryrefslogtreecommitdiff
path: root/gnuradio-core/src
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core/src')
-rw-r--r--gnuradio-core/src/examples/mp-sched/CMakeLists.txt1
-rwxr-xr-xgnuradio-core/src/examples/mp-sched/affinity_set.py73
-rw-r--r--gnuradio-core/src/lib/general/CMakeLists.txt1
-rw-r--r--gnuradio-core/src/lib/general/general.i2
-rw-r--r--gnuradio-core/src/lib/gengen/CMakeLists.txt1
-rw-r--r--gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t116
-rw-r--r--gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t87
-rw-r--r--gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t40
-rw-r--r--gnuradio-core/src/lib/hier/gr_channel_model.cc2
-rw-r--r--gnuradio-core/src/lib/hier/gr_channel_model.h4
-rw-r--r--gnuradio-core/src/lib/io/gr_file_source.cc10
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.cc100
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.h79
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.i14
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.cc108
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.h36
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.cc38
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc7
-rw-r--r--gnuradio-core/src/lib/runtime/gr_types.h1
-rw-r--r--gnuradio-core/src/lib/runtime/qa_gr_top_block.cc21
-rw-r--r--gnuradio-core/src/lib/runtime/qa_gr_top_block.h7
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt1
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/__init__.py1
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py55
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/tag_utils.py54
25 files changed, 832 insertions, 27 deletions
diff --git a/gnuradio-core/src/examples/mp-sched/CMakeLists.txt b/gnuradio-core/src/examples/mp-sched/CMakeLists.txt
index dc47d17f9..d2d910ecf 100644
--- a/gnuradio-core/src/examples/mp-sched/CMakeLists.txt
+++ b/gnuradio-core/src/examples/mp-sched/CMakeLists.txt
@@ -20,6 +20,7 @@
include(GrPython)
GR_PYTHON_INSTALL(PROGRAMS
+ affinity_set.py
plot_flops.py
run_synthetic.py
synthetic.py
diff --git a/gnuradio-core/src/examples/mp-sched/affinity_set.py b/gnuradio-core/src/examples/mp-sched/affinity_set.py
new file mode 100755
index 000000000..6db632e0f
--- /dev/null
+++ b/gnuradio-core/src/examples/mp-sched/affinity_set.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+##################################################
+# Gnuradio Python Flow Graph
+# Title: Affinity Set Test
+##################################################
+
+from gnuradio import eng_notation
+from gnuradio import gr
+from gnuradio.eng_option import eng_option
+from gnuradio.gr import firdes
+from optparse import OptionParser
+import sys
+
+class affinity_set(gr.top_block):
+
+ def __init__(self):
+ gr.top_block.__init__(self, "Affinity Set Test")
+
+ ##################################################
+ # Variables
+ ##################################################
+ self.samp_rate = samp_rate = 32000
+
+ ##################################################
+ # Blocks
+ ##################################################
+ vec_len = 1
+ self.gr_throttle_0 = gr.throttle(gr.sizeof_gr_complex*vec_len, samp_rate)
+ self.gr_null_source_0 = gr.null_source(gr.sizeof_gr_complex*vec_len)
+ self.gr_null_sink_0 = gr.null_sink(gr.sizeof_gr_complex*vec_len)
+ self.gr_filt_0 = gr.fir_filter_ccc(1, 40000*[0.2+0.3j,])
+ self.gr_filt_1 = gr.fir_filter_ccc(1, 40000*[0.2+0.3j,])
+
+ self.gr_filt_0.set_processor_affinity([0,])
+ self.gr_filt_1.set_processor_affinity([0,1])
+
+ ##################################################
+ # Connections
+ ##################################################
+ self.connect((self.gr_null_source_0, 0), (self.gr_throttle_0, 0))
+ self.connect((self.gr_throttle_0, 0), (self.gr_filt_0, 0))
+ self.connect((self.gr_filt_0, 0), (self.gr_filt_1, 0))
+ self.connect((self.gr_filt_1, 0), (self.gr_null_sink_0, 0))
+
+
+ # QT sink close method reimplementation
+
+ def get_samp_rate(self):
+ return self.samp_rate
+
+ def set_samp_rate(self, samp_rate):
+ self.samp_rate = samp_rate
+
+if __name__ == '__main__':
+ parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ (options, args) = parser.parse_args()
+ tb = affinity_set()
+ tb.start()
+
+ while(1):
+ ret = raw_input('Press Enter to quit: ')
+ if(len(ret) == 0):
+ tb.stop()
+ sys.exit(0)
+ elif(ret.lower() == "none"):
+ tb.gr_filt_0.unset_processor_affinity()
+ else:
+ try:
+ n = int(ret)
+ except ValueError:
+ print "Invalid number"
+ else:
+ tb.gr_filt_0.set_processor_affinity([n,])
diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt
index 4c99acfc3..ce9a80f37 100644
--- a/gnuradio-core/src/lib/general/CMakeLists.txt
+++ b/gnuradio-core/src/lib/general/CMakeLists.txt
@@ -259,6 +259,7 @@ set(gr_core_general_triple_threats
gr_pwr_squelch_cc
gr_pwr_squelch_ff
gr_quadrature_demod_cf
+ gr_random_pdu
gr_rail_ff
gr_regenerate_bb
gr_remez
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index 1446088a2..b727bc8a6 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -70,6 +70,7 @@
#include <gr_agc_cc.h>
#include <gr_agc2_ff.h>
#include <gr_agc2_cc.h>
+#include <gr_random_pdu.h>
#include <gr_rms_cf.h>
#include <gr_rms_ff.h>
#include <gr_nlog10_ff.h>
@@ -194,6 +195,7 @@
%include "gr_agc_cc.i"
%include "gr_agc2_ff.i"
%include "gr_agc2_cc.i"
+%include "gr_random_pdu.i"
%include "gr_rms_cf.i"
%include "gr_rms_ff.i"
%include "gr_nlog10_ff.i"
diff --git a/gnuradio-core/src/lib/gengen/CMakeLists.txt b/gnuradio-core/src/lib/gengen/CMakeLists.txt
index b44a47075..db3103a26 100644
--- a/gnuradio-core/src/lib/gengen/CMakeLists.txt
+++ b/gnuradio-core/src/lib/gengen/CMakeLists.txt
@@ -85,6 +85,7 @@ expand_h_cc_i(gr_vector_source_X b s i f c)
expand_h_cc_i(gr_vector_insert_X b)
expand_h_cc_i(gr_vector_sink_X b s i f c)
expand_h_cc_i(gr_noise_source_X s i f c)
+expand_h_cc_i(gr_fastnoise_source_X s i f c)
expand_h_cc_i(gr_sig_source_X s i f c)
expand_h_cc_i(gr_probe_signal_X b s i f c)
expand_h_cc_i(gr_probe_signal_vX b s i f c)
diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t
new file mode 100644
index 000000000..7be7bdde8
--- /dev/null
+++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t
@@ -0,0 +1,116 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010 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.
+ */
+
+// @WARNING@
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <@NAME@.h>
+#include <gr_io_signature.h>
+#include <stdexcept>
+
+
+@NAME@_sptr
+gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed, long samples)
+{
+ return gnuradio::get_initial_sptr(new @NAME@ (type, ampl, seed, samples));
+}
+
+
+@NAME@::@NAME@ (gr_noise_type_t type, float ampl, long seed, long samples)
+ : gr_sync_block ("@BASE_NAME@",
+ gr_make_io_signature (0, 0, 0),
+ gr_make_io_signature (1, 1, sizeof (@TYPE@))),
+ d_type (type),
+ d_ampl (ampl),
+ d_rng (seed)
+{
+ d_samples.resize(samples);
+ generate();
+}
+
+void
+@NAME@::generate()
+{
+ int noutput_items = d_samples.size();
+ switch (d_type){
+#if @IS_COMPLEX@ // complex?
+
+ case GR_UNIFORM:
+ for (int i = 0; i < noutput_items; i++)
+ d_samples[i] = gr_complex (d_ampl * ((d_rng.ran1 () * 2.0) - 1.0),
+ d_ampl * ((d_rng.ran1 () * 2.0) - 1.0));
+ break;
+
+ case GR_GAUSSIAN:
+ for (int i = 0; i < noutput_items; i++)
+ d_samples[i] = d_ampl * d_rng.rayleigh_complex ();
+ break;
+
+#else // nope...
+
+ case GR_UNIFORM:
+ for (int i = 0; i < noutput_items; i++)
+ d_samples[i] = (@TYPE@)(d_ampl * ((d_rng.ran1 () * 2.0) - 1.0));
+ break;
+
+ case GR_GAUSSIAN:
+ for (int i = 0; i < noutput_items; i++)
+ d_samples[i] = (@TYPE@)(d_ampl * d_rng.gasdev ());
+ break;
+
+ case GR_LAPLACIAN:
+ for (int i = 0; i < noutput_items; i++)
+ d_samples[i] = (@TYPE@)(d_ampl * d_rng.laplacian ());
+ break;
+
+ case GR_IMPULSE: // FIXME changeable impulse settings
+ for (int i = 0; i < noutput_items; i++)
+ d_samples[i] = (@TYPE@)(d_ampl * d_rng.impulse (9));
+ break;
+#endif
+
+ default:
+ throw std::runtime_error ("invalid type");
+ }
+
+}
+
+int
+@NAME@::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ @TYPE@ *out = (@TYPE@ *) output_items[0];
+
+ for(int i=0; i<noutput_items; i++){
+#ifdef __USE_GNU
+ size_t idx = lrand48() % d_samples.size();
+#else
+ size_t idx = rand() % d_samples.size();
+#endif
+ out[i] = d_samples[idx];
+ }
+
+ return noutput_items;
+}
diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t
new file mode 100644
index 000000000..007e44975
--- /dev/null
+++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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.
+ */
+
+// @WARNING@
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+#include <gr_noise_type.h>
+#include <gr_random.h>
+
+
+class @NAME@;
+typedef boost::shared_ptr<@NAME@> @NAME@_sptr;
+
+/*! \brief Make a noise source
+ * \param type the random distribution to use (see gr_noise_type.h)
+ * \param ampl a scaling factor for the output
+ * \param seed seed for random generators. Note that for uniform and
+ * Gaussian distributions, this should be a negative number.
+ * \param samples number of samples to pre-generate.
+ */
+GR_CORE_API @NAME@_sptr
+gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples=1024*16);
+
+/*!
+ * \brief Random number source
+ * \ingroup source_blk
+ *
+ * \details
+ * Generate random values from different distributions.
+ * Currently, only Gaussian and uniform are enabled.
+ *
+ * \param type the random distribution to use (see gr_noise_type.h)
+ * \param ampl a scaling factor for the output
+ * \param seed seed for random generators. Note that for uniform and
+ * Gaussian distributions, this should be a negative number.
+ * \param samples number of samples to pre-generate.
+ */
+class GR_CORE_API @NAME@ : public gr_sync_block {
+ friend GR_CORE_API @NAME@_sptr
+
+ gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed, long samples);
+
+ gr_noise_type_t d_type;
+ float d_ampl;
+ gr_random d_rng;
+ std::vector<@TYPE@> d_samples;
+
+ @NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples=1024*16);
+
+ public:
+ void set_type (gr_noise_type_t type) { d_type = type; generate(); }
+ void set_amplitude (float ampl) { d_ampl = ampl; generate(); }
+ void generate();
+
+ gr_noise_type_t type () const { return d_type; }
+ float amplitude () const { return d_ampl; }
+
+ virtual int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+
+#endif
diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t
new file mode 100644
index 000000000..e1f7c775b
--- /dev/null
+++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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.
+ */
+
+// @WARNING@
+
+GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@);
+
+@NAME@_sptr
+gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples = 1024*16);
+
+class @NAME@ : public gr_block {
+ private:
+ @NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples = 1024*16);
+
+ public:
+ void set_type (gr_noise_type_t type) { d_type = type; }
+ void set_amplitude (float ampl) { d_ampl = ampl; }
+
+ gr_noise_type_t type () const { return d_type; }
+ float amplitude () const { return d_ampl; }
+};
diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.cc b/gnuradio-core/src/lib/hier/gr_channel_model.cc
index bb01972d2..7da357809 100644
--- a/gnuradio-core/src/lib/hier/gr_channel_model.cc
+++ b/gnuradio-core/src/lib/hier/gr_channel_model.cc
@@ -59,7 +59,7 @@ gr_channel_model::gr_channel_model(double noise_voltage,
d_multipath = gr_make_fir_filter_ccc(1, d_taps);
d_noise_adder = gr_make_add_cc();
- d_noise = gr_make_noise_source_c(GR_GAUSSIAN, noise_voltage, noise_seed);
+ d_noise = gr_make_fastnoise_source_c(GR_GAUSSIAN, noise_voltage, noise_seed, 1024*8);
d_freq_offset = gr_make_sig_source_c(1, GR_SIN_WAVE, frequency_offset, 1.0, 0.0);
d_mixer_offset = gr_make_multiply_cc();
diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.h b/gnuradio-core/src/lib/hier/gr_channel_model.h
index f0b31b1a6..5796a6db2 100644
--- a/gnuradio-core/src/lib/hier/gr_channel_model.h
+++ b/gnuradio-core/src/lib/hier/gr_channel_model.h
@@ -25,7 +25,7 @@
#include <gr_sig_source_c.h>
#include <gr_fir_filter_ccc.h>
#include <gr_add_cc.h>
-#include <gr_noise_source_c.h>
+#include <gr_fastnoise_source_c.h>
#include <gr_multiply_cc.h>
class gr_channel_model;
@@ -61,7 +61,7 @@ class GR_CORE_API gr_channel_model : public gr_hier_block2
gr_sig_source_c_sptr d_freq_offset;
gr_fir_filter_ccc_sptr d_multipath;
gr_add_cc_sptr d_noise_adder;
- gr_noise_source_c_sptr d_noise;
+ gr_fastnoise_source_c_sptr d_noise;
gr_multiply_cc_sptr d_mixer_offset;
std::vector<gr_complex> d_taps;
diff --git a/gnuradio-core/src/lib/io/gr_file_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc
index 09f3986cd..f3def0721 100644
--- a/gnuradio-core/src/lib/io/gr_file_source.cc
+++ b/gnuradio-core/src/lib/io/gr_file_source.cc
@@ -89,7 +89,7 @@ gr_file_source::work (int noutput_items,
if(d_fp == NULL)
throw std::runtime_error("work with file not open");
- boost::mutex::scoped_lock lock(fp_mutex); // hold for the rest of this function
+ gruel::scoped_lock lock(fp_mutex); // hold for the rest of this function
while (size) {
i = fread(o, d_itemsize, size, (FILE *) d_fp);
@@ -129,7 +129,7 @@ bool
gr_file_source::seek (long seek_point, int whence)
{
// obtain exclusive access for duration of this function
- boost::mutex::scoped_lock lock(fp_mutex);
+ gruel::scoped_lock lock(fp_mutex);
return fseek((FILE *) d_fp, seek_point * d_itemsize, whence) == 0;
}
@@ -137,7 +137,7 @@ void
gr_file_source::open(const char *filename, bool repeat)
{
// obtain exclusive access for duration of this function
- boost::mutex::scoped_lock lock(fp_mutex);
+ gruel::scoped_lock lock(fp_mutex);
int fd;
@@ -166,7 +166,7 @@ void
gr_file_source::close()
{
// obtain exclusive access for duration of this function
- boost::mutex::scoped_lock lock(fp_mutex);
+ gruel::scoped_lock lock(fp_mutex);
if(d_new_fp != NULL) {
fclose(d_new_fp);
@@ -179,7 +179,7 @@ void
gr_file_source::do_update()
{
if(d_updated) {
- boost::mutex::scoped_lock lock(fp_mutex); // hold while in scope
+ gruel::scoped_lock lock(fp_mutex); // hold while in scope
if(d_fp)
fclose(d_fp);
diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc
index 5ba30955f..f52f7a6ba 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block.cc
@@ -31,8 +31,8 @@
#include <gr_block_registry.h>
gr_block::gr_block (const std::string &name,
- gr_io_signature_sptr input_signature,
- gr_io_signature_sptr output_signature)
+ gr_io_signature_sptr input_signature,
+ gr_io_signature_sptr output_signature)
: gr_basic_block(name, input_signature, output_signature),
d_output_multiple (1),
d_output_multiple_set(false),
@@ -43,6 +43,7 @@ gr_block::gr_block (const std::string &name,
d_fixed_rate(false),
d_max_noutput_items_set(false),
d_max_noutput_items(0),
+ d_min_noutput_items(0),
d_tag_propagation_policy(TPP_ALL_TO_ALL),
d_max_output_buffer(std::max(output_signature->max_streams(),1), -1),
d_min_output_buffer(std::max(output_signature->max_streams(),1), -1)
@@ -251,6 +252,101 @@ gr_block::is_set_max_noutput_items()
return d_max_noutput_items_set;
}
+void
+gr_block::set_processor_affinity(const std::vector<unsigned int> &mask)
+{
+ d_affinity = mask;
+ if(d_detail) {
+ d_detail->set_processor_affinity(d_affinity);
+ }
+}
+
+void
+gr_block::unset_processor_affinity()
+{
+ d_affinity.clear();
+ if(d_detail) {
+ d_detail->unset_processor_affinity();
+ }
+}
+
+float
+gr_block::pc_noutput_items()
+{
+ if(d_detail) {
+ return d_detail->pc_noutput_items();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_nproduced()
+{
+ if(d_detail) {
+ return d_detail->pc_nproduced();
+ }
+ else {
+ return 0;
+ }
+}
+
+float
+gr_block::pc_input_buffers_full(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
+std::vector<float>
+gr_block::pc_input_buffers_full()
+{
+ if(d_detail) {
+ return d_detail->pc_input_buffers_full();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
+float
+gr_block::pc_output_buffers_full(int which)
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full(static_cast<size_t>(which));
+ }
+ else {
+ return 0;
+ }
+}
+
+std::vector<float>
+gr_block::pc_output_buffers_full()
+{
+ if(d_detail) {
+ return d_detail->pc_output_buffers_full();
+ }
+ else {
+ return std::vector<float>(1,0);
+ }
+}
+
+float
+gr_block::pc_work_time()
+{
+ if(d_detail) {
+ return d_detail->pc_work_time();
+ }
+ else {
+ return 0;
+ }
+}
+
std::ostream&
operator << (std::ostream& os, const gr_block *m)
{
diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h
index 7a70bdaf0..bd9ff42df 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_block.h
@@ -252,13 +252,30 @@ class GR_CORE_API gr_block : public gr_basic_block {
void set_tag_propagation_policy(tag_propagation_policy_t p);
/*!
+ * \brief Return the minimum number of output items this block can
+ * produce during a call to work.
+ *
+ * Should be 0 for most blocks. Useful if we're dealing with packets and
+ * the block produces one packet per call to work.
+ */
+ int min_noutput_items() const { return d_min_noutput_items; }
+
+ /*!
+ * \brief Set the minimum number of output items this block can
+ * produce during a call to work.
+ *
+ * \param m the minimum noutput_items this block can produce.
+ */
+ void set_min_noutput_items(int m) { d_min_noutput_items = m; }
+
+ /*!
* \brief Return the maximum number of output items this block will
* handle during a call to work.
*/
int max_noutput_items();
/*!
- * \brief Set the maximum number of ouput items htis block will
+ * \brief Set the maximum number of output items this block will
* handle during a call to work.
*
* \param m the maximum noutput_items this block will handle.
@@ -358,6 +375,64 @@ class GR_CORE_API gr_block : public gr_basic_block {
d_min_output_buffer[port] = min_output_buffer;
}
+ // --------------- Performance counter functions -------------
+
+ /*!
+ * \brief Gets average noutput_items performance counter.
+ */
+ float pc_noutput_items();
+
+ /*!
+ * \brief Gets average num items produced performance counter.
+ */
+ float pc_nproduced();
+
+ /*!
+ * \brief Gets average average fullness of \p which input buffer.
+ */
+ float pc_input_buffers_full(int which);
+
+ /*!
+ * \brief Gets average fullness of all input buffers.
+ */
+ std::vector<float> pc_input_buffers_full();
+
+ /*!
+ * \brief Gets average fullness of \p which input buffer.
+ */
+ float pc_output_buffers_full(int which);
+
+ /*!
+ * \brief Gets average fullness of all output buffers.
+ */
+ std::vector<float> pc_output_buffers_full();
+
+ /*!
+ * \brief Gets average clock cycles spent in work.
+ */
+ float pc_work_time();
+
+
+ // ----------------------------------------------------------------------------
+ // Functions to handle thread affinity
+
+ /*!
+ * \brief Set the thread's affinity to processor core \p n.
+ *
+ * \param mask a vector of unsigned ints of the core numbers available to this block.
+ */
+ void set_processor_affinity(const std::vector<unsigned int> &mask);
+
+ /*!
+ * \brief Remove processor affinity to a specific core.
+ */
+ void unset_processor_affinity();
+
+ /*!
+ * \brief Get the current processor affinity.
+ */
+ std::vector<unsigned int> processor_affinity() { return d_affinity; }
+
// ----------------------------------------------------------------------------
private:
@@ -370,9 +445,11 @@ class GR_CORE_API gr_block : public gr_basic_block {
gr_block_detail_sptr d_detail; // implementation details
unsigned d_history;
bool d_fixed_rate;
+ int d_min_noutput_items;
bool d_max_noutput_items_set; // if d_max_noutput_items is valid
int d_max_noutput_items; // value of max_noutput_items for this block
tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream
+ std::vector<unsigned int> d_affinity; // thread affinity proc. mask
protected:
gr_block (void){} //allows pure virtual interface sub-classes
diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i
index db6c1d04a..c016f2c28 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_block.i
@@ -66,6 +66,20 @@ class gr_block : public gr_basic_block {
void set_min_output_buffer(long min_output_buffer);
void set_min_output_buffer(int port, long min_output_buffer);
+ // Methods to access performance counters
+ float pc_noutput_items();
+ float pc_nproduced();
+ float pc_input_buffers_full(int which);
+ std::vector<float> pc_input_buffers_full();
+ float pc_output_buffers_full(int which);
+ std::vector<float> pc_output_buffers_full();
+ float pc_work_time();
+
+ // Methods to manage processor affinity.
+ void set_processor_affinity(const gr_vector_uint &mask);
+ void unset_processor_affinity();
+ gr_vector_uint processor_affinity();
+
// internal use
gr_block_detail_sptr detail () const { return d_detail; }
void set_detail (gr_block_detail_sptr detail) { d_detail = detail; }
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
index c65493473..ff20e0e85 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
@@ -26,6 +26,7 @@
#include <gr_block_detail.h>
#include <gr_buffer.h>
+#include <iostream>
using namespace pmt;
@@ -41,7 +42,11 @@ gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs)
: d_produce_or(0),
d_ninputs (ninputs), d_noutputs (noutputs),
d_input (ninputs), d_output (noutputs),
- d_done (false)
+ d_done (false),
+ d_avg_noutput_items(0), d_avg_nproduced(0),
+ d_avg_input_buffers_full(ninputs, 0),
+ d_avg_output_buffers_full(noutputs, 0),
+ d_avg_work_time(0)
{
s_ncurrently_allocated++;
}
@@ -201,3 +206,104 @@ gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v,
}
}
}
+
+void
+gr_block_detail::set_processor_affinity(const std::vector<unsigned int> &mask)
+{
+ if(threaded) {
+ try {
+ gruel::thread_bind_to_processor(thread, mask);
+ }
+ catch (std::runtime_error e) {
+ std::cerr << "set_processor_affinity: invalid mask." << std::endl;;
+ }
+ }
+}
+
+void
+gr_block_detail::unset_processor_affinity()
+{
+ if(threaded) {
+ gruel::thread_unbind(thread);
+ }
+}
+
+void
+gr_block_detail::start_perf_counters()
+{
+ d_start_of_work = gruel::high_res_timer_now();
+}
+
+void
+gr_block_detail::stop_perf_counters(int noutput_items, int nproduced)
+{
+ float alpha = 0.05;
+ float beta = 1.0-alpha;
+
+ d_end_of_work = gruel::high_res_timer_now();
+ gruel::high_res_timer_type diff = d_end_of_work - d_start_of_work;
+ d_avg_work_time = beta*d_avg_work_time + alpha*diff;
+
+ d_avg_nproduced = beta*d_avg_nproduced + alpha*nproduced;
+ d_avg_noutput_items = beta*d_avg_noutput_items + alpha*noutput_items;
+
+ for(size_t i=0; i < d_input.size(); i++) {
+ float pfull = static_cast<float>(d_input[i]->items_available()) /
+ static_cast<float>(d_input[i]->max_possible_items_available());
+ d_avg_input_buffers_full[i] = beta*d_avg_input_buffers_full[i] + alpha*pfull;
+ }
+
+ for(size_t i=0; i < d_output.size(); i++) {
+ float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) /
+ static_cast<float>(d_output[i]->bufsize());
+ d_avg_output_buffers_full[i] = beta*d_avg_output_buffers_full[i] + alpha*pfull;
+ }
+}
+
+float
+gr_block_detail::pc_noutput_items()
+{
+ return d_avg_noutput_items;
+}
+
+float
+gr_block_detail::pc_nproduced()
+{
+ return d_avg_nproduced;
+}
+
+float
+gr_block_detail::pc_input_buffers_full(size_t which)
+{
+ if(which < d_avg_input_buffers_full.size())
+ return d_avg_input_buffers_full[which];
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_input_buffers_full()
+{
+ return d_avg_input_buffers_full;
+}
+
+float
+gr_block_detail::pc_output_buffers_full(size_t which)
+{
+ if(which < d_avg_output_buffers_full.size())
+ return d_avg_output_buffers_full[which];
+ else
+ return 0;
+}
+
+std::vector<float>
+gr_block_detail::pc_output_buffers_full()
+{
+ return d_avg_output_buffers_full;
+}
+
+float
+gr_block_detail::pc_work_time()
+{
+ return d_avg_work_time;
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h
index af00ea7c7..a8ed8da90 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h
@@ -27,6 +27,7 @@
#include <gr_runtime_types.h>
#include <gr_tpb_detail.h>
#include <gr_tags.h>
+#include <gruel/high_res_timer.h>
#include <stdexcept>
/*!
@@ -155,6 +156,33 @@ class GR_CORE_API gr_block_detail {
uint64_t abs_end,
const pmt::pmt_t &key);
+ /*!
+ * \brief Set core affinity of block to the cores in the vector mask.
+ *
+ * \param mask a vector of unsigned ints of the core numbers available to this block.
+ */
+ void set_processor_affinity(const std::vector<unsigned int> &mask);
+
+ /*!
+ * \brief Unset core affinity.
+ */
+ void unset_processor_affinity();
+
+ bool threaded; // set if thread is currently running.
+ gruel::gr_thread_t thread; // portable thread handle
+
+ void start_perf_counters();
+ void stop_perf_counters(int noutput_items, int nproduced);
+
+ // Calls to get performance counter items
+ float pc_noutput_items();
+ float pc_nproduced();
+ float pc_input_buffers_full(size_t which);
+ std::vector<float> pc_input_buffers_full();
+ float pc_output_buffers_full(size_t which);
+ std::vector<float> pc_output_buffers_full();
+ float pc_work_time();
+
gr_tpb_detail d_tpb; // used by thread-per-block scheduler
int d_produce_or;
@@ -167,6 +195,14 @@ class GR_CORE_API gr_block_detail {
std::vector<gr_buffer_sptr> d_output;
bool d_done;
+ // Performance counters
+ float d_avg_noutput_items;
+ float d_avg_nproduced;
+ std::vector<float> d_avg_input_buffers_full;
+ std::vector<float> d_avg_output_buffers_full;
+ gruel::high_res_timer_type d_start_of_work, d_end_of_work;
+ float d_avg_work_time;
+
gr_block_detail (unsigned int ninputs, unsigned int noutputs);
friend struct gr_tpb_detail;
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
index 375b58f56..27f591452 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
@@ -64,22 +64,21 @@ round_down (unsigned int n, unsigned int multiple)
// on is done.
//
static int
-min_available_space (gr_block_detail *d, int output_multiple)
+min_available_space (gr_block_detail *d, int output_multiple, int min_noutput_items)
{
- int min_space = std::numeric_limits<int>::max();
-
+ int min_space = std::numeric_limits<int>::max();
+ if (min_noutput_items == 0)
+ min_noutput_items = 1;
for (int i = 0; i < d->noutputs (); i++){
gruel::scoped_lock guard(*d->output(i)->mutex());
-#if 0
- int n = round_down(d->output(i)->space_available(), output_multiple);
-#else
- int n = round_down(std::min(d->output(i)->space_available(),
- d->output(i)->bufsize()/2),
- output_multiple);
-#endif
- if (n == 0){ // We're blocked on output.
- if (d->output(i)->done()){ // Downstream is done, therefore we're done.
- return -1;
+ int avail_n = round_down(d->output(i)->space_available(), output_multiple);
+ int best_n = round_down(d->output(i)->bufsize()/2, output_multiple);
+ if (best_n < min_noutput_items)
+ throw std::runtime_error("Buffer too small for min_noutput_items");
+ int n = std::min(avail_n, best_n);
+ if (n < min_noutput_items){ // We're blocked on output.
+ if (d->output(i)->done()){ // Downstream is done, therefore we're done.
+ return -1;
}
return 0;
}
@@ -205,7 +204,7 @@ gr_block_executor::run_one_iteration()
d_start_nitems_read.resize(0);
// determine the minimum available output space
- noutput_items = min_available_space (d, m->output_multiple ());
+ noutput_items = min_available_space (d, m->output_multiple (), m->min_noutput_items ());
noutput_items = std::min(noutput_items, max_noutput_items);
LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl);
if (noutput_items == -1) // we're done
@@ -286,7 +285,7 @@ gr_block_executor::run_one_iteration()
}
// determine the minimum available output space
- noutput_items = min_available_space (d, m->output_multiple ());
+ noutput_items = min_available_space (d, m->output_multiple (), m->min_noutput_items ());
if (ENABLE_LOGGING){
*d_log << " regular ";
if (m->relative_rate() >= 1.0)
@@ -420,9 +419,18 @@ gr_block_executor::run_one_iteration()
for (int i = 0; i < d->ninputs(); i++)
d_start_nitems_read[i] = d->nitems_read(i);
+#ifdef GR_PERFORMANCE_COUNTERS
+ d->start_perf_counters();
+#endif /* GR_PERFORMANCE_COUNTERS */
+
// Do the actual work of the block
int n = m->general_work (noutput_items, d_ninput_items,
d_input_items, d_output_items);
+
+#ifdef GR_PERFORMANCE_COUNTERS
+ d->stop_perf_counters(noutput_items, n);
+#endif /* GR_PERFORMANCE_COUNTERS */
+
LOG(*d_log << " general_work: noutput_items = " << noutput_items
<< " result = " << n << std::endl);
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
index 9f17a48a8..cea374fac 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
@@ -38,6 +38,13 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_item
gr_block_executor::state s;
pmt_t msg;
+ d->threaded = true;
+ d->thread = gruel::get_current_thread_id();
+
+ // Set thread affinity if it was set before fg was started.
+ if(block->processor_affinity().size() > 0) {
+ gruel::thread_bind_to_processor(d->thread, block->processor_affinity());
+ }
while (1){
boost::this_thread::interruption_point();
diff --git a/gnuradio-core/src/lib/runtime/gr_types.h b/gnuradio-core/src/lib/runtime/gr_types.h
index ad6cee768..db13e456a 100644
--- a/gnuradio-core/src/lib/runtime/gr_types.h
+++ b/gnuradio-core/src/lib/runtime/gr_types.h
@@ -31,6 +31,7 @@
#include <gr_complex.h>
typedef std::vector<int> gr_vector_int;
+typedef std::vector<unsigned int> gr_vector_uint;
typedef std::vector<float> gr_vector_float;
typedef std::vector<double> gr_vector_double;
typedef std::vector<void *> gr_vector_void_star;
diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc
index a0b4755a8..1d3dafadf 100644
--- a/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc
+++ b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc
@@ -262,3 +262,24 @@ void qa_gr_top_block::t10_reconfig_max_output_buffer()
// Wait for flowgraph to end on its own
tb->wait();
}
+
+void qa_gr_top_block::t11_set_block_affinity()
+{
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(float)));
+ gr_block_sptr snk (gr_make_null_sink(sizeof(float)));
+
+ std::vector<unsigned int> set(1, 0), ret;
+ src->set_processor_affinity(set);
+
+ tb->connect(src, 0, snk, 0);
+ tb->start();
+ tb->stop();
+ tb->wait();
+
+ ret = src->processor_affinity();
+
+ // We only set the core affinity to 0 because we always know at
+ // least one thread core exists to use.
+ CPPUNIT_ASSERT_EQUAL(set[0], ret[0]);
+}
diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.h b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h
index bb891abca..634eeab1f 100644
--- a/gnuradio-core/src/lib/runtime/qa_gr_top_block.h
+++ b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h
@@ -38,6 +38,11 @@ class qa_gr_top_block : public CppUnit::TestCase
CPPUNIT_TEST(t4_reconfigure); // triggers 'join never returns' bug
CPPUNIT_TEST(t5_max_noutputs);
CPPUNIT_TEST(t6_reconfig_max_noutputs);
+ CPPUNIT_TEST(t7_max_noutputs_per_block);
+ CPPUNIT_TEST(t8_reconfig_max_noutputs_per_block);
+ CPPUNIT_TEST(t9_max_output_buffer);
+ CPPUNIT_TEST(t10_reconfig_max_output_buffer);
+ CPPUNIT_TEST(t11_set_block_affinity);
CPPUNIT_TEST_SUITE_END();
@@ -54,6 +59,8 @@ private:
void t8_reconfig_max_noutputs_per_block();
void t9_max_output_buffer();
void t10_reconfig_max_output_buffer();
+ void t11_set_block_affinity();
+
};
#endif /* INCLUDED_QA_GR_TOP_BLOCK_H */
diff --git a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
index bd78c8fb4..da22a5f98 100644
--- a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
+++ b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt
@@ -29,6 +29,7 @@ GR_PYTHON_INSTALL(FILES
gr_threading_24.py
hier_block2.py
prefs.py
+ tag_utils.py
top_block.py
pubsub.py
DESTINATION ${GR_PYTHON_DIR}/gnuradio/gr
diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py
index 5d01ea11b..f1b971e62 100644
--- a/gnuradio-core/src/python/gnuradio/gr/__init__.py
+++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py
@@ -29,6 +29,7 @@ from exceptions import *
from hier_block2 import *
from top_block import *
from gateway import basic_block, sync_block, decim_block, interp_block
+from tag_utils import tag_to_python, tag_to_pmt
# create a couple of aliases
serial_to_parallel = stream_to_vector
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py
new file mode 100755
index 000000000..ca1184979
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+#
+# Copyright 2007,2010 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.
+#
+
+from gnuradio import gr, gr_unittest
+import tag_utils
+
+try:
+ import pmt_swig as pmt
+except ImportError:
+ import pmt
+
+class test_tag_utils (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001(self):
+ t = gr.gr_tag_t()
+ t.offset = 10
+ t.key = pmt.pmt_string_to_symbol('key')
+ t.value = pmt.pmt_from_long(23)
+ t.srcid = pmt.pmt_from_bool(False)
+ pt = tag_utils.tag_to_python(t)
+ self.assertEqual(pt.key, 'key')
+ self.assertEqual(pt.value, 23)
+ self.assertEqual(pt.offset, 10)
+
+
+if __name__ == '__main__':
+ print 'hi'
+ gr_unittest.run(test_tag_utils, "test_tag_utils.xml")
+
diff --git a/gnuradio-core/src/python/gnuradio/gr/tag_utils.py b/gnuradio-core/src/python/gnuradio/gr/tag_utils.py
new file mode 100644
index 000000000..923718fc9
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/tag_utils.py
@@ -0,0 +1,54 @@
+#
+# Copyright 2003-2012 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.
+#
+""" Conversion tools between stream tags and Python objects """
+
+try: import pmt
+except: from gruel import pmt
+
+from gnuradio_core import gr_tag_t
+
+class PythonTag(object):
+ " Python container for tags "
+ def __init__(self):
+ self.offset = None
+ self.key = None
+ self.value = None
+ self.srcid = None
+
+def tag_to_python(tag):
+ """ Convert a stream tag to a Python-readable object """
+ newtag = PythonTag()
+ newtag.offset = tag.offset
+ newtag.key = pmt.to_python(tag.key)
+ newtag.value = pmt.to_python(tag.value)
+ newtag.srcid = pmt.to_python(tag.srcid)
+ return newtag
+
+def tag_to_pmt(tag):
+ """ Convert a Python-readable object to a stream tag """
+ newtag = gr_tag_t()
+ newtag.offset = tag.offset
+ newtag.key = pmt.to_python(tag.key)
+ newtag.value = pmt.from_python(tag.value)
+ newtag.srcid = pmt.from_python(tag.srcid)
+ return newtag
+
+