Skip to content

Commit

Permalink
Merge 1296284 into 3c8a936
Browse files Browse the repository at this point in the history
  • Loading branch information
msoeken committed Apr 26, 2020
2 parents 3c8a936 + 1296284 commit e5e9374
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ v0.2 (not yet released)
- Constant modular multiplication (`modular_constant_multiplier`) `#227 <https://github.com/lsils/mockturtle/pull/227>`_
- Out-of-place modular addition, subtraction, and multiplication (`modular_adder`, `modular_subtractor`, `modular_multiplication`) `#234 <https://github.com/lsils/mockturtle/pull/234>`_
- Create self-dualization of a logic network (`self_dualize_aig`) `#331 <https://github.com/lsils/mockturtle/pull/331>`_
- Binary decoder (`binary_decoder`) `#342 <https://github.com/lsils/mockturtle/pull/342>`_
- 2^k MUX (`binary_mux` and `binary_mux_klein_paterson`) `#342 <https://github.com/lsils/mockturtle/pull/342>`_
* Properties:
- Costs based on multiplicative complexity (`multiplicative_complexity` and `multiplicative_complexity_depth`) `#170 <https://github.com/lsils/mockturtle/pull/170>`_

Expand Down
3 changes: 3 additions & 0 deletions docs/generators/control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ generate control logic networks.
.. doxygenfunction:: mockturtle::constant_word
.. doxygenfunction:: mockturtle::zero_extend
.. doxygenfunction:: mockturtle::mux_inplace
.. doxygenfunction:: mockturtle::binary_decoder
.. doxygenfunction:: mockturtle::binary_mux
.. doxygenfunction:: mockturtle::binary_mux_klein_paterson
100 changes: 100 additions & 0 deletions include/mockturtle/generators/control.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,104 @@ inline std::vector<signal<Ntk>> mux( Ntk& ntk, signal<Ntk> const& cond, std::vec
return ret;
}

/*! \brief Creates k-to-2^k binary decoder
*
* Given k signals `xs`, this function creates 2^k signals of which exactly one
* input is 1, for each of the 2^k input assignments to `xs`.
*/
template<class Ntk>
std::vector<signal<Ntk>> binary_decoder( Ntk& ntk, std::vector<signal<Ntk>> const& xs )
{
if ( xs.empty() )
{
return {};
}

if ( xs.size() == 1u )
{
return {ntk.create_not( xs[0] ), xs[0]};
}

// recursion
const auto m = ( xs.size() + 1 ) / 2;

const auto d1 = binary_decoder( ntk, std::vector<signal<Ntk>>( xs.begin(), xs.begin() + m ) );
const auto d2 = binary_decoder( ntk, std::vector<signal<Ntk>>( xs.begin() + m, xs.end() ) );

std::vector<signal<Ntk>> d( 1 << xs.size() );
auto it = d.begin();

for ( auto const& s2 : d2 )
{
for ( auto const& s1 : d1 )
{
*it++ = ntk.create_and( s1, s2 );
}
}

return d;
}

/*! \brief Creates 2^k MUX
*
* Given k select signals `sel` and 2^k data signals `data`, this function
* creates a logic network that outputs `data[i]` when `i` is the encoded
* assignment of `sel`.
*
* This is an iterative construction based on MUX gates. A more efficient
* method may be provided by the Klein-Paterson variant
* `binary_mux_klein_paterson`.
*/
template<class Ntk>
signal<Ntk> binary_mux( Ntk& ntk, std::vector<signal<Ntk>> const& sel, std::vector<signal<Ntk>> data )
{
for ( auto i = 0u; i < sel.size(); ++i )
{
for ( auto j = 0u; j < ( 1u << ( sel.size() - i - 1u ) ); ++j )
{
data[j] = ntk.create_ite( sel[i], data[2 * j + 1], data[2 * j] );
}
}

return data[0u];
}

