gr_complex_to_interleaved_short.cc \
gr_complex_to_xxx.cc \
gr_conjugate_cc.cc \
+ gr_copy.cc \
gr_constellation_decoder_cb.cc \
gr_correlate_access_code_bb.cc \
gr_costas_loop_cc.cc \
gr_complex_to_xxx.h \
gr_conjugate_cc.h \
gr_constellation_decoder_cb.h \
+ gr_copy.h \
gr_correlate_access_code_bb.h \
gr_costas_loop_cc.h \
gr_count_bits.h \
gr_complex_to_xxx.i \
gr_conjugate_cc.i \
gr_constellation_decoder_cb.i \
+ gr_copy.i \
gr_correlate_access_code_bb.i \
gr_costas_loop_cc.i \
gr_cpfsk_bc.i \
/* -*- c++ -*- */
/*
- * Copyright 2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+ * Copyright 2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
#include <gr_stretch_ff.h>
#include <gr_wavelet_ff.h>
#include <gr_wvps_ff.h>
-
+#include <gr_copy.h>
%}
%include "gr_nop.i"
%include "gr_stretch_ff.i"
%include "gr_wavelet_ff.i"
%include "gr_wvps_ff.i"
+%include "gr_copy.i"
--- /dev/null
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_copy.h>
+#include <gr_io_signature.h>
+#include <string.h>
+
+gr_copy_sptr
+gr_make_copy(size_t itemsize)
+{
+ return gnuradio::get_initial_sptr(new gr_copy(itemsize));
+}
+
+gr_copy::gr_copy(size_t itemsize)
+ : gr_block ("copy",
+ gr_make_io_signature (1, 1, itemsize),
+ gr_make_io_signature (1, 1, itemsize)),
+ d_itemsize(itemsize),
+ d_enabled(true)
+{
+}
+
+bool
+gr_copy::check_topology(int ninputs, int noutputs)
+{
+ return ninputs == noutputs;
+}
+
+int
+gr_copy::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const uint8_t *in = (const uint8_t *) input_items[0];
+ uint8_t *out = (uint8_t *) output_items[0];
+
+ int n = std::min<int>(ninput_items[0], noutput_items);
+ int j = 0;
+
+ if (d_enabled) {
+ memcpy(out, in, n*d_itemsize);
+ j = n;
+ }
+
+ consume_each(n);
+ return j;
+}
--- /dev/null
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009 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.
+ */
+
+#ifndef INCLUDED_GR_COPY_H
+#define INCLUDED_GR_COPY_H
+
+#include <gr_block.h>
+
+class gr_copy;
+typedef boost::shared_ptr<gr_copy> gr_copy_sptr;
+
+gr_copy_sptr gr_make_copy(size_t itemsize);
+
+/*!
+ * \brief output[i] = input[i]
+ * \ingroup misc_blk
+ *
+ * When enabled (default), this block copies its input to its output.
+ * When disabled, this block drops its input on the floor.
+ *
+ */
+class gr_copy : public gr_block
+{
+ size_t d_itemsize;
+ bool d_enabled;
+
+ friend gr_copy_sptr gr_make_copy(size_t itemsize);
+ gr_copy(size_t itemsize);
+
+ public:
+
+ bool check_topology(int ninputs, int noutputs);
+
+ void set_enabled(bool enable) { d_enabled = enable; }
+ bool enabled() const { return d_enabled;}
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif
--- /dev/null
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009 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.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,copy)
+
+gr_copy_sptr gr_make_copy(size_t itemsize);
+
+class gr_copy : public gr_block
+{
+ private:
+ gr_copy(size_t itemsize);
+
+public:
+
+ void set_enabled(bool enabled);
+ bool enabled();
+};
qa_cma_equalizer.py \
qa_complex_to_xxx.py \
qa_constellation_decoder_cb.py \
+ qa_copy.py \
qa_correlate_access_code.py \
qa_delay.py \
qa_diff_encoder.py \
--- /dev/null
+#!/usr/bin/env python
+#
+# Copyright 2009 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
+
+class test_copy(gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_copy (self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ expected_result = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ src = gr.vector_source_b(src_data)
+ op = gr.copy(gr.sizeof_char)
+ dst = gr.vector_sink_b()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ dst_data = dst.data()
+ self.assertEqual(expected_result, dst_data)
+
+ def test_copy_drop (self):
+ src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ expected_result = ()
+ src = gr.vector_source_b(src_data)
+ op = gr.copy(gr.sizeof_char)
+ op.set_enabled(False)
+ dst = gr.vector_sink_b()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ dst_data = dst.data()
+ self.assertEqual(expected_result, dst_data)
+
+
+if __name__ == '__main__':
+ gr_unittest.main ()
# Boston, MA 02110-1301, USA.
#
+##################################################
+# conditional disconnections of wx flow graph
+##################################################
+import wx
+from gnuradio import gr
+
+class wxgui_hb(object):
+ """
+ The wxgui hier block helper/wrapper class:
+ A hier block should inherit from this class to make use of the wxgui connect method.
+ To use, call wxgui_connect in place of regular connect; self.win must be defined.
+ The implementation will conditionally enable the copy block after the source (self).
+ This condition depends on weather or not the window is visible with the parent notebooks.
+ This condition will be re-checked on every ui update event.
+ """
+
+ def wxgui_connect(self, *points):
+ """
+ Use wxgui connect when the first point is the self source of the hb.
+ The win property of this object should be set to the wx window.
+ When this method tries to connect self to the next point,
+ it will conditionally make this connection based on the visibility state.
+ All other points will be connected normally.
+ """
+ try:
+ assert points[0] == self or points[0][0] == self
+ copy = gr.copy(self._hb.input_signature().sizeof_stream_item(0))
+ handler = self._handler_factory(copy.set_enabled)
+ handler(False) #initially disable the copy block
+ self._bind_to_visible_event(win=self.win, handler=handler)
+ points = list(points)
+ points.insert(1, copy) #insert the copy block into the chain
+ except (AssertionError, IndexError): pass
+ self.connect(*points) #actually connect the blocks
+
+ @staticmethod
+ def _handler_factory(handler):
+ """
+ Create a function that will cache the visibility flag,
+ and only call the handler when that flag changes.
+ @param handler the function to call on a change
+ @return a function of 1 argument
+ """
+ cache = [None]
+ def callback(visible):
+ if cache[0] == visible: return
+ cache[0] = visible
+ #print visible, handler
+ handler(visible)
+ return callback
+
+ @staticmethod
+ def _bind_to_visible_event(win, handler):
+ """
+ Bind a handler to a window when its visibility changes.
+ Specifically, call the handler when the window visibility changes.
+ This condition is checked on every update ui event.
+ @param win the wx window
+ @param handler a function of 1 param
+ """
+ #is the window visible in the hierarchy
+ def is_wx_window_visible(my_win):
+ while True:
+ parent = my_win.GetParent()
+ if not parent: return True #reached the top of the hierarchy
+ #if we are hidden, then finish, otherwise keep traversing up
+ if isinstance(parent, wx.Notebook) and parent.GetCurrentPage() != my_win: return False
+ my_win = parent
+ #call the handler, the arg is shown or not
+ def handler_factory(my_win, my_handler):
+ return lambda *args: my_handler(is_wx_window_visible(my_win))
+ handler = handler_factory(win, handler)
+ #bind the handler to all the parent notebooks
+ win.Bind(wx.EVT_UPDATE_UI, handler)
+
+##################################################
+# Helpful Functions
+##################################################
+
#A macro to apply an index to a key
index_key = lambda key, i: "%s_%d"%(key, i+1)
##################################################
# Constellation sink block (wrapper for old wxgui)
##################################################
-class const_sink_c(gr.hier_block2):
+class const_sink_c(gr.hier_block2, common.wxgui_hb):
"""
A constellation block with a gui window.
"""
agc = gr.feedforward_agc_cc(16, 1)
msgq = gr.msg_queue(2)
sink = gr.message_sink(gr.sizeof_gr_complex*const_size, msgq, True)
- #connect
- self.connect(self, self._costas, self._retime, agc, sd, sink)
#controller
def setter(p, k, x): p[k] = x
self.controller = pubsub()
sample_rate_key=SAMPLE_RATE_KEY,
)
common.register_access_methods(self, self.win)
+ #connect
+ self.wxgui_connect(self, self._costas, self._retime, agc, sd, sink)
##################################################
# FFT sink block (wrapper for old wxgui)
##################################################
-class _fft_sink_base(gr.hier_block2):
+class _fft_sink_base(gr.hier_block2, common.wxgui_hb):
"""
An fft block with real/complex inputs and a gui window.
"""
)
msgq = gr.msg_queue(2)
sink = gr.message_sink(gr.sizeof_float*fft_size, msgq, True)
- #connect
- self.connect(self, fft, sink)
#controller
self.controller = pubsub()
self.controller.subscribe(AVERAGE_KEY, fft.set_average)
common.register_access_methods(self, self.win)
setattr(self.win, 'set_baseband_freq', getattr(self, 'set_baseband_freq')) #BACKWARDS
setattr(self.win, 'set_peak_hold', getattr(self, 'set_peak_hold')) #BACKWARDS
+ #connect
+ self.wxgui_connect(self, fft, sink)
class fft_sink_f(_fft_sink_base):
_fft_chain = blks2.logpwrfft_f
##################################################
# histo sink block (wrapper for old wxgui)
##################################################
-class histo_sink_f(gr.hier_block2):
+class histo_sink_f(gr.hier_block2, common.wxgui_hb):
"""
A histogram block and a gui window.
"""
histo = gr.histo_sink_f(msgq)
histo.set_num_bins(num_bins)
histo.set_frame_size(frame_size)
- #connect
- self.connect(self, histo)
#controller
self.controller = pubsub()
self.controller.subscribe(NUM_BINS_KEY, histo.set_num_bins)
msg_key=MSG_KEY,
)
common.register_access_methods(self, self.win)
+ #connect
+ self.wxgui_connect(self, histo)
# ----------------------------------------------------------------
# Standalone test app
##################################################
# Number sink block (wrapper for old wxgui)
##################################################
-class _number_sink_base(gr.hier_block2):
+class _number_sink_base(gr.hier_block2, common.wxgui_hb):
"""
An decimator block with a number window display
"""
avg = gr.single_pole_iir_filter_cc(1.0)
msgq = gr.msg_queue(2)
sink = gr.message_sink(self._item_size, msgq, True)
- #connect
- self.connect(self, sd, mult, add, avg, sink)
#controller
self.controller = pubsub()
self.controller.subscribe(SAMPLE_RATE_KEY, sd.set_sample_rate)
common.register_access_methods(self, self.controller)
#backwards compadibility
self.set_show_gauge = self.win.show_gauges
+ #connect
+ self.wxgui_connect(self, sd, mult, add, avg, sink)
class number_sink_f(_number_sink_base):
_item_size = gr.sizeof_float
#bind plotter mouse events
self._plotter.Bind(wx.EVT_MOTION, lambda evt: self.enqueue(evt.GetPosition()))
self._plotter.Bind(wx.EVT_LEAVE_WINDOW, lambda evt: self.enqueue(None))
+ self._plotter.Bind(wx.EVT_RIGHT_DOWN, lambda evt: plotter.enable_point_label(not plotter.enable_point_label()))
#start the thread
threading.Thread.__init__(self)
self.start()
TICK_LABEL_PADDING = 5
TITLE_LABEL_PADDING = 7
POINT_LABEL_FONT_SIZE = 8
-POINT_LABEL_COLOR_SPEC = (1, 1, .5)
+POINT_LABEL_COLOR_SPEC = (1, 1, 0.5, 0.75)
POINT_LABEL_PADDING = 3
+POINT_LABEL_OFFSET = 10
GRID_LINE_DASH_LEN = 4
##################################################
if not label_str: return
txt = gltext.Text(label_str, font_size=POINT_LABEL_FONT_SIZE)
w, h = txt.get_size()
+ #enable transparency
+ GL.glEnable(GL.GL_BLEND)
+ GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
#draw rect + text
- GL.glColor3f(*POINT_LABEL_COLOR_SPEC)
- if x > self.width/2: x -= w+2*POINT_LABEL_PADDING
+ GL.glColor4f(*POINT_LABEL_COLOR_SPEC)
+ if x > self.width/2: x -= w+2*POINT_LABEL_PADDING + POINT_LABEL_OFFSET
+ else: x += POINT_LABEL_OFFSET
self._draw_rect(x, y-h-2*POINT_LABEL_PADDING, w+2*POINT_LABEL_PADDING, h+2*POINT_LABEL_PADDING)
txt.draw_text(wx.Point(x+POINT_LABEL_PADDING, y-h-POINT_LABEL_PADDING))
Mute the low pass filter to disable ac coupling.
"""
- def __init__(self, controller, ac_couple_key, ac_couple, sample_rate_key):
+ def __init__(self, controller, ac_couple_key, sample_rate_key):
gr.hier_block2.__init__(
self,
"ac_couple",
controller.subscribe(ac_couple_key, lambda x: mute.set_mute(not x))
controller.subscribe(sample_rate_key, lambda x: lpf.set_taps(0.05))
#initialize
- controller[ac_couple_key] = ac_couple
+ controller[ac_couple_key] = controller[ac_couple_key]
controller[sample_rate_key] = controller[sample_rate_key]
##################################################
# Scope sink block (wrapper for old wxgui)
##################################################
-class _scope_sink_base(gr.hier_block2):
+class _scope_sink_base(gr.hier_block2, common.wxgui_hb):
"""
A scope block with a gui window.
"""
self.controller.publish(TRIGGER_SLOPE_KEY, scope.get_trigger_slope)
self.controller.subscribe(TRIGGER_CHANNEL_KEY, scope.set_trigger_channel)
self.controller.publish(TRIGGER_CHANNEL_KEY, scope.get_trigger_channel)
- #connect
- if self._real:
- for i in range(num_inputs):
- self.connect(
- (self, i),
- ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, i), ac_couple, SAMPLE_RATE_KEY),
- (scope, i),
- )
- else:
- for i in range(num_inputs):
- c2f = gr.complex_to_float()
- self.connect((self, i), c2f)
- for j in range(2):
- self.connect(
- (c2f, j),
- ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, 2*i+j), ac_couple, SAMPLE_RATE_KEY),
- (scope, 2*i+j),
- )
- num_inputs *= 2
+ actual_num_inputs = self._real and num_inputs or num_inputs*2
+ #init ac couple
+ for i in range(actual_num_inputs):
+ self.controller[common.index_key(AC_COUPLE_KEY, i)] = ac_couple
#start input watcher
common.input_watcher(msgq, self.controller, MSG_KEY)
#create window
size=size,
title=title,
frame_rate=frame_rate,
- num_inputs=num_inputs,
+ num_inputs=actual_num_inputs,
sample_rate_key=SAMPLE_RATE_KEY,
t_scale=t_scale,
v_scale=v_scale,
msg_key=MSG_KEY,
)
common.register_access_methods(self, self.win)
+ #connect
+ if self._real:
+ for i in range(num_inputs):
+ self.wxgui_connect(
+ (self, i),
+ ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, i), SAMPLE_RATE_KEY),
+ (scope, i),
+ )
+ else:
+ for i in range(num_inputs):
+ c2f = gr.complex_to_float()
+ self.wxgui_connect((self, i), c2f)
+ for j in range(2):
+ self.connect(
+ (c2f, j),
+ ac_couple_block(self.controller, common.index_key(AC_COUPLE_KEY, 2*i+j), SAMPLE_RATE_KEY),
+ (scope, 2*i+j),
+ )
class scope_sink_f(_scope_sink_base):
_item_size = gr.sizeof_float
##################################################
# Waterfall sink block (wrapper for old wxgui)
##################################################
-class _waterfall_sink_base(gr.hier_block2):
+class _waterfall_sink_base(gr.hier_block2, common.wxgui_hb):
"""
An fft block with real/complex inputs and a gui window.
"""
)
msgq = gr.msg_queue(2)
sink = gr.message_sink(gr.sizeof_float*fft_size, msgq, True)
- #connect
- self.connect(self, fft, sink)
#controller
self.controller = pubsub()
self.controller.subscribe(AVERAGE_KEY, fft.set_average)
)
common.register_access_methods(self, self.win)
setattr(self.win, 'set_baseband_freq', getattr(self, 'set_baseband_freq')) #BACKWARDS
+ #connect
+ self.wxgui_connect(self, fft, sink)
class waterfall_sink_f(_waterfall_sink_base):
_fft_chain = blks2.logpwrfft_f
gr_complex_to_real.xml \
gr_conjugate_cc.xml \
gr_constellation_decoder_cb.xml \
+ gr_copy.xml \
gr_correlate_access_code_bb.xml \
gr_costas_loop_cc.xml \
gr_cpfsk_bc.xml \
<block>gr_skiphead</block>
<block>gr_kludge_copy</block>
+ <block>gr_copy</block>
<block>gr_nop</block>
<block>xmlrpc_server</block>
--- /dev/null
+<?xml version="1.0"?>
+<!--
+###################################################
+##Copy
+###################################################
+ -->
+<block>
+ <name>Copy</name>
+ <key>gr_copy</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.copy($type.size*$vlen)
+self.$(id).set_enabled($enabled)</make>
+ <callback>set_enabled($enabled)</callback>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Enabled</name>
+ <key>enabled</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
+ <param>
+ <name>Vec Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <check>$vlen > 0</check>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
###################################################
-->
<block>
- <name>Copy</name>
+ <name>Kludge Copy</name>
<key>gr_kludge_copy</key>
<import>from gnuradio import gr</import>
<make>gr.kludge_copy($type.size*$vlen)</make>
<opt>size:gr.sizeof_char</opt>
</option>
</param>
+ <param>
+ <name>Num Ports</name>
+ <key>num_ports</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
<param>
<name>Vec Length</name>
<key>vlen</key>
<value>1</value>
<type>int</type>
</param>
+ <check>$num_ports > 0</check>
<check>$vlen > 0</check>
<sink>
<name>in</name>
<type>$type</type>
<vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
</sink>
<source>
<name>out</name>
<type>$type</type>
<vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
</source>
</block>
<opt>size:gr.sizeof_char</opt>
</option>
</param>
+ <param>
+ <name>Num Ports</name>
+ <key>num_ports</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
<param>
<name>Vec Length</name>
<key>vlen</key>
<value>1</value>
<type>int</type>
</param>
+ <check>$num_ports > 0</check>
<check>$vlen > 0</check>
<sink>
<name>in</name>
<type>$type</type>
<vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
</sink>
<source>
<name>out</name>
<type>$type</type>
<vlen>$vlen</vlen>
+ <nports>$num_ports</nports>
</source>
</block>