mirror of https://github.com/YosysHQ/abc.git
First version of ACD
This commit is contained in:
parent
6ca7eab466
commit
1632dc0d4e
5
Makefile
5
Makefile
|
|
@ -17,6 +17,7 @@ OS := $(shell uname -s)
|
|||
|
||||
MODULES := \
|
||||
$(wildcard src/ext*) \
|
||||
src/acd \
|
||||
src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \
|
||||
src/base/ver src/base/wlc src/base/wln src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \
|
||||
src/map/mapper src/map/mio src/map/super src/map/if \
|
||||
|
|
@ -56,7 +57,7 @@ ARCHFLAGS := $(ARCHFLAGS)
|
|||
|
||||
OPTFLAGS ?= -g -O
|
||||
|
||||
CFLAGS += -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS)
|
||||
CFLAGS += -std=c17 -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS)
|
||||
ifneq ($(findstring arm,$(shell uname -m)),)
|
||||
CFLAGS += -DABC_MEMALIGN=4
|
||||
endif
|
||||
|
|
@ -151,7 +152,7 @@ ifdef ABC_USE_LIBSTDCXX
|
|||
endif
|
||||
|
||||
$(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS))
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
CXXFLAGS += $(CFLAGS) -std=c++17
|
||||
|
||||
SRC :=
|
||||
GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,69 @@
|
|||
// #include "base/main/main.h"
|
||||
#include "ac_wrapper.h"
|
||||
#include "ac_decomposition.hpp"
|
||||
|
||||
// ABC_NAMESPACE_IMPL_START
|
||||
|
||||
int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost )
|
||||
{
|
||||
using namespace mockturtle;
|
||||
|
||||
int num_blocks = ( nVars <= 6 ) ? 1 : ( 1 << ( nVars - 6 ) );
|
||||
|
||||
/* translate truth table into static table */
|
||||
kitty::dynamic_truth_table tt( nVars );
|
||||
for ( int i = 0; i < num_blocks; ++i )
|
||||
tt._bits[i] = pTruth[i];
|
||||
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ac_decomposition_stats st;
|
||||
|
||||
ac_decomposition_impl acd( tt, nVars, ps, &st );
|
||||
acd.run( *pdelay );
|
||||
int val = acd.compute_decomposition();
|
||||
|
||||
if ( val < 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
*cost = st.num_luts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition )
|
||||
{
|
||||
using namespace mockturtle;
|
||||
|
||||
int num_blocks = ( nVars <= 6 ) ? 1 : ( 1 << ( nVars - 6 ) );
|
||||
|
||||
/* translate truth table into static table */
|
||||
kitty::dynamic_truth_table tt( nVars );
|
||||
for ( int i = 0; i < num_blocks; ++i )
|
||||
tt._bits[i] = pTruth[i];
|
||||
|
||||
ac_decomposition_params ps;
|
||||
ps.lut_size = lutSize;
|
||||
ac_decomposition_stats st;
|
||||
|
||||
ac_decomposition_impl acd( tt, nVars, ps, &st );
|
||||
acd.run( *pdelay );
|
||||
int val = acd.compute_decomposition();
|
||||
|
||||
if ( val < 0 )
|
||||
{
|
||||
*pdelay = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pdelay = acd.get_profile();
|
||||
|
||||
acd.get_decomposition( decomposition );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ABC_NAMESPACE_IMPL_END
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// #pragma once
|
||||
#ifndef __ACD_WRAPPER_H_
|
||||
#define __ACD_WRAPPER_H_
|
||||
|
||||
// #include "base/main/main.h"
|
||||
#include "misc/util/abc_global.h"
|
||||
|
||||
// ABC_NAMESPACE_HEADER_START
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost );
|
||||
int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// ABC_NAMESPACE_HEADER_END
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
#ifndef _KITTY_ALGORITHM_H_
|
||||
#define _KITTY_ALGORITHM_H_
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "kitty_constants.hpp"
|
||||
#include "kitty_dynamic_tt.hpp"
|
||||
#include "kitty_static_tt.hpp"
|
||||
|
||||
namespace kitty
|
||||
{
|
||||
|
||||
/*! \brief Perform bitwise unary operation on truth table
|
||||
|
||||
\param tt Truth table
|
||||
\param op Unary operation that takes as input a word (`uint64_t`) and returns a word
|
||||
|
||||
\return new constructed truth table of same type and dimensions
|
||||
*/
|
||||
template<typename TT, typename Fn>
|
||||
auto unary_operation( const TT& tt, Fn&& op )
|
||||
{
|
||||
auto result = tt.construct();
|
||||
std::transform( tt.cbegin(), tt.cend(), result.begin(), op );
|
||||
result.mask_bits();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*! \brief Perform bitwise binary operation on two truth tables
|
||||
|
||||
The dimensions of `first` and `second` must match. This is ensured
|
||||
at compile-time for static truth tables, but at run-time for dynamic
|
||||
truth tables.
|
||||
|
||||
\param first First truth table
|
||||
\param second Second truth table
|
||||
\param op Binary operation that takes as input two words (`uint64_t`) and returns a word
|
||||
|
||||
\return new constructed truth table of same type and dimensions
|
||||
*/
|
||||
template<typename TT, typename Fn>
|
||||
auto binary_operation( const TT& first, const TT& second, Fn&& op )
|
||||
{
|
||||
assert( first.num_vars() == second.num_vars() );
|
||||
|
||||
auto result = first.construct();
|
||||
std::transform( first.cbegin(), first.cend(), second.cbegin(), result.begin(), op );
|
||||
result.mask_bits();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*! \brief Computes a predicate based on two truth tables
|
||||
|
||||
The dimensions of `first` and `second` must match. This is ensured
|
||||
at compile-time for static truth tables, but at run-time for dynamic
|
||||
truth tables.
|
||||
|
||||
\param first First truth table
|
||||
\param second Second truth table
|
||||
\param op Binary operation that takes as input two words (`uint64_t`) and returns a Boolean
|
||||
|
||||
\return true or false based on the predicate
|
||||
*/
|
||||
template<typename TT, typename Fn>
|
||||
bool binary_predicate( const TT& first, const TT& second, Fn&& op )
|
||||
{
|
||||
assert( first.num_vars() == second.num_vars() );
|
||||
|
||||
return std::equal( first.begin(), first.end(), second.begin(), op );
|
||||
}
|
||||
|
||||
/*! \brief Assign computed values to bits
|
||||
|
||||
The functor `op` computes bits which are assigned to the bits of the
|
||||
truth table.
|
||||
|
||||
\param tt Truth table
|
||||
\param op Unary operation that takes no input and returns a word (`uint64_t`)
|
||||
*/
|
||||
template<typename TT, typename Fn>
|
||||
void assign_operation( TT& tt, Fn&& op )
|
||||
{
|
||||
std::generate( tt.begin(), tt.end(), op );
|
||||
tt.mask_bits();
|
||||
}
|
||||
|
||||
/*! \brief Iterates through each block of a truth table
|
||||
|
||||
The functor `op` is called for every block of the truth table.
|
||||
|
||||
\param tt Truth table
|
||||
\param op Unary operation that takes as input a word (`uint64_t`) and returns void
|
||||
*/
|
||||
template<typename TT, typename Fn>
|
||||
void for_each_block( const TT& tt, Fn&& op )
|
||||
{
|
||||
std::for_each( tt.cbegin(), tt.cend(), op );
|
||||
}
|
||||
|
||||
/*! \brief Iterates through each block of a truth table in reverse
|
||||
order
|
||||
|
||||
The functor `op` is called for every block of the truth table in
|
||||
reverse order.
|
||||
|
||||
\param tt Truth table
|
||||
\param op Unary operation that takes as input a word (`uint64_t`) and returns void
|
||||
*/
|
||||
template<typename TT, typename Fn>
|
||||
void for_each_block_reversed( const TT& tt, Fn&& op )
|
||||
{
|
||||
std::for_each( tt.crbegin(), tt.crend(), op );
|
||||
}
|
||||
|
||||
} // namespace kitty
|
||||
|
||||
#endif // _KITTY_ALGORITHM_H_
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
#ifndef _KITTY_CONSTANTS_H_
|
||||
#define _KITTY_CONSTANTS_H_
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace kitty
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
static constexpr uint64_t projections[] = {
|
||||
UINT64_C( 0xaaaaaaaaaaaaaaaa ),
|
||||
UINT64_C( 0xcccccccccccccccc ),
|
||||
UINT64_C( 0xf0f0f0f0f0f0f0f0 ),
|
||||
UINT64_C( 0xff00ff00ff00ff00 ),
|
||||
UINT64_C( 0xffff0000ffff0000 ),
|
||||
UINT64_C( 0xffffffff00000000 ) };
|
||||
|
||||
static constexpr uint64_t projections_neg[] = {
|
||||
UINT64_C( 0x5555555555555555 ),
|
||||
UINT64_C( 0x3333333333333333 ),
|
||||
UINT64_C( 0x0f0f0f0f0f0f0f0f ),
|
||||
UINT64_C( 0x00ff00ff00ff00ff ),
|
||||
UINT64_C( 0x0000ffff0000ffff ),
|
||||
UINT64_C( 0x00000000ffffffff ) };
|
||||
|
||||
static constexpr uint64_t masks[] = {
|
||||
UINT64_C( 0x0000000000000001 ),
|
||||
UINT64_C( 0x0000000000000003 ),
|
||||
UINT64_C( 0x000000000000000f ),
|
||||
UINT64_C( 0x00000000000000ff ),
|
||||
UINT64_C( 0x000000000000ffff ),
|
||||
UINT64_C( 0x00000000ffffffff ),
|
||||
UINT64_C( 0xffffffffffffffff ) };
|
||||
|
||||
static constexpr uint64_t permutation_masks[][3] = {
|
||||
{ UINT64_C( 0x9999999999999999 ), UINT64_C( 0x2222222222222222 ), UINT64_C( 0x4444444444444444 ) },
|
||||
{ UINT64_C( 0xc3c3c3c3c3c3c3c3 ), UINT64_C( 0x0c0c0c0c0c0c0c0c ), UINT64_C( 0x3030303030303030 ) },
|
||||
{ UINT64_C( 0xf00ff00ff00ff00f ), UINT64_C( 0x00f000f000f000f0 ), UINT64_C( 0x0f000f000f000f00 ) },
|
||||
{ UINT64_C( 0xff0000ffff0000ff ), UINT64_C( 0x0000ff000000ff00 ), UINT64_C( 0x00ff000000ff0000 ) },
|
||||
{ UINT64_C( 0xffff00000000ffff ), UINT64_C( 0x00000000ffff0000 ), UINT64_C( 0x0000ffff00000000 ) } };
|
||||
|
||||
static constexpr uint64_t ppermutation_masks[][6][3] = {
|
||||
{ { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x9999999999999999 ), UINT64_C( 0x2222222222222222 ), UINT64_C( 0x4444444444444444 ) },
|
||||
{ UINT64_C( 0xa5a5a5a5a5a5a5a5 ), UINT64_C( 0x0a0a0a0a0a0a0a0a ), UINT64_C( 0x5050505050505050 ) },
|
||||
{ UINT64_C( 0xaa55aa55aa55aa55 ), UINT64_C( 0x00aa00aa00aa00aa ), UINT64_C( 0x5500550055005500 ) },
|
||||
{ UINT64_C( 0xaaaa5555aaaa5555 ), UINT64_C( 0x0000aaaa0000aaaa ), UINT64_C( 0x5555000055550000 ) },
|
||||
{ UINT64_C( 0xaaaaaaaa55555555 ), UINT64_C( 0x00000000aaaaaaaa ), UINT64_C( 0x5555555500000000 ) } },
|
||||
{ { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0xc3c3c3c3c3c3c3c3 ), UINT64_C( 0x0c0c0c0c0c0c0c0c ), UINT64_C( 0x3030303030303030 ) },
|
||||
{ UINT64_C( 0xcc33cc33cc33cc33 ), UINT64_C( 0x00cc00cc00cc00cc ), UINT64_C( 0x3300330033003300 ) },
|
||||
{ UINT64_C( 0xcccc3333cccc3333 ), UINT64_C( 0x0000cccc0000cccc ), UINT64_C( 0x3333000033330000 ) },
|
||||
{ UINT64_C( 0xcccccccc33333333 ), UINT64_C( 0x00000000cccccccc ), UINT64_C( 0x3333333300000000 ) } },
|
||||
{ { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0xf00ff00ff00ff00f ), UINT64_C( 0x00f000f000f000f0 ), UINT64_C( 0x0f000f000f000f00 ) },
|
||||
{ UINT64_C( 0xf0f00f0ff0f00f0f ), UINT64_C( 0x0000f0f00000f0f0 ), UINT64_C( 0x0f0f00000f0f0000 ) },
|
||||
{ UINT64_C( 0xf0f0f0f00f0f0f0f ), UINT64_C( 0x00000000f0f0f0f0 ), UINT64_C( 0x0f0f0f0f00000000 ) } },
|
||||
{ { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0xff0000ffff0000ff ), UINT64_C( 0x0000ff000000ff00 ), UINT64_C( 0x00ff000000ff0000 ) },
|
||||
{ UINT64_C( 0xff00ff0000ff00ff ), UINT64_C( 0x00000000ff00ff00 ), UINT64_C( 0x00ff00ff00000000 ) } },
|
||||
{ { UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ), UINT64_C( 0x0000000000000000 ) },
|
||||
{ UINT64_C( 0xffff00000000ffff ), UINT64_C( 0x00000000ffff0000 ), UINT64_C( 0x0000ffff00000000 ) } } };
|
||||
|
||||
static constexpr int32_t hex_to_int[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace kitty
|
||||
|
||||
#endif //_KITTY_CONSTANTS_H_
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
#ifndef _KITTY_CONSTRUCT_TT_H_
|
||||
#define _KITTY_CONSTRUCT_TT_H_
|
||||
#pragma once
|
||||
|
||||
#include <cctype>
|
||||
#include <chrono>
|
||||
#include <istream>
|
||||
#include <random>
|
||||
#include <stack>
|
||||
|
||||
#include "kitty_constants.hpp"
|
||||
#include "kitty_dynamic_tt.hpp"
|
||||
#include "kitty_static_tt.hpp"
|
||||
|
||||
namespace kitty
|
||||
{
|
||||
|
||||
/*! \brief Creates truth table with number of variables
|
||||
|
||||
If some truth table instance is given, one can create a truth table with the
|
||||
same type by calling the `construct()` method on it. This function helps if
|
||||
only the number of variables is known and the base type and uniforms the
|
||||
creation of static and dynamic truth tables. Note, however, that for static
|
||||
truth tables `num_vars` must be consistent to the number of variables in the
|
||||
truth table type.
|
||||
|
||||
\param num_vars Number of variables
|
||||
*/
|
||||
template<typename TT>
|
||||
inline TT create( unsigned num_vars )
|
||||
{
|
||||
(void)num_vars;
|
||||
TT tt;
|
||||
assert( tt.num_vars() == num_vars );
|
||||
return tt;
|
||||
}
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
template<>
|
||||
inline dynamic_truth_table create<dynamic_truth_table>( unsigned num_vars )
|
||||
{
|
||||
return dynamic_truth_table( num_vars );
|
||||
}
|
||||
/*! \endcond */
|
||||
|
||||
/*! \brief Constructs projections (single-variable functions)
|
||||
|
||||
\param tt Truth table
|
||||
\param var_index Index of the variable, must be smaller than the truth table's number of variables
|
||||
\param complement If true, realize inverse projection
|
||||
*/
|
||||
template<typename TT>
|
||||
void create_nth_var( TT& tt, uint8_t var_index, bool complement = false )
|
||||
{
|
||||
if ( tt.num_vars() <= 6 )
|
||||
{
|
||||
/* assign from precomputed table */
|
||||
tt._bits[0] = complement ? ~detail::projections[var_index] : detail::projections[var_index];
|
||||
|
||||
/* mask if truth table does not require all bits */
|
||||
tt.mask_bits();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( var_index < 6 )
|
||||
{
|
||||
std::fill( std::begin( tt._bits ), std::end( tt._bits ), complement ? ~detail::projections[var_index] : detail::projections[var_index] );
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto c = 1 << ( var_index - 6 );
|
||||
const auto zero = uint64_t( 0 );
|
||||
const auto one = ~zero;
|
||||
auto block = uint64_t( 0u );
|
||||
|
||||
while ( block < tt.num_blocks() )
|
||||
{
|
||||
for ( auto i = 0; i < c; ++i )
|
||||
{
|
||||
tt._bits[block++] = complement ? one : zero;
|
||||
}
|
||||
for ( auto i = 0; i < c; ++i )
|
||||
{
|
||||
tt._bits[block++] = complement ? zero : one;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace kitty
|
||||
|
||||
#endif // _KITTY_CONSTRUCT_TT_H_
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
#ifndef _KITTY_DYNAMIC_TT_H_
|
||||
#define _KITTY_DYNAMIC_TT_H_
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include "kitty_constants.hpp"
|
||||
|
||||
namespace kitty
|
||||
{
|
||||
|
||||
/*! Truth table in which number of variables is known at runtime.
|
||||
*/
|
||||
struct dynamic_truth_table
|
||||
{
|
||||
/*! Standard constructor.
|
||||
|
||||
The number of variables provided to the truth table can be
|
||||
computed at runtime. However, once the truth table is constructed
|
||||
its number of variables cannot change anymore.
|
||||
|
||||
The constructor computes the number of blocks and resizes the
|
||||
vector accordingly.
|
||||
|
||||
\param num_vars Number of variables
|
||||
*/
|
||||
explicit dynamic_truth_table( uint32_t num_vars )
|
||||
: _bits( ( num_vars <= 6 ) ? 1u : ( 1u << ( num_vars - 6 ) ) ),
|
||||
_num_vars( num_vars )
|
||||
{
|
||||
}
|
||||
|
||||
/*! Empty constructor.
|
||||
|
||||
Creates an empty truth table. It has 0 variables, but no bits, i.e., it is
|
||||
different from a truth table for the constant function. This constructor is
|
||||
only used for convenience, if algorithms require the existence of default
|
||||
constructable classes.
|
||||
*/
|
||||
dynamic_truth_table() : _num_vars( 0 ) {}
|
||||
|
||||
/*! Constructs a new dynamic truth table instance with the same number of variables. */
|
||||
inline dynamic_truth_table construct() const
|
||||
{
|
||||
return dynamic_truth_table( _num_vars );
|
||||
}
|
||||
|
||||
/*! Returns number of variables.
|
||||
*/
|
||||
inline auto num_vars() const noexcept { return _num_vars; }
|
||||
|
||||
/*! Returns number of blocks.
|
||||
*/
|
||||
inline auto num_blocks() const noexcept { return _bits.size(); }
|
||||
|
||||
/*! Returns number of bits.
|
||||
*/
|
||||
inline auto num_bits() const noexcept { return uint64_t( 1 ) << _num_vars; }
|
||||
|
||||
/*! \brief Begin iterator to bits.
|
||||
*/
|
||||
inline auto begin() noexcept { return _bits.begin(); }
|
||||
|
||||
/*! \brief End iterator to bits.
|
||||
*/
|
||||
inline auto end() noexcept { return _bits.end(); }
|
||||
|
||||
/*! \brief Begin iterator to bits.
|
||||
*/
|
||||
inline auto begin() const noexcept { return _bits.begin(); }
|
||||
|
||||
/*! \brief End iterator to bits.
|
||||
*/
|
||||
inline auto end() const noexcept { return _bits.end(); }
|
||||
|
||||
/*! \brief Reverse begin iterator to bits.
|
||||
*/
|
||||
inline auto rbegin() noexcept { return _bits.rbegin(); }
|
||||
|
||||
/*! \brief Reverse end iterator to bits.
|
||||
*/
|
||||
inline auto rend() noexcept { return _bits.rend(); }
|
||||
|
||||
/*! \brief Constant begin iterator to bits.
|
||||
*/
|
||||
inline auto cbegin() const noexcept { return _bits.cbegin(); }
|
||||
|
||||
/*! \brief Constant end iterator to bits.
|
||||
*/
|
||||
inline auto cend() const noexcept { return _bits.cend(); }
|
||||
|
||||
/*! \brief Constant reverse begin iterator to bits.
|
||||
*/
|
||||
inline auto crbegin() const noexcept { return _bits.crbegin(); }
|
||||
|
||||
/*! \brief Constant teverse end iterator to bits.
|
||||
*/
|
||||
inline auto crend() const noexcept { return _bits.crend(); }
|
||||
|
||||
/*! \brief Assign other truth table.
|
||||
|
||||
This replaces the current truth table with another truth table. The truth
|
||||
table type has to be complete. The vector of bits is resized accordingly.
|
||||
|
||||
\param other Other truth table
|
||||
*/
|
||||
template<class TT>
|
||||
dynamic_truth_table& operator=( const TT& other )
|
||||
{
|
||||
_bits.resize( other.num_blocks() );
|
||||
std::copy( other.begin(), other.end(), begin() );
|
||||
_num_vars = other.num_vars();
|
||||
|
||||
if ( _num_vars < 6 )
|
||||
{
|
||||
mask_bits();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*! Masks the number of valid truth table bits.
|
||||
|
||||
If the truth table has less than 6 variables, it may not use all
|
||||
the bits. This operation makes sure to zero out all non-valid
|
||||
bits.
|
||||
*/
|
||||
inline void mask_bits() noexcept
|
||||
{
|
||||
if ( _num_vars < 6 )
|
||||
{
|
||||
_bits[0u] &= detail::masks[_num_vars];
|
||||
}
|
||||
}
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
public: /* fields */
|
||||
std::vector<uint64_t> _bits;
|
||||
uint32_t _num_vars;
|
||||
/*! \endcond */
|
||||
};
|
||||
|
||||
} //namespace kitty
|
||||
|
||||
#endif // _KITTY_DYNAMIC_TT_H_
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
#ifndef _KITTY_OPERATIONS_TT_H_
|
||||
#define _KITTY_OPERATIONS_TT_H_
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
#include <iostream>
|
||||
|
||||
#include "kitty_algorithm.hpp"
|
||||
#include "kitty_constants.hpp"
|
||||
#include "kitty_dynamic_tt.hpp"
|
||||
#include "kitty_static_tt.hpp"
|
||||
|
||||
namespace kitty
|
||||
{
|
||||
|
||||
/*! Inverts all bits in a truth table, based on a condition */
|
||||
template<typename TT>
|
||||
inline TT unary_not_if( const TT& tt, bool cond )
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4146 )
|
||||
#endif
|
||||
const auto mask = -static_cast<uint64_t>( cond );
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
return unary_operation( tt, [mask]( auto a )
|
||||
{ return a ^ mask; } );
|
||||
}
|
||||
|
||||
/*! \brief Inverts all bits in a truth table */
|
||||
template<typename TT>
|
||||
inline TT unary_not( const TT& tt )
|
||||
{
|
||||
return unary_operation( tt, []( auto a )
|
||||
{ return ~a; } );
|
||||
}
|
||||
|
||||
/*! \brief Bitwise AND of two truth tables */
|
||||
template<typename TT>
|
||||
|
||||
inline TT binary_and( const TT& first, const TT& second )
|
||||
{
|
||||
return binary_operation( first, second, std::bit_and<>() );
|
||||
}
|
||||
|
||||
/*! \brief Bitwise OR of two truth tables */
|
||||
template<typename TT>
|
||||
inline TT binary_or( const TT& first, const TT& second )
|
||||
{
|
||||
return binary_operation( first, second, std::bit_or<>() );
|
||||
}
|
||||
|
||||
/*! \brief Swaps two variables in a truth table
|
||||
|
||||
The function swaps variable `var_index1` with `var_index2`. The
|
||||
function will change `tt` in-place. If `tt` should not be changed,
|
||||
one can use `swap` instead.
|
||||
|
||||
\param tt Truth table
|
||||
\param var_index1 First variable
|
||||
\param var_index2 Second variable
|
||||
*/
|
||||
template<typename TT>
|
||||
void swap_inplace( TT& tt, uint8_t var_index1, uint8_t var_index2 )
|
||||
{
|
||||
if ( var_index1 == var_index2 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( var_index1 > var_index2 )
|
||||
{
|
||||
std::swap( var_index1, var_index2 );
|
||||
}
|
||||
|
||||
if ( tt.num_vars() <= 6 )
|
||||
{
|
||||
const auto& pmask = detail::ppermutation_masks[var_index1][var_index2];
|
||||
const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 );
|
||||
tt._bits[0] = ( tt._bits[0] & pmask[0] ) | ( ( tt._bits[0] & pmask[1] ) << shift ) | ( ( tt._bits[0] & pmask[2] ) >> shift );
|
||||
}
|
||||
else if ( var_index2 <= 5 )
|
||||
{
|
||||
const auto& pmask = detail::ppermutation_masks[var_index1][var_index2];
|
||||
const auto shift = ( 1 << var_index2 ) - ( 1 << var_index1 );
|
||||
std::transform( std::begin( tt._bits ), std::end( tt._bits ), std::begin( tt._bits ),
|
||||
[shift, &pmask]( uint64_t word )
|
||||
{
|
||||
return ( word & pmask[0] ) | ( ( word & pmask[1] ) << shift ) | ( ( word & pmask[2] ) >> shift );
|
||||
} );
|
||||
}
|
||||
else if ( var_index1 <= 5 ) /* in this case, var_index2 > 5 */
|
||||
{
|
||||
const auto step = 1 << ( var_index2 - 6 );
|
||||
const auto shift = 1 << var_index1;
|
||||
auto it = std::begin( tt._bits );
|
||||
while ( it != std::end( tt._bits ) )
|
||||
{
|
||||
for ( auto i = decltype( step ){ 0 }; i < step; ++i )
|
||||
{
|
||||
const auto low_to_high = ( *( it + i ) & detail::projections[var_index1] ) >> shift;
|
||||
const auto high_to_low = ( *( it + i + step ) << shift ) & detail::projections[var_index1];
|
||||
*( it + i ) = ( *( it + i ) & ~detail::projections[var_index1] ) | high_to_low;
|
||||
*( it + i + step ) = ( *( it + i + step ) & detail::projections[var_index1] ) | low_to_high;
|
||||
}
|
||||
it += 2 * step;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto step1 = 1 << ( var_index1 - 6 );
|
||||
const auto step2 = 1 << ( var_index2 - 6 );
|
||||
auto it = std::begin( tt._bits );
|
||||
while ( it != std::end( tt._bits ) )
|
||||
{
|
||||
for ( auto i = 0; i < step2; i += 2 * step1 )
|
||||
{
|
||||
for ( auto j = 0; j < step1; ++j )
|
||||
{
|
||||
std::swap( *( it + i + j + step1 ), *( it + i + j + step2 ) );
|
||||
}
|
||||
}
|
||||
it += 2 * step2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Extends smaller truth table to larger one
|
||||
|
||||
The most significant variables will not be in the functional support of the
|
||||
resulting truth table, but the method is helpful to align a truth table when
|
||||
being used with another one.
|
||||
|
||||
\param tt Larger truth table to create
|
||||
\param from Smaller truth table to copy from
|
||||
*/
|
||||
template<typename TT, typename TTFrom>
|
||||
void extend_to_inplace( TT& tt, const TTFrom& from )
|
||||
{
|
||||
assert( tt.num_vars() >= from.num_vars() );
|
||||
|
||||
if ( from.num_vars() < 6 )
|
||||
{
|
||||
auto mask = *from.begin();
|
||||
|
||||
for ( auto i = from.num_vars(); i < std::min<uint8_t>( 6, tt.num_vars() ); ++i )
|
||||
{
|
||||
mask |= ( mask << ( 1 << i ) );
|
||||
}
|
||||
|
||||
std::fill( tt.begin(), tt.end(), mask );
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = tt.begin();
|
||||
while ( it != tt.end() )
|
||||
{
|
||||
it = std::copy( from.cbegin(), from.cend(), it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Extends smaller truth table to larger static one
|
||||
|
||||
This is an out-of-place version of `extend_to_inplace` that has the truth
|
||||
table as a return value. It only works for creating static truth tables. The
|
||||
template parameter `NumVars` must be equal or larger to the number of
|
||||
variables in `from`.
|
||||
|
||||
\param from Smaller truth table to copy from
|
||||
*/
|
||||
template<uint32_t NumVars, typename TTFrom>
|
||||
inline static_truth_table<NumVars> extend_to( const TTFrom& from )
|
||||
{
|
||||
static_truth_table<NumVars> tt;
|
||||
extend_to_inplace( tt, from );
|
||||
return tt;
|
||||
}
|
||||
|
||||
/*! \brief Checks whether truth table depends on given variable index
|
||||
|
||||
\param tt Truth table
|
||||
\param var_index Variable index
|
||||
*/
|
||||
template<typename TT>
|
||||
bool has_var( const TT& tt, uint8_t var_index )
|
||||
{
|
||||
assert( var_index < tt.num_vars() );
|
||||
|
||||
if ( tt.num_vars() <= 6 || var_index < 6 )
|
||||
{
|
||||
return std::any_of( std::begin( tt._bits ), std::end( tt._bits ),
|
||||
[var_index]( uint64_t word )
|
||||
{ return ( ( word >> ( uint64_t( 1 ) << var_index ) ) & detail::projections_neg[var_index] ) !=
|
||||
( word & detail::projections_neg[var_index] ); } );
|
||||
}
|
||||
|
||||
const auto step = 1 << ( var_index - 6 );
|
||||
for ( auto i = 0u; i < static_cast<uint32_t>( tt.num_blocks() ); i += 2 * step )
|
||||
{
|
||||
for ( auto j = 0; j < step; ++j )
|
||||
{
|
||||
if ( tt._bits[i + j] != tt._bits[i + j + step] )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! \brief Checks whether truth table depends on given variable index
|
||||
|
||||
\param tt Truth table
|
||||
\param care Care set
|
||||
\param var_index Variable index
|
||||
*/
|
||||
template<typename TT>
|
||||
bool has_var( const TT& tt, const TT& care, uint8_t var_index )
|
||||
{
|
||||
assert( var_index < tt.num_vars() );
|
||||
assert( tt.num_vars() == care.num_vars() );
|
||||
|
||||
if ( tt.num_vars() <= 6 || var_index < 6 )
|
||||
{
|
||||
auto it_tt = std::begin( tt._bits );
|
||||
auto it_care = std::begin( care._bits );
|
||||
while ( it_tt != std::end( tt._bits ) )
|
||||
{
|
||||
if ( ( ( ( *it_tt >> ( uint64_t( 1 ) << var_index ) ) ^ *it_tt ) & detail::projections_neg[var_index]
|
||||
& ( *it_care >> ( uint64_t( 1 ) << var_index ) ) & *it_care ) != 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
++it_tt;
|
||||
++it_care;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto step = 1 << ( var_index - 6 );
|
||||
for ( auto i = 0u; i < static_cast<uint32_t>( tt.num_blocks() ); i += 2 * step )
|
||||
{
|
||||
for ( auto j = 0; j < step; ++j )
|
||||
{
|
||||
if ( ( ( tt._bits[i + j] ^ tt._bits[i + j + step] ) & care._bits[i + j] & care._bits[i + j + step] ) != 0 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*! \brief Shrinks larger truth table to smaller one
|
||||
|
||||
The function expects that the most significant bits, which are cut off, are
|
||||
not in the functional support of the original function. Only then it is
|
||||
ensured that the resulting function is equivalent.
|
||||
|
||||
\param tt Smaller truth table to create
|
||||
\param from Larger truth table to copy from
|
||||
*/
|
||||
template<typename TT, typename TTFrom>
|
||||
void shrink_to_inplace( TT& tt, const TTFrom& from )
|
||||
{
|
||||
assert( tt.num_vars() <= from.num_vars() );
|
||||
|
||||
std::copy( from.begin(), from.begin() + tt.num_blocks(), tt.begin() );
|
||||
|
||||
if ( tt.num_vars() < 6 )
|
||||
{
|
||||
tt.mask_bits();
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Shrinks larger truth table to smaller dynamic one
|
||||
|
||||
This is an out-of-place version of `shrink_to` that has the truth table as a
|
||||
return value. It only works for creating dynamic tables. The parameter
|
||||
`num_vars` must be equal or smaller to the number of variables in `from`.
|
||||
|
||||
\param from Smaller truth table to copy from
|
||||
*/
|
||||
template<typename TTFrom>
|
||||
inline dynamic_truth_table shrink_to( const TTFrom& from, unsigned num_vars )
|
||||
{
|
||||
auto tt = create<dynamic_truth_table>( num_vars );
|
||||
shrink_to_inplace( tt, from );
|
||||
return tt;
|
||||
}
|
||||
|
||||
/*! \brief Prints truth table in hexadecimal representation
|
||||
|
||||
The most-significant bit will be the first character of the string.
|
||||
|
||||
\param tt Truth table
|
||||
\param os Output stream
|
||||
*/
|
||||
template<typename TT>
|
||||
void print_hex( const TT& tt, std::ostream& os = std::cout )
|
||||
{
|
||||
auto const chunk_size =
|
||||
std::min<uint64_t>( tt.num_vars() <= 1 ? 1 : ( tt.num_bits() >> 2 ), 16 );
|
||||
|
||||
for_each_block_reversed( tt, [&os, chunk_size]( auto word )
|
||||
{
|
||||
std::string chunk( chunk_size, '0' );
|
||||
|
||||
auto it = chunk.rbegin();
|
||||
while (word && it != chunk.rend()) {
|
||||
auto hex = word & 0xf;
|
||||
if (hex < 10) {
|
||||
*it = '0' + static_cast<char>(hex);
|
||||
} else {
|
||||
*it = 'a' + static_cast<char>(hex - 10);
|
||||
}
|
||||
++it;
|
||||
word >>= 4;
|
||||
}
|
||||
os << chunk; } );
|
||||
}
|
||||
|
||||
} //namespace kitty
|
||||
|
||||
#endif // _KITTY_OPERATIONS_TT_H_
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#ifndef _KITTY_OPERATORS_TT_H_
|
||||
#define _KITTY_OPERATORS_TT_H_
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
|
||||
#include "kitty_constants.hpp"
|
||||
#include "kitty_dynamic_tt.hpp"
|
||||
#include "kitty_static_tt.hpp"
|
||||
#include "kitty_operations.hpp"
|
||||
|
||||
namespace kitty
|
||||
{
|
||||
|
||||
/*! \brief Operator for unary_not */
|
||||
inline dynamic_truth_table operator~( const dynamic_truth_table& tt )
|
||||
{
|
||||
return unary_not( tt );
|
||||
}
|
||||
|
||||
/*! \brief Operator for unary_not */
|
||||
template<uint32_t NumVars>
|
||||
inline static_truth_table<NumVars> operator~( const static_truth_table<NumVars>& tt )
|
||||
{
|
||||
return unary_not( tt );
|
||||
}
|
||||
|
||||
/*! \brief Operator for binary_and */
|
||||
inline dynamic_truth_table operator&( const dynamic_truth_table& first, const dynamic_truth_table& second )
|
||||
{
|
||||
return binary_and( first, second );
|
||||
}
|
||||
|
||||
/*! \brief Operator for binary_and */
|
||||
template<uint32_t NumVars>
|
||||
inline static_truth_table<NumVars> operator&( const static_truth_table<NumVars>& first, const static_truth_table<NumVars>& second )
|
||||
{
|
||||
return binary_and( first, second );
|
||||
}
|
||||
|
||||
/*! \brief Operator for binary_and and assign */
|
||||
inline void operator&=( dynamic_truth_table& first, const dynamic_truth_table& second )
|
||||
{
|
||||
first = binary_and( first, second );
|
||||
}
|
||||
|
||||
/*! \brief Operator for binary_and and assign */
|
||||
template<uint32_t NumVars>
|
||||
inline void operator&=( static_truth_table<NumVars>& first, const static_truth_table<NumVars>& second )
|
||||
{
|
||||
first = binary_and( first, second );
|
||||
}
|
||||
|
||||
/*! \brief Operator for binary_or */
|
||||
inline dynamic_truth_table operator|( const dynamic_truth_table& first, const dynamic_truth_table& second )
|
||||
{
|
||||
return binary_or( first, second );
|
||||
}
|
||||
|
||||
/*! \brief Operator for binary_or */
|
||||
template<uint32_t NumVars>
|
||||
inline static_truth_table<NumVars> operator|( const static_truth_table<NumVars>& first, const static_truth_table<NumVars>& second )
|
||||
{
|
||||
return binary_or( first, second );
|
||||
}
|
||||
|
||||
/*! \brief Operator for binary_or and assign */
|
||||
inline void operator|=( dynamic_truth_table& first, const dynamic_truth_table& second )
|
||||
{
|
||||
first = binary_or( first, second );
|
||||
}
|
||||
|
||||
/*! \brief Operator for binary_or and assign */
|
||||
template<uint32_t NumVars>
|
||||
inline void operator|=( static_truth_table<NumVars>& first, const static_truth_table<NumVars>& second )
|
||||
{
|
||||
first = binary_or( first, second );
|
||||
}
|
||||
|
||||
} // namespace kitty
|
||||
|
||||
#endif // _KITTY_OPERATORS_TT_H_
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
#ifndef _KITTY_STATIC_TT_H_
|
||||
#define _KITTY_STATIC_TT_H_
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
#include "kitty_constants.hpp"
|
||||
|
||||
namespace kitty
|
||||
{
|
||||
|
||||
template<uint32_t NumVars>
|
||||
struct static_truth_table
|
||||
{
|
||||
/*! \cond PRIVATE */
|
||||
enum
|
||||
{
|
||||
NumBlocks = ( NumVars <= 6 ) ? 1u : ( 1u << ( NumVars - 6 ) )
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NumBits = uint64_t( 1 ) << NumVars
|
||||
};
|
||||
/*! \endcond */
|
||||
|
||||
/*! Standard constructor.
|
||||
|
||||
The number of variables provided to the truth table must be known
|
||||
at runtime. The number of blocks will be computed as a compile
|
||||
time constant.
|
||||
*/
|
||||
static_truth_table()
|
||||
{
|
||||
_bits.fill( 0 );
|
||||
}
|
||||
|
||||
/*! Constructs a new static truth table instance with the same number of variables. */
|
||||
inline static_truth_table<NumVars> construct() const
|
||||
{
|
||||
return static_truth_table<NumVars>();
|
||||
}
|
||||
|
||||
/*! Returns number of variables.
|
||||
*/
|
||||
inline auto num_vars() const noexcept { return NumVars; }
|
||||
|
||||
/*! Returns number of blocks.
|
||||
*/
|
||||
inline auto num_blocks() const noexcept { return NumBlocks; }
|
||||
|
||||
/*! Returns number of bits.
|
||||
*/
|
||||
inline auto num_bits() const noexcept { return NumBits; }
|
||||
|
||||
/*! \brief Begin iterator to bits.
|
||||
*/
|
||||
inline auto begin() noexcept { return _bits.begin(); }
|
||||
|
||||
/*! \brief End iterator to bits.
|
||||
*/
|
||||
inline auto end() noexcept { return _bits.end(); }
|
||||
|
||||
/*! \brief Begin iterator to bits.
|
||||
*/
|
||||
inline auto begin() const noexcept { return _bits.begin(); }
|
||||
|
||||
/*! \brief End iterator to bits.
|
||||
*/
|
||||
inline auto end() const noexcept { return _bits.end(); }
|
||||
|
||||
/*! \brief Reverse begin iterator to bits.
|
||||
*/
|
||||
inline auto rbegin() noexcept { return _bits.rbegin(); }
|
||||
|
||||
/*! \brief Reverse end iterator to bits.
|
||||
*/
|
||||
inline auto rend() noexcept { return _bits.rend(); }
|
||||
|
||||
/*! \brief Constant begin iterator to bits.
|
||||
*/
|
||||
inline auto cbegin() const noexcept { return _bits.cbegin(); }
|
||||
|
||||
/*! \brief Constant end iterator to bits.
|
||||
*/
|
||||
inline auto cend() const noexcept { return _bits.cend(); }
|
||||
|
||||
/*! \brief Constant reverse begin iterator to bits.
|
||||
*/
|
||||
inline auto crbegin() const noexcept { return _bits.crbegin(); }
|
||||
|
||||
/*! \brief Constant teverse end iterator to bits.
|
||||
*/
|
||||
inline auto crend() const noexcept { return _bits.crend(); }
|
||||
|
||||
/*! \brief Assign other truth table if number of variables match.
|
||||
|
||||
This replaces the current truth table with another truth table, if `other`
|
||||
has the same number of variables. Otherwise, the truth table is not
|
||||
changed.
|
||||
|
||||
\param other Other truth table
|
||||
*/
|
||||
template<class TT>
|
||||
static_truth_table<NumVars>& operator=( const TT& other )
|
||||
{
|
||||
if ( other.num_bits() == num_bits() )
|
||||
{
|
||||
std::copy( other.begin(), other.end(), begin() );
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*! Masks the number of valid truth table bits.
|
||||
|
||||
We know that we will have at least 7 variables in this data
|
||||
structure.
|
||||
*/
|
||||
inline void mask_bits() noexcept {}
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
public: /* fields */
|
||||
std::array<uint64_t, NumBlocks> _bits;
|
||||
/*! \endcond */
|
||||
};
|
||||
|
||||
} //namespace kitty
|
||||
|
||||
#endif // _KITTY_STATIC_TT_H_
|
||||
|
|
@ -0,0 +1 @@
|
|||
SRC += src/acd/ac_wrapper.cpp
|
||||
|
|
@ -19447,7 +19447,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
If_ManSetDefaultPars( pPars );
|
||||
pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut();
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyzuojiktncvh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRNTXYDEWSqaflepmrsdbgxyuojiktnczvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -19652,9 +19652,6 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
case 'y':
|
||||
pPars->fUserRecLib ^= 1;
|
||||
break;
|
||||
case 'z':
|
||||
pPars->fUserLutDec ^= 1;
|
||||
break;
|
||||
case 'u':
|
||||
pPars->fUserSesLib ^= 1;
|
||||
break;
|
||||
|
|
@ -19679,6 +19676,9 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
case 'c':
|
||||
pPars->fUseTtPerm ^= 1;
|
||||
break;
|
||||
case 'z':
|
||||
pPars->fAcd ^= 1;
|
||||
break;
|
||||
case 'v':
|
||||
pPars->fVerbose ^= 1;
|
||||
break;
|
||||
|
|
@ -19810,7 +19810,7 @@ int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
pPars->pLutLib = NULL;
|
||||
}
|
||||
// modify for delay optimization
|
||||
if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fUserLutDec )
|
||||
if ( pPars->fDelayOpt || pPars->fDsdBalance || pPars->fDelayOptLut || pPars->fAcd )
|
||||
{
|
||||
pPars->fTruth = 1;
|
||||
pPars->fCutMin = 1;
|
||||
|
|
@ -19956,7 +19956,7 @@ usage:
|
|||
sprintf(LutSize, "library" );
|
||||
else
|
||||
sprintf(LutSize, "%d", pPars->nLutSize );
|
||||
Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyzuojiktncvh]\n" );
|
||||
Abc_Print( -2, "usage: if [-KCFAGRNTXY num] [-DEW float] [-S str] [-qarlepmsdbgxyuojiktncvh]\n" );
|
||||
Abc_Print( -2, "\t performs FPGA technology mapping of the network\n" );
|
||||
Abc_Print( -2, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize );
|
||||
Abc_Print( -2, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax );
|
||||
|
|
@ -19985,7 +19985,6 @@ usage:
|
|||
Abc_Print( -2, "\t-g : toggles delay optimization by SOP balancing [default = %s]\n", pPars->fDelayOpt? "yes": "no" );
|
||||
Abc_Print( -2, "\t-x : toggles delay optimization by DSD balancing [default = %s]\n", pPars->fDsdBalance? "yes": "no" );
|
||||
Abc_Print( -2, "\t-y : toggles delay optimization with recorded library [default = %s]\n", pPars->fUserRecLib? "yes": "no" );
|
||||
Abc_Print( -2, "\t-z : toggles delay optimization with LUT decomposition [default = %s]\n", pPars->fUserLutDec? "yes": "no" );
|
||||
Abc_Print( -2, "\t-u : toggles delay optimization with SAT-based library [default = %s]\n", pPars->fUserSesLib? "yes": "no" );
|
||||
Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", pPars->fUseBuffs? "yes": "no" );
|
||||
Abc_Print( -2, "\t-j : toggles enabling additional check [default = %s]\n", pPars->fEnableCheck07? "yes": "no" );
|
||||
|
|
@ -19994,6 +19993,7 @@ usage:
|
|||
Abc_Print( -2, "\t-t : toggles optimizing average rather than maximum level [default = %s]\n", pPars->fDoAverage? "yes": "no" );
|
||||
Abc_Print( -2, "\t-n : toggles computing DSDs of the cut functions [default = %s]\n", pPars->fUseDsd? "yes": "no" );
|
||||
Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" );
|
||||
Abc_Print( -2, "\t-z : toggles using ACD decomposition [default = %s]\n", pPars->fAcd? "yes": "no" );
|
||||
Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" );
|
||||
Abc_Print( -2, "\t-h : prints the command usage\n");
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars )
|
|||
pPars->pTimesReq = Abc_NtkGetCoRequiredFloats(pNtk);
|
||||
|
||||
// update timing info to reflect logic level
|
||||
if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fUserLutDec) && pNtk->pManTime )
|
||||
if ( (pPars->fDelayOpt || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib || pPars->fAcd) && pNtk->pManTime )
|
||||
{
|
||||
int c;
|
||||
if ( pNtk->AndGateDelay == 0.0 )
|
||||
|
|
@ -427,28 +427,143 @@ Hop_Obj_t * Abc_NodeBuildFromMini( Hop_Man_t * pMan, If_Man_t * p, If_Cut_t * pC
|
|||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
Synopsis [Implements decomposed LUT-structure of the cut.]
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
SeeAlso []
|
||||
***********************************************************************/
|
||||
void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover, Abc_Obj_t * pNodeTop )
|
||||
{
|
||||
extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
|
||||
assert( !pIfMan->pPars->fUseTtPerm );
|
||||
|
||||
Synopsis [Implements decomposed LUT-structure of the cut.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Hop_Obj_t * Abc_DecRecordToHop( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCutBest, If_Obj_t * pIfObj, Vec_Int_t * vCover )
|
||||
{
|
||||
// get the truth table
|
||||
word * pTruth = If_CutTruthW(pIfMan, pCutBest);
|
||||
int v;
|
||||
If_Obj_t * pIfLeaf;
|
||||
|
||||
if ( pCutBest->nLeaves <= 6 )
|
||||
{
|
||||
/* add fanins */
|
||||
If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, v )
|
||||
Abc_ObjAddFanin( pNodeTop, (Abc_Obj_t *)If_ObjCopy( pIfLeaf ) );
|
||||
|
||||
pNodeTop->Level = Abc_ObjLevelNew( pNodeTop );
|
||||
|
||||
pNodeTop->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover );
|
||||
return;
|
||||
}
|
||||
|
||||
// get the delay profile
|
||||
unsigned delayProfile = pCutBest->acdDelay;
|
||||
|
||||
// If_Obj_t * pLeaf;
|
||||
// int i, leafDelay;
|
||||
// int DelayMax = -1, nLeafMax = 0;
|
||||
// unsigned uLeafMask = 0;
|
||||
|
||||
// If_CutForEachLeaf( pIfMan, pCutBest, pLeaf, i )
|
||||
// {
|
||||
// leafDelay = If_ObjCutBest(pLeaf)->Delay;
|
||||
|
||||
// if ( DelayMax < leafDelay )
|
||||
// {
|
||||
// DelayMax = leafDelay;
|
||||
// nLeafMax = 1;
|
||||
// uLeafMask = (1 << i);
|
||||
// }
|
||||
// else if ( DelayMax == leafDelay )
|
||||
// {
|
||||
// nLeafMax++;
|
||||
// uLeafMask |= (1 << i);
|
||||
// }
|
||||
// }
|
||||
|
||||
// perform LUT-decomposition and return the LUT-structure
|
||||
unsigned char decompArray[92];
|
||||
int val = acd_decompose( pTruth, pCutBest->nLeaves, 6, &(delayProfile), decompArray );
|
||||
|
||||
assert( val == 0 );
|
||||
// assert( DelayMax + 2 >= pCutBest->Delay );
|
||||
|
||||
// convert the LUT-structure into a set of logic nodes in Abc_Ntk_t
|
||||
unsigned char bytes_check = decompArray[0];
|
||||
assert( bytes_check <= 92 );
|
||||
|
||||
int byte_p = 2;
|
||||
unsigned char i, j, k, num_fanins, num_words, num_bytes;
|
||||
int level, fanin;
|
||||
word *tt;
|
||||
Abc_Obj_t *pNewNodes[5];
|
||||
|
||||
/* create intermediate LUTs*/
|
||||
assert( decompArray[1] - 1 <= 5 );
|
||||
Abc_Obj_t * pFanin;
|
||||
for ( i = 0; i < decompArray[1]; ++i )
|
||||
{
|
||||
if ( i < decompArray[1] - 1 )
|
||||
{
|
||||
pNewNodes[i] = Abc_NtkCreateNode( pNtkNew );
|
||||
}
|
||||
else
|
||||
{
|
||||
pNewNodes[i] = pNodeTop;
|
||||
}
|
||||
num_fanins = decompArray[byte_p++];
|
||||
level = 0;
|
||||
for ( j = 0; j < num_fanins; ++j )
|
||||
{
|
||||
fanin = (int)decompArray[byte_p++];
|
||||
if ( fanin < If_CutLeaveNum(pCutBest) )
|
||||
{
|
||||
pFanin = (Abc_Obj_t *)If_ObjCopy( If_CutLeaf(pIfMan, pCutBest, fanin) );
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( fanin - If_CutLeaveNum(pCutBest) < i );
|
||||
pFanin = pNewNodes[fanin - If_CutLeaveNum(pCutBest)];
|
||||
}
|
||||
Abc_ObjAddFanin( pNewNodes[i], pFanin );
|
||||
level = Abc_MaxInt( level, Abc_ObjLevel(pFanin) );
|
||||
}
|
||||
|
||||
pNewNodes[i]->Level = level + (int)(Abc_ObjFaninNum(pNewNodes[i]) > 0);
|
||||
|
||||
/* extract the truth table */
|
||||
tt = pIfMan->puTempW;
|
||||
num_words = ( num_fanins <= 6 ) ? 1 : ( 1 << ( num_fanins - 6 ) );
|
||||
num_bytes = ( num_fanins <= 3 ) ? 1 : ( 1 << ( Abc_MinInt( (int)num_fanins, 6 ) - 3 ) );
|
||||
for ( j = 0; j < num_words; ++j )
|
||||
{
|
||||
tt[j] = 0;
|
||||
for ( k = 0; k < num_bytes; ++k )
|
||||
{
|
||||
tt[j] |= ( (word)(decompArray[byte_p++]) ) << ( k << 3 );
|
||||
}
|
||||
}
|
||||
|
||||
/* extend truth table if size < 5 */
|
||||
assert( num_fanins != 1 );
|
||||
if ( num_fanins == 2 )
|
||||
{
|
||||
tt[0] |= tt[0] << 4;
|
||||
}
|
||||
while ( num_bytes < 4 )
|
||||
{
|
||||
tt[0] |= tt[0] << ( num_bytes << 3 );
|
||||
num_bytes <<= 1;
|
||||
}
|
||||
|
||||
/* add node data */
|
||||
pNewNodes[i]->pData = Kit_TruthToHop( (Hop_Man_t *)pNtkNew->pManFunc, (unsigned *)tt, (int) num_fanins, vCover );
|
||||
}
|
||||
|
||||
/* check correct read */
|
||||
assert( byte_p == decompArray[0] );
|
||||
|
||||
// this is a placeholder, which takes the truth table and converts it into an AIG without LUT-decomposition
|
||||
extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory );
|
||||
word * pTruth = If_CutTruthW(pIfMan, pCutBest);
|
||||
assert( !pIfMan->pPars->fUseTtPerm );
|
||||
return Kit_TruthToHop( (Hop_Man_t *)pMan, (unsigned *)pTruth, If_CutLeaveNum(pCutBest), vCover );
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -488,13 +603,18 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
|
|||
pNodeNew = Abc_NtkCreateNode( pNtkNew );
|
||||
// if ( pIfMan->pPars->pLutLib && pIfMan->pPars->pLutLib->fVarPinDelays )
|
||||
if ( !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->fUseTtPerm &&
|
||||
!pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->fUserLutDec && !pIfMan->pPars->nGateSize )
|
||||
!pIfMan->pPars->pLutStruct && !pIfMan->pPars->fAcd && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize )
|
||||
If_CutRotatePins( pIfMan, pCutBest );
|
||||
if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv )
|
||||
{
|
||||
If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i )
|
||||
Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) );
|
||||
}
|
||||
else if ( pIfMan->pPars->fAcd )
|
||||
{
|
||||
If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
|
||||
Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover);
|
||||
}
|
||||
else
|
||||
{
|
||||
If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i )
|
||||
|
|
@ -548,10 +668,10 @@ Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t
|
|||
extern Hop_Obj_t * Abc_RecToHop3( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj );
|
||||
pNodeNew->pData = Abc_RecToHop3( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj );
|
||||
}
|
||||
else if ( pIfMan->pPars->fUserLutDec )
|
||||
else if ( pIfMan->pPars->fAcd )
|
||||
{
|
||||
extern Hop_Obj_t * Abc_DecRecordToHop( Hop_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory );
|
||||
pNodeNew->pData = Abc_DecRecordToHop( (Hop_Man_t *)pNtkNew->pManFunc, pIfMan, pCutBest, pIfObj, vCover );
|
||||
extern void Abc_DecRecordToHop( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Cut_t * pCut, If_Obj_t * pIfObj, Vec_Int_t * vMemory, Abc_Obj_t * pNodeTop );
|
||||
Abc_DecRecordToHop( pNtkNew, pIfMan, pCutBest, pIfObj, vCover, pNodeNew );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "opt/dau/dau.h"
|
||||
#include "misc/vec/vecHash.h"
|
||||
#include "misc/vec/vecWec.h"
|
||||
#include "ACD/ac_wrapper.h"
|
||||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
|
|
@ -126,7 +127,6 @@ struct If_Par_t_
|
|||
int fDsdBalance; // special delay optimization
|
||||
int fUserRecLib; // use recorded library
|
||||
int fUserSesLib; // use SAT-based synthesis
|
||||
int fUserLutDec; // use LUT-based decomposition
|
||||
int fBidec; // use bi-decomposition
|
||||
int fUse34Spec; // use specialized matching
|
||||
int fUseBat; // use one specialized feature
|
||||
|
|
@ -146,6 +146,7 @@ struct If_Par_t_
|
|||
int fDeriveLuts; // enables deriving LUT structures
|
||||
int fDoAverage; // optimize average rather than maximum level
|
||||
int fHashMapping; // perform AIG hashing after mapping
|
||||
int fAcd; // perform AIG hashing after mapping
|
||||
int fVerbose; // the verbosity flag
|
||||
int fVerboseTrace; // the verbosity flag
|
||||
char * pLutStruct; // LUT structure
|
||||
|
|
@ -280,6 +281,7 @@ struct If_Man_t_
|
|||
int pDumpIns[16];
|
||||
Vec_Str_t * vMarks;
|
||||
Vec_Int_t * vVisited2;
|
||||
int useLimitAdc;
|
||||
|
||||
// timing manager
|
||||
Tim_Man_t * pManTim;
|
||||
|
|
@ -303,6 +305,7 @@ struct If_Cut_t_
|
|||
int iCutFunc; // TT ID of the cut
|
||||
int uMaskFunc; // polarity bitmask
|
||||
unsigned uSign; // cut signature
|
||||
unsigned acdDelay; // Computed pin delay during ACD
|
||||
unsigned Cost : 12; // the user's cost of the cut (related to IF_COST_MAX)
|
||||
unsigned fCompl : 1; // the complemented attribute
|
||||
unsigned fUser : 1; // using the user's area and delay
|
||||
|
|
@ -552,6 +555,7 @@ extern int If_CutPerformCheck45( If_Man_t * p, unsigned * pTruth, in
|
|||
extern int If_CutPerformCheck54( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern int If_CutPerformCheck75( If_Man_t * p, unsigned * pTruth, int nVars, int nLeaves, char * pStr );
|
||||
extern float If_CutDelayLutStruct( If_Man_t * p, If_Cut_t * pCut, char * pStr, float WireDelay );
|
||||
// extern int If_CutPerformAcd( If_Man_t * p, unsigned nVars, int lutSize, unsigned * pdelay, int use_late_arrival, unsigned * cost );
|
||||
extern int If_CluCheckExt( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutRoot,
|
||||
char * pLut0, char * pLut1, word * pFunc0, word * pFunc1 );
|
||||
extern int If_CluCheckExt3( void * p, word * pTruth, int nVars, int nLutLeaf, int nLutLeaf2, int nLutRoot,
|
||||
|
|
@ -566,6 +570,9 @@ extern int If_CutSopBalancePinDelaysInt( Vec_Int_t * vCover, int * p
|
|||
extern int If_CutSopBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm );
|
||||
extern int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern int If_CutLutBalancePinDelays( If_Man_t * p, If_Cut_t * pCut, char * pPerm );
|
||||
extern int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, int best_delay );
|
||||
extern int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut );
|
||||
extern float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required );
|
||||
/*=== ifDsd.c =============================================================*/
|
||||
extern If_DsdMan_t * If_DsdManAlloc( int nVars, int nLutSize );
|
||||
extern void If_DsdManAllocIsops( If_DsdMan_t * p, int nLutSize );
|
||||
|
|
@ -693,6 +700,8 @@ extern int If_ManCountSpecialPos( If_Man_t * p );
|
|||
extern void If_CutTraverse( If_Man_t * p, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes );
|
||||
extern void If_ObjPrint( If_Obj_t * pObj );
|
||||
|
||||
extern int acd_evaluate( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned *cost );
|
||||
extern int acd_decompose( word * pTruth, unsigned nVars, int lutSize, unsigned *pdelay, unsigned char *decomposition );
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ void If_ManSetDefaultPars( If_Par_t * pPars )
|
|||
pPars->fPower = 0;
|
||||
pPars->fCutMin = 0;
|
||||
pPars->fBidec = 0;
|
||||
pPars->fAcd = 0;
|
||||
pPars->fVerbose = 0;
|
||||
}
|
||||
|
||||
|
|
@ -106,9 +107,16 @@ int If_ManPerformMappingComb( If_Man_t * p )
|
|||
If_Obj_t * pObj;
|
||||
abctime clkTotal = Abc_Clock();
|
||||
int i;
|
||||
p->useLimitAdc = 1;
|
||||
|
||||
//p->vVisited2 = Vec_IntAlloc( 100 );
|
||||
//p->vMarks = Vec_StrStart( If_ManObjNum(p) );
|
||||
|
||||
// if ( p->pPars->fAcd )
|
||||
// {
|
||||
// p->pPars->nLutSize = 6;
|
||||
// }
|
||||
|
||||
// set arrival times and fanout estimates
|
||||
If_ManForEachCi( p, pObj, i )
|
||||
{
|
||||
|
|
@ -121,6 +129,16 @@ int If_ManPerformMappingComb( If_Man_t * p )
|
|||
{
|
||||
// map for delay
|
||||
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 1, "Delay" );
|
||||
|
||||
if ( p->pPars->fAcd )
|
||||
{
|
||||
// p->pPars->nLutSize = oldLutSize;
|
||||
p->useLimitAdc = 0;
|
||||
If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, 0, "Delay" );
|
||||
p->useLimitAdc = 1;
|
||||
// p->pPars->nLutSize = 6;
|
||||
}
|
||||
|
||||
// map for delay second option
|
||||
p->pPars->fFancy = 1;
|
||||
If_ManResetOriginalRefs( p );
|
||||
|
|
|
|||
|
|
@ -604,10 +604,6 @@ static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC
|
|||
return -1;
|
||||
if ( pC0->nLeaves > pC1->nLeaves )
|
||||
return 1;
|
||||
if ( pC0->Delay < pC1->Delay - p->fEpsilon )
|
||||
return -1;
|
||||
if ( pC0->Delay > pC1->Delay + p->fEpsilon )
|
||||
return 1;
|
||||
if ( pC0->fUseless < pC1->fUseless )
|
||||
return -1;
|
||||
if ( pC0->fUseless > pC1->fUseless )
|
||||
|
|
@ -765,7 +761,7 @@ void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut )
|
|||
|
||||
if ( !pCut->fUseless &&
|
||||
(p->pPars->fUseDsd || p->pPars->pFuncCell2 || p->pPars->fUseBat ||
|
||||
p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec ||
|
||||
p->pPars->pLutStruct || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fAcd ||
|
||||
p->pPars->fEnableCheck07 || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec ||
|
||||
p->pPars->fUseDsdTune || p->pPars->fEnableCheck75 || p->pPars->fEnableCheck75u || p->pPars->fUseCheck1 || p->pPars->fUseCheck2) )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -411,6 +411,132 @@ int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut )
|
|||
return DelayMax + 2;
|
||||
}
|
||||
}
|
||||
|
||||
int If_AcdEval( If_Man_t * p, If_Cut_t * pCut, int best_delay )
|
||||
{
|
||||
pCut->fUser = 1;
|
||||
pCut->Cost = pCut->nLeaves > 1 ? 1 : 0;
|
||||
pCut->acdDelay = 0;
|
||||
if ( pCut->nLeaves == 0 ) // const
|
||||
{
|
||||
assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 );
|
||||
return 0;
|
||||
}
|
||||
if ( pCut->nLeaves == 1 ) // variable
|
||||
{
|
||||
assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 );
|
||||
return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
|
||||
}
|
||||
|
||||
// int LutSize = p->pPars->pLutStruct[0] - '0';
|
||||
int LutSize = 6;
|
||||
int i, leaf_delay;
|
||||
int DelayMax = -1, nLeafMax = 0;
|
||||
unsigned uLeafMask = 0;
|
||||
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
|
||||
{
|
||||
leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay;
|
||||
|
||||
if ( DelayMax < leaf_delay )
|
||||
{
|
||||
DelayMax = leaf_delay;
|
||||
nLeafMax = 1;
|
||||
uLeafMask = (1 << i);
|
||||
}
|
||||
else if ( DelayMax == leaf_delay )
|
||||
{
|
||||
nLeafMax++;
|
||||
uLeafMask |= (1 << i);
|
||||
}
|
||||
}
|
||||
if ( If_CutLeaveNum(pCut) <= LutSize )
|
||||
{
|
||||
pCut->acdDelay = ( 1 << LutSize ) - 1;
|
||||
return DelayMax + 1;
|
||||
}
|
||||
// else if ( DelayMax + 1 >= best_delay )
|
||||
// {
|
||||
// return DelayMax + 2;
|
||||
// }
|
||||
|
||||
/* compute the decomposition */
|
||||
int use_late_arrival = DelayMax + 2 >= best_delay;
|
||||
unsigned cost = 1;
|
||||
|
||||
/* TODO: have checks based on delay */
|
||||
if ( use_late_arrival && nLeafMax > LutSize / 2 )
|
||||
{
|
||||
pCut->Cost = IF_COST_MAX;
|
||||
return ABC_INFINITY;
|
||||
}
|
||||
|
||||
/* remove from critical set */
|
||||
if ( !use_late_arrival )
|
||||
uLeafMask = 0;
|
||||
|
||||
|
||||
word *pTruth = If_CutTruthW( p, pCut );
|
||||
int val = acd_evaluate( pTruth, pCut->nLeaves, LutSize, &uLeafMask, &cost );
|
||||
|
||||
/* not feasible decomposition */
|
||||
pCut->acdDelay = uLeafMask;
|
||||
if ( val < 0 )
|
||||
{
|
||||
pCut->Cost = IF_COST_MAX;
|
||||
return ABC_INFINITY;
|
||||
}
|
||||
|
||||
pCut->Cost = cost;
|
||||
|
||||
return DelayMax + ( use_late_arrival ? 1 : 2 );
|
||||
}
|
||||
|
||||
int If_AcdReEval( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
// pCut->fUser = 1;
|
||||
|
||||
if ( pCut->nLeaves == 0 ) // const
|
||||
{
|
||||
assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 );
|
||||
return 0;
|
||||
}
|
||||
if ( pCut->nLeaves == 1 ) // variable
|
||||
{
|
||||
assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 );
|
||||
return (int)If_ObjCutBest(If_CutLeaf(p, pCut, 0))->Delay;
|
||||
}
|
||||
|
||||
// int LutSize = p->pPars->pLutStruct[0] - '0';
|
||||
int LutSize = 6;
|
||||
int i, leaf_delay;
|
||||
int DelayMax = -1, nLeafMax = 0;
|
||||
unsigned uLeafMask = 0;
|
||||
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
|
||||
{
|
||||
leaf_delay = If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay;
|
||||
leaf_delay += ( ( pCut->acdDelay >> i ) & 1 ) == 0 ? 2 : 1;
|
||||
DelayMax = Abc_MaxInt( leaf_delay, DelayMax );
|
||||
}
|
||||
|
||||
return DelayMax;
|
||||
}
|
||||
|
||||
float If_AcdLeafProp( If_Man_t * p, If_Cut_t * pCut, int i, float required )
|
||||
{
|
||||
if ( pCut->nLeaves == 0 ) // const
|
||||
{
|
||||
assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 0 );
|
||||
return required;
|
||||
}
|
||||
if ( pCut->nLeaves == 1 ) // variable
|
||||
{
|
||||
assert( Abc_Lit2Var(If_CutTruthLit(pCut)) == 1 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ( ( pCut->acdDelay >> i ) & 1 ) == 0 ? 2 : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
int If_CutLutBalanceEval( If_Man_t * p, If_Cut_t * pCut )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -148,32 +148,6 @@ int * If_CutArrTimeProfile( If_Man_t * p, If_Cut_t * pCut )
|
|||
return p->pArrTimeProfile;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the node's delay if its cut it LUT-decomposed.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int If_CutDelayLutDec( If_Man_t * p, If_Cut_t * pCut, If_Obj_t * pObj )
|
||||
{
|
||||
// get the truth table
|
||||
// get the cut leaves' arrival times
|
||||
// run LUT-decomposition in the evaluation mode
|
||||
// return expected arrival time at the output
|
||||
|
||||
// this is a placeholder code, which is assume the cut has unit delay
|
||||
int i, ArrTimes = 0;
|
||||
for ( i = 0; i < If_CutLeaveNum(pCut); i++ )
|
||||
ArrTimes = Abc_MaxInt( ArrTimes, (int)If_ObjCutBest(If_CutLeaf(p, pCut, i))->Delay );
|
||||
return ArrTimes + 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds the best cut for the given node.]
|
||||
|
|
@ -192,7 +166,7 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
|
|||
If_Cut_t * pCut0R, * pCut1R;
|
||||
int fFunc0R, fFunc1R;
|
||||
int i, k, v, iCutDsd, fChange;
|
||||
int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec ||
|
||||
int fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fAcd ||
|
||||
p->pPars->fUseDsdTune || p->pPars->fUseCofVars || p->pPars->fUseAndVars || p->pPars->fUse34Spec || p->pPars->pLutStruct || p->pPars->pFuncCell2 || p->pPars->fUseCheck1 || p->pPars->fUseCheck2;
|
||||
int fUseAndCut = (p->pPars->nAndDelay > 0) || (p->pPars->nAndArea > 0);
|
||||
assert( !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 0 );
|
||||
|
|
@ -234,8 +208,10 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
|
|||
pCut->fUseless = 1;
|
||||
}
|
||||
}
|
||||
else if ( p->pPars->fUserLutDec )
|
||||
pCut->Delay = If_CutDelayLutDec( p, pCut, pObj );
|
||||
else if ( p->pPars->fAcd )
|
||||
{
|
||||
pCut->Delay = If_AcdReEval( p, pCut );
|
||||
}
|
||||
else if ( p->pPars->fDelayOptLut )
|
||||
pCut->Delay = If_CutLutBalanceEval( p, pCut );
|
||||
else if( p->pPars->nGateSize > 0 )
|
||||
|
|
@ -292,6 +268,8 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
|
|||
if ( !If_CutMergeOrdered( p, pCut0, pCut1, pCut ) )
|
||||
continue;
|
||||
}
|
||||
if ( p->pPars->fAcd && p->useLimitAdc && pCut->nLeaves > 6 )
|
||||
continue;
|
||||
if ( pObj->fSpec && pCut->nLeaves == (unsigned)p->pPars->nLutSize )
|
||||
continue;
|
||||
p->nCutsMerged++;
|
||||
|
|
@ -450,7 +428,12 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
|
|||
else if ( p->pPars->fDsdBalance )
|
||||
pCut->Delay = If_CutDsdBalanceEval( p, pCut, NULL );
|
||||
else if ( p->pPars->fUserRecLib )
|
||||
pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj );
|
||||
pCut->Delay = If_CutDelayRecCost3( p, pCut, pObj );
|
||||
else if ( p->pPars->fAcd )
|
||||
{
|
||||
pCut->Delay = If_AcdEval( p, pCut, fFirst ? ABC_INFINITY : (int) If_ObjCutBest(pObj)->Delay );
|
||||
pCut->fUseless = pCut->Delay == ABC_INFINITY;
|
||||
}
|
||||
else if ( p->pPars->fUserSesLib )
|
||||
{
|
||||
int Cost = 0;
|
||||
|
|
@ -464,8 +447,6 @@ void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPrep
|
|||
pCut->fUseless = 1;
|
||||
}
|
||||
}
|
||||
else if ( p->pPars->fUserLutDec )
|
||||
pCut->Delay = If_CutDelayLutDec( p, pCut, pObj );
|
||||
else if ( p->pPars->fDelayOptLut )
|
||||
pCut->Delay = If_CutLutBalanceEval( p, pCut );
|
||||
else if( p->pPars->nGateSize > 0 )
|
||||
|
|
@ -537,7 +518,7 @@ void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fP
|
|||
If_Set_t * pCutSet;
|
||||
If_Obj_t * pTemp;
|
||||
If_Cut_t * pCutTemp, * pCut;
|
||||
int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUserLutDec || p->pPars->fUse34Spec;
|
||||
int i, fSave0 = p->pPars->fDelayOpt || p->pPars->fDelayOptLut || p->pPars->fDsdBalance || p->pPars->fUserRecLib || p->pPars->fUserSesLib || p->pPars->fUse34Spec || p->pPars->fAcd;
|
||||
assert( pObj->pEquiv != NULL );
|
||||
|
||||
// prepare
|
||||
|
|
|
|||
|
|
@ -211,6 +211,12 @@ void If_CutPropagateRequired( If_Man_t * p, If_Obj_t * pObj, If_Cut_t * pCut, fl
|
|||
pLeaf->Required = IF_MIN( pLeaf->Required, Required - pLutDelays[0] );
|
||||
}
|
||||
}
|
||||
else if ( p->pPars->fAcd )
|
||||
{
|
||||
Required = ObjRequired;
|
||||
If_CutForEachLeaf( p, pCut, pLeaf, i )
|
||||
pLeaf->Required = IF_MIN( pLeaf->Required, Required - If_AcdLeafProp( p, pCut, i, ObjRequired ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pCut->fUser )
|
||||
|
|
|
|||
Loading…
Reference in New Issue