71 lines
2.0 KiB
Erlang
71 lines
2.0 KiB
Erlang
-module( four_bit_adder ).
|
|
|
|
-export( [add_bits/3, create/1, task/0] ).
|
|
|
|
add_bits( Adder, A_bits, B_bits ) ->
|
|
Adder ! {erlang:self(), lists:reverse(A_bits), lists:reverse(B_bits)},
|
|
receive
|
|
{Adder, Sum, Carry} -> {Sum, Carry}
|
|
end.
|
|
|
|
create( How_many_bits ) ->
|
|
Full_adders = connect_full_adders( [full_adder_create() || _X <- lists:seq(1, How_many_bits)] ),
|
|
erlang:spawn_link( fun() -> bit_adder_loop( Full_adders ) end ).
|
|
|
|
task() ->
|
|
Adder = create( 4 ),
|
|
add_bits( Adder, [0,0,1,0], [0,0,1,1] ).
|
|
|
|
|
|
|
|
bit_adder_loop( Full_adders ) ->
|
|
receive
|
|
{Pid, As, Bs} ->
|
|
Sum = [full_adder_sum(Adder, A, B) || {Adder, A, B} <- lists:zip3(Full_adders, As, Bs)],
|
|
Carry = receive
|
|
{carry, C} -> C
|
|
end,
|
|
Pid ! {erlang:self(), lists:reverse(Sum), Carry},
|
|
bit_adder_loop( Full_adders )
|
|
end.
|
|
|
|
connect_full_adders( [Full_adder | T]=Full_adders ) ->
|
|
lists:foldl( fun connect_full_adders/2, Full_adder, T ),
|
|
Full_adders.
|
|
|
|
connect_full_adders( Full_adder, Previous_full_adder ) ->
|
|
Previous_full_adder ! {carry_to, Full_adder},
|
|
Full_adder.
|
|
|
|
half_adder( A, B ) -> {z_xor(A, B), A band B}.
|
|
|
|
full_adder( A, B, Carry ) ->
|
|
{Sum1, Carry1} = half_adder( A, Carry),
|
|
{Sum, Carry2} = half_adder( B, Sum1),
|
|
{Sum, Carry1 bor Carry2}.
|
|
|
|
full_adder_create( ) -> erlang:spawn( fun() -> full_adder_loop({0, no_carry_pid}) end ).
|
|
|
|
full_adder_loop( {Carry, Carry_to} ) ->
|
|
receive
|
|
{carry, New_carry} -> full_adder_loop( {New_carry, Carry_to} );
|
|
{carry_to, Pid} -> full_adder_loop( {Carry, Pid} );
|
|
{add, Pid, A, B} ->
|
|
{Sum, New_carry} = full_adder( A, B, Carry ),
|
|
Pid ! {sum, erlang:self(), Sum},
|
|
full_adder_loop_carry_pid( Carry_to, Pid ) ! {carry, New_carry},
|
|
full_adder_loop( {New_carry, Carry_to} )
|
|
end.
|
|
|
|
full_adder_loop_carry_pid( no_carry_pid, Pid ) -> Pid;
|
|
full_adder_loop_carry_pid( Pid, _Pid ) -> Pid.
|
|
|
|
full_adder_sum( Pid, A, B ) ->
|
|
Pid ! {add, erlang:self(), A, B},
|
|
receive
|
|
{sum, Pid, S} -> S
|
|
end.
|
|
|
|
%% xor exists, this is another implementation.
|
|
z_xor( A, B ) -> (A band (2+bnot B)) bor ((2+bnot A) band B).
|