|
@@ -0,0 +1,101 @@
|
|
|
+-module(ebb_flow).
|
|
|
+
|
|
|
+%%% Convenience operations
|
|
|
+-export([id/0, id/1, nop/0, select/2]).
|
|
|
+
|
|
|
+%%% Parallelism
|
|
|
+-export([fanout/1, fanout/2]).
|
|
|
+
|
|
|
+%%% Sequencing
|
|
|
+-export([seq/1]).
|
|
|
+
|
|
|
+%%% Choice
|
|
|
+-export([cases/1, case_of/2,
|
|
|
+ iff/2, if_else/3,
|
|
|
+ fanin/1, fanin/2]).
|
|
|
+
|
|
|
+%%%-----------------------------------------------------------------------------
|
|
|
+%%% Convenience operations
|
|
|
+%%%-----------------------------------------------------------------------------
|
|
|
+
|
|
|
+id() ->
|
|
|
+ ebb_prim:route(1, [1]).
|
|
|
+
|
|
|
+id(N) ->
|
|
|
+ ebb_prim:route(N, lists:seq(1,N)).
|
|
|
+
|
|
|
+nop() ->
|
|
|
+ ebb_prim:value('nop').
|
|
|
+
|
|
|
+select(I, N) ->
|
|
|
+ ebb_prim:route(N, [I]).
|
|
|
+
|
|
|
+%%%-----------------------------------------------------------------------------
|
|
|
+%%% Parallelism
|
|
|
+%%%-----------------------------------------------------------------------------
|
|
|
+
|
|
|
+fanout(Copies) ->
|
|
|
+ fanout(1, Copies).
|
|
|
+
|
|
|
+fanout(In, Copies) ->
|
|
|
+ Out = Copies*In,
|
|
|
+ ebb_prim:route(In, [ (I rem In) + 1 || I <- lists:seq(0, Out-1) ]).
|
|
|
+
|
|
|
+%%%-----------------------------------------------------------------------------
|
|
|
+%%% Sequencing
|
|
|
+%%%-----------------------------------------------------------------------------
|
|
|
+
|
|
|
+seq(Ops = [Op1|Rest]) ->
|
|
|
+ {In, _} = ebb_prim:flatten_arity(Ops),
|
|
|
+ {Seq, _, _} =
|
|
|
+ lists:foldl(fun(Op, {Seq,Produced,Remaining}) ->
|
|
|
+ Sync = ebb_prim:sync(Produced+Remaining),
|
|
|
+ {ebb_prim:pipe(
|
|
|
+ [Seq, Sync,
|
|
|
+ build_seq_step(Op, Produced, Remaining)]),
|
|
|
+ Produced+ebb_prim:out_arity(Op),
|
|
|
+ Remaining-ebb_prim:in_arity(Op)}
|
|
|
+ end,
|
|
|
+ {build_seq_step(Op1, 0, In),
|
|
|
+ ebb_prim:out_arity(Op1),
|
|
|
+ In-ebb_prim:in_arity(Op1)},
|
|
|
+ Rest),
|
|
|
+ Seq.
|
|
|
+
|
|
|
+build_seq_step(Op, Produced, Remaining) ->
|
|
|
+ case {Produced, Remaining-ebb_prim:in_arity(Op)} of
|
|
|
+ {0, 0} -> Op;
|
|
|
+ {_, 0} -> ebb_prim:par([id(Produced), Op]);
|
|
|
+ {0, Remaining2} -> ebb_prim:par([Op, id(Remaining2)]);
|
|
|
+ {_, Remaining2} -> ebb_prim:par([id(Produced), Op, id(Remaining2)])
|
|
|
+ end.
|
|
|
+
|
|
|
+%%%-----------------------------------------------------------------------------
|
|
|
+%%% Choice
|
|
|
+%%%-----------------------------------------------------------------------------
|
|
|
+
|
|
|
+cases(Branches) ->
|
|
|
+ ebb_prim:switch(Branches).
|
|
|
+
|
|
|
+case_of(Disc, Branches) ->
|
|
|
+ Cases = cases(Branches),
|
|
|
+ case ebb_prim:in_arity(Cases)-1 of
|
|
|
+ 0 -> ebb_prim:pipe([Disc, Cases]);
|
|
|
+ In -> ebb_prim:pipe(
|
|
|
+ [ebb_prim:par([Disc, id(In)]),
|
|
|
+ Cases])
|
|
|
+ end.
|
|
|
+
|
|
|
+iff(Then, Else) ->
|
|
|
+ cases([{true, Then}, {false, Else}]).
|
|
|
+
|
|
|
+if_else(Test, Then, Else) ->
|
|
|
+ case_of(Test, [{true, Then}, {false, Else}]).
|
|
|
+
|
|
|
+fanin(Copies) ->
|
|
|
+ cases([ {I , select(I, Copies)} || I <- lists:seq(1, Copies) ]).
|
|
|
+
|
|
|
+fanin(Copies, Out) ->
|
|
|
+ In = Copies*Out,
|
|
|
+ cases([ {I, ebb_prim:route(In, [ (I-1)*Out + J || J <- lists:seq(1, Out)])}
|
|
|
+ || I <- lists:seq(1, Copies) ]).
|