# Synchronous Dataflow

The first part of this lecture introduced the Synchronous Dataflow model of computation. Synchronous Dataflow (SDF) has the advantage that algorithms expressed as consistent SDF graphs can always be converted into an implementation that is guaranteed to take finite-time to complete all tasks and use finite memory, provided that individual SDF actors take finite time and finite memory to execute. Thus, an SDF graph can be executed over and over again in a periodic fashion without requiring additional resources as it runs. This type of operation is well-suited to digital signal processing, controls, and communications systems because they often process an endless supply of data.

The two steps in scheduling an SDF graph are:

1. compute the repetitions vector which tells how many times to execute each actor to bring the graph back to its original state, and
2. find an order of the firings using the repetitions vector that satisfies the data dependencies in the graph.
In the earlier example, we had the dataflow graph
```A    ------>   B   ------>    C
20        10   20        10
```
When A executes, it produces 20 tokens. When B executes, it consumes 10 tokens and produces 20 tokens. When C executes, it consumes 10 tokens.

The repetitions vector is computed by the following linear-time algorithm :

1. Pick a node at random
2. Set the firing rate of that node to 1.
3. Traverse the graph and set the appropriate firing rates based on the production and consumption on each arc.
4. Normalize all fractional firings to integers by multiplying each firing rate by the least common multiple all of the denominators
The traversal keeps track of nodes and arcs that it has previously visited. The repetitions vector in the above graph is [1 2 4].

For the SDF graph below,

``` -->    A    ------>   B   ----
|     4   20        10   20    |
|                              |
|                              |
----[4]----   C    <----------
2   10
```
where [4] means a four-sample delay, a repetitions vector cannot be found. If the firing rate for A is set to 1, then the firing rate of B would be 2, and so the firing rate of C would be 4, and so the firing rate of A should be 2, which it is not. We can modify this graph as shown below to make it consistent:
``` -->    A    ------>   B   ----
|     4   20        10   20    |
|                              |
|                              |
----[4]----   C    <----------
1   10
```

## Example: Median filter

In the first homework assignment, you implemented a median filter. How would you model it as an SDF graph?
```FileRead  ------>  Median  ------>  FileWrite
1         1      1         1
```
This is an example of homogeneous SDF:
• all actors produce and consume 1 token
• every directed loop must have at least one delay
For homogeneous SDF, we can treat delays as initial tokens, and find a firing sequence that fires each actor once and obeys the firing rules. That firing can be repeated indefinitely, and is just a special case of SDF.

## Example: Filter Bank

A two-channel filter bank or wavelet can be naturally specified using the SDF model. Here, "down by 2" means downsample by 2, and "up by 2" means upsample by 2.
```        --------     -----------     ---------     --------
-->| filter |-->| down by 2 |-->| up by 2 |-->| filter |--
|    --------     -----------     ---------     --------   |  1
|   1        1   2           1   1         2   1        1  |   -----
|                                                           ->|     |
---|                                                             |  +  |-->
|                                                           ->|     |
|                                                          |   -----
|    --------     -----------     ---------     --------   |  1     1
-->| filter |-->| down by 2 |-->| up by 2 |-->| filter |--
--------     -----------     ---------     --------
1        1   2          1   1         2   1        1
```

## Example: Commutators and Distributors

Commutators and distributors are used in communication systems to interleave and deinterleave data and in signal processing in polyphase forms of filters. Commutators and distributors have periodic behavior and the flow of data through them is static. A distributor takes n tokens on one input and distributes one token to each output in a predictable fashion: the nth token on the input goes to the nth output port. A commutator takes one input token from each of n inputs and places them on the single output port in a predictable fashion: the token on the first input port is output first, the token on second output port is output next, and so forth. Distributors and commutators have periodic behavior and the flow of data through them is predictable. They are modeled well using the SDF model. Here is a polyphase form with two phases:
```                          -----------
| first     |
-->| polyphase |----
|   | filter    |    |
1  |    -----------     |   1
-------------   |   1           1    |    ------------
|             |--                      -->|            |
--->| Distributor |                           | Commutator |--->
|             |--                      -->|            |
-------------   |    -----------     |    ------------
2             1  |   | second    |    |   1            2
-->| polyphase |----
| filter    |
-----------
1           1
```

## Example: Fast Fourier Transform as a coarse grain computation

```FileRead  ------>   FFT   ------>  FileWrite
1         16   16         1
```
The Fast Fourier Transform takes N tokens as input and produces N tokens as output. Assuming that the tokens are scalars, the Fast Fourier Transform implements the equation
```        N-1             2 Pi k n
---         - j --------
\                   N
X[k] =   |   x[n]  e                 for  k = 0, 1, ..., N - 1
/
---
n=0
```
In the above diagram, even though the system does not change sampling rates, the load balancing produces a repetitions vector [16 1 16] that seems as if the sampling rates are being changed.

### Example: Fast Fourier Transform as a fine grain computation

The previous example contained a 16-point Fast Fourier Transform, but the details of the internal computation were hidden. The basic computation of the Fast Fourier Transform is a two-input, two-output butterfly:
```---------------> Fork -------------> Add ---->
|                  ^
-------\ /--------
X
-------/ \--------
|                  v
-----> Scale --> Fork --- Negate --> Add ---->
```

## References

1. Shuvra S. Bhattacharyya, Praveen K. Murthy, and Edward A. Lee, Software Synthesis from Dataflow Graphs, Kluwer Academic Press, Norwell, MA, ISBN 0-7923-9722-3, 1996.
2. S. S. Bhattacharyya, P. K. Murthy, and E. A. Lee, ``APGAN and RPMC: Complimentary Heuristics for Translating DSP Block Diagrams into Efficient Software Implementations'', Design Automation for Embedded Systems Journal, to appear.

Updated 02/08/00.