/*! \brief Creates 2^k MUX
*
* Given k select signals `sel` and 2^k data signals `data`, this function
* creates a logic network that outputs `data[i]` when `i` is the encoded
* assignment of `sel`.
*
* This Klein-Paterson variant uses fewer gates than the direct method
* `binary_mux` (see Klein, & Paterson. (1980). Asymptotically Optimal Circuit
* for a Storage Access Function. IEEE Transactions on Computers, C-29(8),
* 737–738. doi:10.1109/tc.1980.1675657 )
*/
template<class Ntk>
signal<Ntk> binary_mux_klein_paterson( Ntk& ntk, std::vector<signal<Ntk>> const& sel, std::vector<signal<Ntk>> const& data )
{
if ( sel.size() == 1u )
{
return ntk.create_ite( sel[0u], data[1u], data[0u] );
}

// recursion
const auto s = sel.size() / 2u;
const auto r = sel.size() - s;

const auto ds = binary_decoder( ntk, std::vector<signal<Ntk>>( sel.begin(), sel.begin() + s ) );
std::vector<signal<Ntk>> s_data( 1u << r );
for ( auto j = 0u; j < s_data.size(); ++j )
{
std::vector<signal<Ntk>> and_terms( 1u << s );
std::transform( ds.begin(), ds.end(),
data.begin() + ( j * ( 1u << s ) ),
and_terms.begin(),
[&]( auto const& f1, auto const& f2 ) { return ntk.create_and( f1, f2 ); } );
s_data[j] = ntk.create_nary_or( and_terms );
}

return binary_mux_klein_paterson( ntk, std::vector<signal<Ntk>>( sel.begin() + s, sel.end() ), s_data );
}

} // namespace mockturtle
67 changes: 67 additions & 0 deletions test/generators/control.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <catch.hpp>

#include <algorithm>
#include <vector>

#include <kitty/bit_operations.hpp>
#include <kitty/dynamic_truth_table.hpp>
#include <mockturtle/algorithms/simulation.hpp>
#include <mockturtle/generators/control.hpp>
#include <mockturtle/networks/xag.hpp>
#include <mockturtle/traits.hpp>

using namespace mockturtle;

TEST_CASE( "Create n-to-2^n binary decoder using XAGs", "[control]" )
{
for ( auto n = 0u; n <= 6u; ++n )
{
xag_network xag;
std::vector<xag_network::signal> xs( n );
std::generate( xs.begin(), xs.end(), [&]() { return xag.create_pi(); } );
const auto ds = binary_decoder( xag, xs );
std::for_each( ds.begin(), ds.end(), [&]( auto const& d ) { xag.create_po( d ); } );

const auto sim = simulate<kitty::dynamic_truth_table>( xag, {n} );

for ( auto i = 0u; i < sim.size(); ++i )
{
const auto& s = sim[i];

CHECK( kitty::count_ones( s ) == 1u );
CHECK( static_cast<bool>( kitty::get_bit( s, i ) ) );
}
}
}

TEST_CASE( "Create a 2^k-way MUX in XAGs", "[control]" )
{
for ( auto k = 1u; k <= 4u; ++k )
{
xag_network xag;
std::vector<xag_network::signal> sel( k ), data( 1u << k );

std::generate( sel.begin(), sel.end(), [&]() { return xag.create_pi(); } );
std::generate( data.begin(), data.end(), [&]() { return xag.create_pi(); } );

xag.create_po( binary_mux( xag, sel, data ) );

CHECK( xag.num_gates() == 3 * ( data.size() - 1u ) );
}
}

TEST_CASE( "Create a Klein-Paterson 2^k-way MUX in XAGs", "[control]" )
{
for ( auto k = 1u; k <= 4u; ++k )
{
xag_network xag;
std::vector<xag_network::signal> sel( k ), data( 1u << k );

std::generate( sel.begin(), sel.end(), [&]() { return xag.create_pi(); } );
std::generate( data.begin(), data.end(), [&]() { return xag.create_pi(); } );

xag.create_po( binary_mux_klein_paterson( xag, sel, data ) );

CHECK( xag.num_gates() <= 3 * ( data.size() - 1u ) );
}
}

0 comments on commit e5e9374

Please sign in to comment.