Feedback loops and buffer resources Mon, Sep 1 2014 PM
Feedback loops are now confirmed working in the Pothos framework, after a few snags and fixes. They work with both circular buffers and discontinuous buffer pools. I knew it should have techinically worked, but you definitly have to give these things a real world test at some point...
Whats a feedback loop?
A feedback loop is formed in a topology when a block's input has a direct or indirect relationship with one of its outputs. In the example above, the adder's input port 0 is fed directly from one of its output ports. You have probably seen slightly more complicated examples in a DSP textbook, but this is just a prof-of-concept to prove that the framework's plumbing is working correctly.
Getting the loop started
Take a second look at that topology above. It shouldnt work. The adder will not produce any output until both inputs are fed. How can this adder produce any output when it has no input on port 1 to produce any output? The answer: preload.
The adder's inputs can be preloaded with elements using the preload parameter. In this example, input 0 is not preloaded, however, input 1 is preloaded with 1 element. This means that adder will process one input per work() cycle, and on the next work cycle, input port 1 will have the element that was produced on the previous cycle.
Some implementation challenges
In my head, this should have simply just worked. The buffer resources from an output port should be able to go everywhere and anywhere. And thanks to atomic reference couting, resources will return to their source pool when all consumers of said buffer resource are "finished". However, we were running out of resources!
You see, in this feedback example, the adder only produced one element at a time. When this happened, for each production, an entire buffer slab was removed from the output pool and sent downstream. So, a mostly empty slab was removed from a finite pool of buffers. Eventually, a downstream consumer would have only a few elements spread across all of the producer's buffer resources. However, a block like the waveform viewer requires many elements to accumulate at its input port before it can create the diplay and consume all the available inputs. So the plotter deadlocks waiting for more input, while the adder deadlocks waiting for its buffer resources to return.
The solution
I changed the buffer manager to re-use the same buffer slab from the pool when ever the slab is under-consumed. This should make sense, why should the output port discard all if its resources for only a few elements? Also, when the input port for the plotter see the same buffer slabs with continous addresses, it combines them into one larger slab, effectively providing the same advantage as a circular buffer (when within the bounds of the memory slab).