Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
language:langs:dflow [2020/08/03 06:27] rajit |
language:langs:dflow [2023/01/08 18:38] rajit [Split] |
||
---|---|---|---|
Line 2: | Line 2: | ||
The dataflow sublanguage provides a convenient short-hand when designing asynchronous circuits using pipelined asynchronous circuits. The dataflow language operates exclusively on channels, and treats channels as variables to specify the dataflow computation. | The dataflow sublanguage provides a convenient short-hand when designing asynchronous circuits using pipelined asynchronous circuits. The dataflow language operates exclusively on channels, and treats channels as variables to specify the dataflow computation. | ||
- | < | + | < |
chan(int) a, b, c; | chan(int) a, b, c; | ||
Line 10: | Line 10: | ||
</ | </ | ||
This corresponds to an adder, with inputs on channels '' | This corresponds to an adder, with inputs on channels '' | ||
- | < | + | < |
*[ a? | *[ a? | ||
</ | </ | ||
Line 22: | Line 22: | ||
* Initial tokens: these are specified directly in the syntax | * Initial tokens: these are specified directly in the syntax | ||
* Copy: implicit, with the same channel is used for multiple inputs | * Copy: implicit, with the same channel is used for multiple inputs | ||
+ | * Sources and sinks have short-hand syntax. | ||
===== Function ===== | ===== Function ===== | ||
Line 30: | Line 31: | ||
The //split// dataflow element receives a control token and a data token, and uses the value of the control token to route the data token to one of the output channels. If the control token=0, the first channel is used; if it is 1, then the next channel is used; etc. The syntax for this is shown below: | The //split// dataflow element receives a control token and a data token, and uses the value of the control token to route the data token to one of the output channels. If the control token=0, the first channel is used; if it is 1, then the next channel is used; etc. The syntax for this is shown below: | ||
- | < | + | < |
dataflow { | dataflow { | ||
{c} I -> O0, O1 | {c} I -> O0, O1 | ||
Line 36: | Line 37: | ||
</ | </ | ||
The data input on channel '' | The data input on channel '' | ||
- | < | + | < |
dataflow { | dataflow { | ||
{c} I -> *, O | {c} I -> *, O | ||
Line 43: | Line 44: | ||
The '' | The '' | ||
+ | Splits with more than two outputs use the same syntax. The control token is assumed to take on an integer value specifying which output channel is used. | ||
+ | <code act> | ||
+ | dataflow { | ||
+ | {c} I -> O0, O1, O2, ..., On | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The bit-width of channel '' | ||
===== Controlled merge ===== | ===== Controlled merge ===== | ||
The // | The // | ||
- | < | + | < |
dataflow { | dataflow { | ||
{c} I0, I1 -> O | {c} I0, I1 -> O | ||
} | } | ||
</ | </ | ||
- | In this example, if a 0 is received on '' | + | In this example, if a 0 is received on '' |
+ | <code act> | ||
+ | dataflow { | ||
+ | {c} I0, I1, ..., Ik -> O | ||
+ | } | ||
+ | </ | ||
===== Implicit copy and explicit buffers ===== | ===== Implicit copy and explicit buffers ===== | ||
Copies are implicit, and are automatically introduced when the same channel name is used multiple times on the left hand side. In the example below, an input token is received on '' | Copies are implicit, and are automatically introduced when the same channel name is used multiple times on the left hand side. In the example below, an input token is received on '' | ||
- | < | + | < |
dataflow { | dataflow { | ||
a + b -> sum; | a + b -> sum; | ||
Line 65: | Line 79: | ||
In pipelined circuits, it is important to be able to introduce slack to optimize performance. The syntax for this is the following: | In pipelined circuits, it is important to be able to introduce slack to optimize performance. The syntax for this is the following: | ||
- | < | + | < |
dataflow { | dataflow { | ||
a + b -> [4] sum | a + b -> [4] sum | ||
Line 75: | Line 89: | ||
Finally, we need to be able to introduce initial tokens with pre-specified initial values. The bracket notation is overloaded for this purpose. | Finally, we need to be able to introduce initial tokens with pre-specified initial values. The bracket notation is overloaded for this purpose. | ||
- | < | + | < |
dataflow { | dataflow { | ||
a + b -> [4,2] sum | a + b -> [4,2] sum | ||
Line 87: | Line 101: | ||
There are two other primitives that are also supported, because they can be useful in certain circumstances. They are both variations of the controlled merge. The first is the // | There are two other primitives that are also supported, because they can be useful in certain circumstances. They are both variations of the controlled merge. The first is the // | ||
- | < | + | < |
dataflow { | dataflow { | ||
{*} I0, I1 -> O | {*} I0, I1 -> O | ||
Line 93: | Line 107: | ||
</ | </ | ||
The '' | The '' | ||
- | < | + | < |
dataflow { | dataflow { | ||
{|} I0, I1 -> O | {|} I0, I1 -> O | ||
Line 99: | Line 113: | ||
</ | </ | ||
Note that this introduces an arbiter. | Note that this introduces an arbiter. | ||
+ | |||
+ | Often it is helpful to know what decision was made by the arbiter. To support this, we permit an optional second channel on the right hand side of the dataflow expression as follows: | ||
+ | <code act> | ||
+ | dataflow { | ||
+ | {|} I0, I1 -> O, c | ||
+ | } | ||
+ | </ | ||
+ | For each output generated, the control channel '' | ||
+ | |||
+ | ===== Sink ===== | ||
+ | |||
+ | A dataflow sink simply receives and discards a token from a channel. Sinks are not needed in general, since the channel that corresponds to the sink can be optimized away by an implementation. However, sinks can be useful when a particular process is re-used in a context when one of its outputs is not used. The syntax is the following: | ||
+ | <code act> | ||
+ | dataflow { | ||
+ | c -> * | ||
+ | } | ||
+ | </ | ||
+ | The values received on '' | ||
====== Examples ====== | ====== Examples ====== | ||
Line 105: | Line 137: | ||
As a simple example, consider a multiply-accumulate block. The block can be specified as follows: | As a simple example, consider a multiply-accumulate block. The block can be specified as follows: | ||
- | < | + | < |
dataflow { | dataflow { | ||
a * b -> mul; | a * b -> mul; | ||
Line 116: | Line 148: | ||
Suppose we augment this with an external control token on '' | Suppose we augment this with an external control token on '' | ||
- | < | + | < |
dataflow { | dataflow { | ||
a * b -> mul; | a * b -> mul; | ||
Line 126: | Line 158: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | ====== Clusters and Ordering ====== | ||
+ | |||
+ | It can be convenient to group dataflow elements into clusters. The syntax for grouping dataflow elements is: | ||
+ | |||
+ | <code act> | ||
+ | dataflow { | ||
+ | ... | ||
+ | | ||
+ | a + b -> c; | ||
+ | a - b -> d | ||
+ | } | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||