blob: ea1ab64fe9ff8286011e771bec27f61679ca1f7b [file] [log] [blame]
/**CFile****************************************************************
FileName [cutPre22.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Precomputes truth tables for the 2x2 macro cell.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cutInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define CUT_CELL_MVAR 9
typedef struct Cut_Cell_t_ Cut_Cell_t;
typedef struct Cut_CMan_t_ Cut_CMan_t;
struct Cut_Cell_t_
{
Cut_Cell_t * pNext; // pointer to the next cell in the table
Cut_Cell_t * pNextVar; // pointer to the next cell of this support size
Cut_Cell_t * pParent; // pointer to the cell used to derive this one
int nUsed; // the number of times the cell is used
char Box[4]; // functions in the boxes
unsigned nVars : 4; // the number of variables
unsigned CrossBar0 : 4; // the variable set equal
unsigned CrossBar1 : 4; // the variable set equal
unsigned CrossBarPhase : 2; // the phase of the cross bar (0, 1, or 2)
unsigned CanonPhase : 18; // the canonical phase
char CanonPerm[CUT_CELL_MVAR+3]; // semicanonical permutation
short Store[2*CUT_CELL_MVAR]; // minterm counts in the cofactors
unsigned uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table
};
struct Cut_CMan_t_
{
// storage for canonical cells
Extra_MmFixed_t * pMem;
st__table * tTable;
Cut_Cell_t * pSameVar[CUT_CELL_MVAR+1];
// elementary truth tables
unsigned uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)];
// temporary truth tables
unsigned uTemp1[22][1<<(CUT_CELL_MVAR-5)];
unsigned uTemp2[22][1<<(CUT_CELL_MVAR-5)];
unsigned uTemp3[22][1<<(CUT_CELL_MVAR-5)];
unsigned uFinal[1<<(CUT_CELL_MVAR-5)];
unsigned puAux[1<<(CUT_CELL_MVAR-5)];
// statistical variables
int nTotal;
int nGood;
int nVarCounts[CUT_CELL_MVAR+1];
int nSymGroups[CUT_CELL_MVAR+1];
int nSymGroupsE[CUT_CELL_MVAR+1];
abctime timeCanon;
abctime timeSupp;
abctime timeTable;
int nCellFound;
int nCellNotFound;
};
// NP-classes of functions of 3 variables (22)
//static char * s_NP3[22] = {
// " 0\n", // 00 const 0 // 0 vars
// " 1\n", // 01 const 1 // 0 vars
// "1 1\n", // 02 a // 1 vars
// "11 1\n", // 03 ab // 2 vars
// "11 0\n", // 04 (ab)' // 2 vars
// "10 1\n01 1\n", // 05 a<+>b // 2 vars
// "111 1\n", // 06 0s abc // 3 vars
// "111 0\n", // 07 (abc)' //
// "11- 1\n1-1 1\n", // 08 1p a(b+c) //
// "11- 0\n1-1 0\n", // 09 (a(b+c))' //
// "111 1\n100 1\n010 1\n001 1\n", // 10 2s a<+>b<+>c //
// "10- 0\n1-0 0\n011 0\n", // 11 3p a<+>bc //
// "101 1\n110 1\n", // 12 4p a(b<+>c) //
// "101 0\n110 0\n", // 13 (a(b<+>c))' //
// "11- 1\n1-1 1\n-11 1\n", // 14 5s ab+bc+ac //
// "111 1\n000 1\n", // 15 6s abc+a'b'c' //
// "111 0\n000 0\n", // 16 (abc+a'b'c')' //
// "11- 1\n-11 1\n0-1 1\n", // 17 7 ab+bc+a'c //
// "011 1\n101 1\n110 1\n", // 18 8s a'bc+ab'c+abc' //
// "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' //
// "100 1\n-11 1\n", // 20 9p ab'c'+bc //
// "100 0\n-11 0\n" // 21 (ab'c'+bc)' //
//};
// NP-classes of functions of 3 variables (22)
static char * s_NP3Names[22] = {
" const 0 ",
" const 1 ",
" a ",
" ab ",
" (ab)' ",
" a<+>b ",
"0s abc ",
" (abc)' ",
"1p a(b+c) ",
" (a(b+c))' ",
"2s a<+>b<+>c ",
"3p a<+>bc ",
"4p a(b<+>c) ",
" (a(b<+>c))' ",
"5s ab+bc+ac ",
"6s abc+a'b'c' ",
" (abc+a'b'c')' ",
"7 ab+bc+a'c ",
"8s a'bc+ab'c+abc' ",
" (a'bc+ab'c+abc')' ",
"9p ab'c'+bc ",
" (ab'c'+bc)' "
};
// the number of variables in each function
//static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 };
// NPN classes of functions of exactly 3 inputs (10)
static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 };
// NPN classes of functions of exactly 3 inputs that are symmetric (5)
//static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 };
// NPN classes of functions of exactly 3 inputs (4)
//static int s_NPNe3p[10] = { 8, 11, 12, 20 };
static Cut_CMan_t * Cut_CManStart();
static void Cut_CManStop( Cut_CMan_t * p );
static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type );
static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell );
static int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell );
static void Cut_CellSuppMin( Cut_Cell_t * pCell );
static void Cut_CellCrossBar( Cut_Cell_t * pCell );
static Cut_CMan_t * s_pCMan = NULL;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Start the precomputation manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cut_CellLoad()
{
FILE * pFile;
char * pFileName = "cells22_daomap_iwls.txt";
char pString[1000];
Cut_CMan_t * p;
Cut_Cell_t * pCell;
int Length; //, i;
pFile = fopen( pFileName, "r" );
if ( pFile == NULL )
{
printf( "Cannot open file \"%s\".\n", pFileName );
return;
}
// start the manager
p = Cut_CManStart();
// load truth tables
while ( fgets(pString, 1000, pFile) )
{
Length = strlen(pString);
pString[Length--] = 0;
if ( Length == 0 )
continue;
// derive the cell
pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
memset( pCell, 0, sizeof(Cut_Cell_t) );
pCell->nVars = Abc_Base2Log(Length*4);
pCell->nUsed = 1;
// Extra_TruthCopy( pCell->uTruth, pTruth, nVars );
Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars );
Cut_CellSuppMin( pCell );
/*
// set the elementary permutation
for ( i = 0; i < (int)pCell->nVars; i++ )
pCell->CanonPerm[i] = i;
// canonicize
pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
*/
// add to the table
p->nTotal++;
// Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" );
// if ( p->nTotal == 500 )
// break;
if ( !Cut_CellTableLookup( p, pCell ) ) // new cell
p->nGood++;
}
printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood );
fclose( pFile );
// return p;
}
/**Function*************************************************************
Synopsis [Precomputes truth tables for the 2x2 macro cell.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cut_CellPrecompute()
{
Cut_CMan_t * p;
Cut_Cell_t * pCell, * pTemp;
int i1, i2, i3, i, j, k, c;
abctime clk = Abc_Clock(); //, clk2 = Abc_Clock();
p = Cut_CManStart();
// precompute truth tables
for ( i = 0; i < 22; i++ )
Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i );
for ( i = 0; i < 22; i++ )
Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i );
for ( i = 0; i < 22; i++ )
Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i );
/*
if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) )
{
Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " );
for ( i = 0; i < pCell->nVars; i++ )
printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars );
printf( "\n" );
}
*/
/*
// go through symmetric roots
for ( k = 0; k < 5; k++ )
for ( i1 = 0; i1 < 22; i1++ )
for ( i2 = i1; i2 < 22; i2++ )
for ( i3 = i2; i3 < 22; i3++ )
{
// derive the cell
pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
memset( pCell, 0, sizeof(Cut_Cell_t) );
pCell->nVars = 9;
pCell->Box[0] = s_NPNe3s[k];
pCell->Box[1] = i1;
pCell->Box[2] = i2;
pCell->Box[3] = i3;
// fill in the truth table
Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] );
// canonicize
Cut_CellCanonicize( pCell );
// add to the table
p->nTotal++;
if ( Cut_CellTableLookup( p, pCell ) ) // already exists
Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
else
p->nGood++;
}
// go through partially symmetric roots
for ( k = 0; k < 4; k++ )
for ( i1 = 0; i1 < 22; i1++ )
for ( i2 = 0; i2 < 22; i2++ )
for ( i3 = i2; i3 < 22; i3++ )
{
// derive the cell
pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
memset( pCell, 0, sizeof(Cut_Cell_t) );
pCell->nVars = 9;
pCell->Box[0] = s_NPNe3p[k];
pCell->Box[1] = i1;
pCell->Box[2] = i2;
pCell->Box[3] = i3;
// fill in the truth table
Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] );
// canonicize
Cut_CellCanonicize( pCell );
// add to the table
p->nTotal++;
if ( Cut_CellTableLookup( p, pCell ) ) // already exists
Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
else
p->nGood++;
}
// go through non-symmetric functions
for ( i1 = 0; i1 < 22; i1++ )
for ( i2 = 0; i2 < 22; i2++ )
for ( i3 = 0; i3 < 22; i3++ )
{
// derive the cell
pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
memset( pCell, 0, sizeof(Cut_Cell_t) );
pCell->nVars = 9;
pCell->Box[0] = 17;
pCell->Box[1] = i1;
pCell->Box[2] = i2;
pCell->Box[3] = i3;
// fill in the truth table
Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 );
// canonicize
Cut_CellCanonicize( pCell );
// add to the table
p->nTotal++;
if ( Cut_CellTableLookup( p, pCell ) ) // already exists
Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
else
p->nGood++;
}
*/
// go through non-symmetric functions
for ( k = 0; k < 10; k++ )
for ( i1 = 0; i1 < 22; i1++ )
for ( i2 = 0; i2 < 22; i2++ )
for ( i3 = 0; i3 < 22; i3++ )
{
// derive the cell
pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
memset( pCell, 0, sizeof(Cut_Cell_t) );
pCell->nVars = 9;
pCell->Box[0] = s_NPNe3[k];
pCell->Box[1] = i1;
pCell->Box[2] = i2;
pCell->Box[3] = i3;
// set the elementary permutation
for ( i = 0; i < (int)pCell->nVars; i++ )
pCell->CanonPerm[i] = i;
// fill in the truth table
Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] );
// minimize the support
Cut_CellSuppMin( pCell );
// canonicize
pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
// add to the table
p->nTotal++;
if ( Cut_CellTableLookup( p, pCell ) ) // already exists
Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
else
{
p->nGood++;
p->nVarCounts[pCell->nVars]++;
if ( pCell->nVars )
for ( i = 0; i < (int)pCell->nVars-1; i++ )
{
if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric
continue;
// i and i+1 can be symmetric
// find the end of this group
for ( j = i+1; j < (int)pCell->nVars; j++ )
if ( pCell->Store[2*i] != pCell->Store[2*j] )
break;
if ( pCell->Store[2*i] == pCell->Store[2*i+1] )
p->nSymGroupsE[j-i]++;
else
p->nSymGroups[j-i]++;
i = j - 1;
}
/*
if ( pCell->nVars == 3 )
{
Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" );
for ( i = 0; i < (int)pCell->nVars; i++ )
printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
printf( "\n" );
}
*/
}
}
printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", (int)p->nTotal, (int)p->nGood, (int)sizeof(Cut_Cell_t) );
ABC_PRT( "Time", Abc_Clock() - clk );
printf( "Cells: " );
for ( i = 0; i <= 9; i++ )
printf( "%d=%d ", i, p->nVarCounts[i] );
printf( "\nDiffs: " );
for ( i = 0; i <= 9; i++ )
printf( "%d=%d ", i, p->nSymGroups[i] );
printf( "\nEquals: " );
for ( i = 0; i <= 9; i++ )
printf( "%d=%d ", i, p->nSymGroupsE[i] );
printf( "\n" );
// continue adding new cells using support
for ( k = CUT_CELL_MVAR; k > 3; k-- )
{
for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
for ( i1 = 0; i1 < k; i1++ )
for ( i2 = i1+1; i2 < k; i2++ )
for ( c = 0; c < 3; c++ )
{
// derive the cell
pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem );
memset( pCell, 0, sizeof(Cut_Cell_t) );
pCell->nVars = pTemp->nVars;
pCell->pParent = pTemp;
// set the elementary permutation
for ( i = 0; i < (int)pCell->nVars; i++ )
pCell->CanonPerm[i] = i;
// fill in the truth table
Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars );
// create the cross-bar
pCell->CrossBar0 = i1;
pCell->CrossBar1 = i2;
pCell->CrossBarPhase = c;
Cut_CellCrossBar( pCell );
// minimize the support
//clk2 = Abc_Clock();
Cut_CellSuppMin( pCell );
//p->timeSupp += Abc_Clock() - clk2;
// canonicize
//clk2 = Abc_Clock();
pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
//p->timeCanon += Abc_Clock() - clk2;
// add to the table
//clk2 = Abc_Clock();
p->nTotal++;
if ( Cut_CellTableLookup( p, pCell ) ) // already exists
Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell );
else
{
p->nGood++;
p->nVarCounts[pCell->nVars]++;
for ( i = 0; i < (int)pCell->nVars-1; i++ )
{
if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric
continue;
// i and i+1 can be symmetric
// find the end of this group
for ( j = i+1; j < (int)pCell->nVars; j++ )
if ( pCell->Store[2*i] != pCell->Store[2*j] )
break;
if ( pCell->Store[2*i] == pCell->Store[2*i+1] )
p->nSymGroupsE[j-i]++;
else
p->nSymGroups[j-i]++;
i = j - 1;
}
/*
if ( pCell->nVars == 3 )
{
Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" );
for ( i = 0; i < (int)pCell->nVars; i++ )
printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] );
printf( "\n" );
}
*/
}
//p->timeTable += Abc_Clock() - clk2;
}
printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, (int)sizeof(Cut_Cell_t) );
ABC_PRT( "Time", Abc_Clock() - clk );
printf( "Cells: " );
for ( i = 0; i <= 9; i++ )
printf( "%d=%d ", i, p->nVarCounts[i] );
printf( "\nDiffs: " );
for ( i = 0; i <= 9; i++ )
printf( "%d=%d ", i, p->nSymGroups[i] );
printf( "\nEquals: " );
for ( i = 0; i <= 9; i++ )
printf( "%d=%d ", i, p->nSymGroupsE[i] );
printf( "\n" );
}
// printf( "\n" );
ABC_PRT( "Supp ", p->timeSupp );
ABC_PRT( "Canon", p->timeCanon );
ABC_PRT( "Table", p->timeTable );
// Cut_CManStop( p );
}
/**Function*************************************************************
Synopsis [Check the table.]
Description [Returns 1 if such a truth table already exists.]
SideEffects []
SeeAlso []
***********************************************************************/
int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell )
{
Cut_Cell_t ** pSlot, * pTemp;
unsigned Hash;
Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) );
if ( ! st__find_or_add( p->tTable, (char *)(ABC_PTRUINT_T)Hash, (char ***)&pSlot ) )
*pSlot = NULL;
for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext )
{
if ( pTemp->nVars != pCell->nVars )
continue;
if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) )
return 1;
}
// the entry is new
pCell->pNext = *pSlot;
*pSlot = pCell;
// add it to the variable support list
pCell->pNextVar = p->pSameVar[pCell->nVars];
p->pSameVar[pCell->nVars] = pCell;
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cut_CellSuppMin( Cut_Cell_t * pCell )
{
static unsigned uTemp[1<<(CUT_CELL_MVAR-5)];
unsigned * pIn, * pOut, * pTemp;
int i, k, Counter, Temp;
// go backward through the support variables and remove redundant
for ( k = pCell->nVars - 1; k >= 0; k-- )
if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) )
{
// shift all the variables above this one
Counter = 0;
pIn = pCell->uTruth; pOut = uTemp;
for ( i = k; i < (int)pCell->nVars - 1; i++ )
{
Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i );
pTemp = pIn; pIn = pOut; pOut = pTemp;
// swap the support vars
Temp = pCell->CanonPerm[i];
pCell->CanonPerm[i] = pCell->CanonPerm[i+1];
pCell->CanonPerm[i+1] = Temp;
Counter++;
}
// return the function back into its place
if ( Counter & 1 )
Extra_TruthCopy( pOut, pIn, pCell->nVars );
// remove one variable
pCell->nVars--;
// Extra_PrintBinary( stdout, pCell->uTruth, (1<<pCell->nVars) ); printf( "\n" );
}
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cut_CellCrossBar( Cut_Cell_t * pCell )
{
static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)];
static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)];
Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars );
Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars );
if ( pCell->CanonPhase == 0 )
{
Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 );
Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 );
Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 );
Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 );
}
else if ( pCell->CanonPhase == 1 )
{
Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 );
Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 );
Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 );
Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 );
}
else if ( pCell->CanonPhase == 2 )
{
Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 );
Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 );
Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 );
Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 );
}
else assert( 0 );
Extra_TruthMux( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type )
{
int nWords = Extra_TruthWordNum( nVars );
int i;
assert( Type < 22 );
switch ( Type )
{
// " 0\n", // 00 const 0
case 0:
for ( i = 0; i < nWords; i++ )
pOut[i] = 0;
return;
// " 1\n", // 01 const 1
case 1:
for ( i = 0; i < nWords; i++ )
pOut[i] = 0xFFFFFFFF;
return;
// "1 1\n", // 02 a
case 2:
for ( i = 0; i < nWords; i++ )
pOut[i] = InA[i];
return;
// "11 1\n", // 03 ab
case 3:
for ( i = 0; i < nWords; i++ )
pOut[i] = InA[i] & InB[i];
return;
// "11 0\n", // 04 (ab)'
case 4:
for ( i = 0; i < nWords; i++ )
pOut[i] = ~(InA[i] & InB[i]);
return;
// "10 1\n01 1\n", // 05 a<+>b
case 5:
for ( i = 0; i < nWords; i++ )
pOut[i] = InA[i] ^ InB[i];
return;
// "111 1\n", // 06 + abc
case 6:
for ( i = 0; i < nWords; i++ )
pOut[i] = InA[i] & InB[i] & InC[i];
return;
// "111 0\n", // 07 (abc)'
case 7:
for ( i = 0; i < nWords; i++ )
pOut[i] = ~(InA[i] & InB[i] & InC[i]);
return;
// "11- 1\n1-1 1\n", // 08 + a(b+c)
case 8:
for ( i = 0; i < nWords; i++ )
pOut[i] = InA[i] & (InB[i] | InC[i]);
return;
// "11- 0\n1-1 0\n", // 09 (a(b+c))'
case 9:
for ( i = 0; i < nWords; i++ )
pOut[i] = ~(InA[i] & (InB[i] | InC[i]));
return;
// "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c
case 10:
for ( i = 0; i < nWords; i++ )
pOut[i] = InA[i] ^ InB[i] ^ InC[i];
return;
// "10- 0\n1-0 0\n011 0\n", // 11 + a<+>bc
case 11:
for ( i = 0; i < nWords; i++ )
pOut[i] = InA[i] ^ (InB[i] & InC[i]);
return;
// "101 1\n110 1\n", // 12 + a(b<+>c)
case 12:
for ( i = 0; i < nWords; i++ )
pOut[i] = InA[i] & (InB[i] ^ InC[i]);
return;
// "101 0\n110 0\n", // 13 (a(b<+>c))'
case 13:
for ( i = 0; i < nWords; i++ )
pOut[i] = ~(InA[i] & (InB[i] ^ InC[i]));
return;
// "11- 1\n1-1 1\n-11 1\n", // 14 + ab+bc+ac
case 14:
for ( i = 0; i < nWords; i++ )
pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]);
return;
// "111 1\n000 1\n", // 15 + abc+a'b'c'
case 15:
for ( i = 0; i < nWords; i++ )
pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]);
return;
// "111 0\n000 0\n", // 16 (abc+a'b'c')'
case 16:
for ( i = 0; i < nWords; i++ )
pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]));
return;
// "11- 1\n-11 1\n0-1 1\n", // 17 + ab+bc+a'c
case 17:
for ( i = 0; i < nWords; i++ )
pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]);
return;
// "011 1\n101 1\n110 1\n", // 18 + a'bc+ab'c+abc'
case 18:
for ( i = 0; i < nWords; i++ )
pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]);
return;
// "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')'
case 19:
for ( i = 0; i < nWords; i++ )
pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]));
return;
// "100 1\n-11 1\n", // 20 + ab'c'+bc
case 20:
for ( i = 0; i < nWords; i++ )
pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]);
return;
// "100 0\n-11 0\n" // 21 (ab'c'+bc)'
case 21:
for ( i = 0; i < nWords; i++ )
pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]));
return;
}
}
/**Function*************************************************************
Synopsis [Start the precomputation manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cut_CMan_t * Cut_CManStart()
{
Cut_CMan_t * p;
int i, k;
// start the manager
assert( sizeof(unsigned) == 4 );
p = ABC_ALLOC( Cut_CMan_t, 1 );
memset( p, 0, sizeof(Cut_CMan_t) );
// start the table and the memory manager
p->tTable = st__init_table( st__ptrcmp, st__ptrhash);;
p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) );
// set elementary truth tables
for ( k = 0; k < CUT_CELL_MVAR; k++ )
for ( i = 0; i < (1<<CUT_CELL_MVAR); i++ )
if ( i & (1 << k) )
p->uInputs[k][i>>5] |= (1 << (i&31));
s_pCMan = p;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cut_CManStop( Cut_CMan_t * p )
{
st__free_table( p->tTable );
Extra_MmFixedStop( p->pMem );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Cut_CellIsRunning()
{
return s_pCMan != NULL;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cut_CellDumpToFile()
{
FILE * pFile;
Cut_CMan_t * p = s_pCMan;
Cut_Cell_t * pTemp;
char * pFileName = "celllib22.txt";
int NumUsed[10][5] = {{0}};
int BoxUsed[22][5] = {{0}};
int i, k, Counter;
abctime clk = Abc_Clock();
if ( p == NULL )
{
printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" );
return;
}
// count the number of cells used
for ( k = CUT_CELL_MVAR; k >= 0; k-- )
{
for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
{
if ( pTemp->nUsed == 0 )
NumUsed[k][0]++;
else if ( pTemp->nUsed < 10 )
NumUsed[k][1]++;
else if ( pTemp->nUsed < 100 )
NumUsed[k][2]++;
else if ( pTemp->nUsed < 1000 )
NumUsed[k][3]++;
else
NumUsed[k][4]++;
for ( i = 0; i < 4; i++ )
if ( pTemp->nUsed == 0 )
BoxUsed[ (int)pTemp->Box[i] ][0]++;
else if ( pTemp->nUsed < 10 )
BoxUsed[ (int)pTemp->Box[i] ][1]++;
else if ( pTemp->nUsed < 100 )
BoxUsed[ (int)pTemp->Box[i] ][2]++;
else if ( pTemp->nUsed < 1000 )
BoxUsed[ (int)pTemp->Box[i] ][3]++;
else
BoxUsed[ (int)pTemp->Box[i] ][4]++;
}
}
printf( "Functions found = %10d. Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound );
for ( k = 0; k <= CUT_CELL_MVAR; k++ )
{
printf( "%3d : ", k );
for ( i = 0; i < 5; i++ )
printf( "%8d ", NumUsed[k][i] );
printf( "\n" );
}
printf( "Box usage:\n" );
for ( k = 0; k < 22; k++ )
{
printf( "%3d : ", k );
for ( i = 0; i < 5; i++ )
printf( "%8d ", BoxUsed[k][i] );
printf( " %s", s_NP3Names[k] );
printf( "\n" );
}
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
{
printf( "Cut_CellDumpToFile: Cannout open output file.\n" );
return;
}
Counter = 0;
for ( k = 0; k <= CUT_CELL_MVAR; k++ )
{
for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar )
if ( pTemp->nUsed > 0 )
{
Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) );
fprintf( pFile, "\n" );
Counter++;
}
fprintf( pFile, "\n" );
}
fclose( pFile );
printf( "Library composed of %d functions is written into file \"%s\". ", Counter, pFileName );
ABC_PRT( "Time", Abc_Clock() - clk );
}
/**Function*************************************************************
Synopsis [Looks up if the given function exists in the hash table.]
Description [If the function exists, returns 1, meaning that it can be
implemented using two levels of 3-input LUTs. If the function does not
exist, return 0.]
SideEffects []
SeeAlso []
***********************************************************************/
int Cut_CellTruthLookup( unsigned * pTruth, int nVars )
{
Cut_CMan_t * p = s_pCMan;
Cut_Cell_t * pTemp;
Cut_Cell_t Cell, * pCell = &Cell;
unsigned Hash;
int i;
// cell manager is not defined
if ( p == NULL )
{
printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" );
return 0;
}
// canonicize
memset( pCell, 0, sizeof(Cut_Cell_t) );
pCell->nVars = nVars;
Extra_TruthCopy( pCell->uTruth, pTruth, nVars );
Cut_CellSuppMin( pCell );
// set the elementary permutation
for ( i = 0; i < (int)pCell->nVars; i++ )
pCell->CanonPerm[i] = i;
// canonicize
pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store );
// check if the cell exists
Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) );
if ( st__lookup( p->tTable, (char *)(ABC_PTRUINT_T)Hash, (char **)&pTemp ) )
{
for ( ; pTemp; pTemp = pTemp->pNext )
{
if ( pTemp->nVars != pCell->nVars )
continue;
if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) )
{
pTemp->nUsed++;
p->nCellFound++;
return 1;
}
}
}
p->nCellNotFound++;
return 0;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END