mirror of https://github.com/YosysHQ/abc.git
1452 lines
50 KiB
C
1452 lines
50 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [ifTune.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [FPGA mapping based on priority cuts.]
|
|
|
|
Synopsis [Library tuning.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - November 21, 2006.]
|
|
|
|
Revision [$Id: ifTune.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "if.h"
|
|
#include "aig/gia/giaAig.h"
|
|
#include "sat/bsat/satStore.h"
|
|
#include "sat/cnf/cnf.h"
|
|
#include "misc/extra/extra.h"
|
|
#include "bool/kit/kit.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#define IFN_INS 11
|
|
#define IFN_WRD (IFN_INS > 6 ? 1 << (IFN_INS-6) : 1)
|
|
#define IFN_PAR 1024
|
|
|
|
// network types
|
|
typedef enum {
|
|
IFN_DSD_NONE = 0, // 0: unknown
|
|
IFN_DSD_CONST0, // 1: constant
|
|
IFN_DSD_VAR, // 2: variable
|
|
IFN_DSD_AND, // 3: AND
|
|
IFN_DSD_XOR, // 4: XOR
|
|
IFN_DSD_MUX, // 5: MUX
|
|
IFN_DSD_PRIME // 6: PRIME
|
|
} Ifn_DsdType_t;
|
|
|
|
// object types
|
|
static char * Ifn_Symbs[16] = {
|
|
NULL, // 0: unknown
|
|
"const", // 1: constant
|
|
"var", // 2: variable
|
|
"()", // 3: AND
|
|
"[]", // 4: XOR
|
|
"<>", // 5: MUX
|
|
"{}" // 6: PRIME
|
|
};
|
|
|
|
typedef struct Ifn_Obj_t_ Ifn_Obj_t;
|
|
struct Ifn_Obj_t_
|
|
{
|
|
unsigned Type : 3; // node type
|
|
unsigned nFanins : 5; // fanin counter
|
|
unsigned iFirst : 8; // first parameter
|
|
unsigned Var : 16; // current variable
|
|
int Fanins[IFN_INS]; // fanin IDs
|
|
};
|
|
struct Ifn_Ntk_t_
|
|
{
|
|
// cell structure
|
|
int nInps; // inputs
|
|
int nObjs; // objects
|
|
Ifn_Obj_t Nodes[2*IFN_INS]; // nodes
|
|
// constraints
|
|
int pConstr[IFN_INS]; // constraint pairs
|
|
int nConstr; // number of pairs
|
|
// user data
|
|
int nVars; // variables
|
|
int nWords; // truth table words
|
|
int nParsVNum; // selection parameters per variable
|
|
int nParsVIni; // first selection parameter
|
|
int nPars; // total parameters
|
|
word * pTruth; // user truth table
|
|
// matching procedures
|
|
int Values[IFN_PAR]; // variable values
|
|
word pTtElems[IFN_INS*IFN_WRD]; // elementary truth tables
|
|
word pTtObjs[2*IFN_INS*IFN_WRD]; // object truth tables
|
|
};
|
|
|
|
static inline word * Ifn_ElemTruth( Ifn_Ntk_t * p, int i ) { return p->pTtElems + i * Abc_TtWordNum(p->nInps); }
|
|
static inline word * Ifn_ObjTruth( Ifn_Ntk_t * p, int i ) { return p->pTtObjs + i * p->nWords; }
|
|
|
|
// variable ordering
|
|
// - primary inputs [0; p->nInps)
|
|
// - internal nodes [p->nInps; p->nObjs)
|
|
// - configuration params [p->nObjs; p->nParsVIni)
|
|
// - variable selection params [p->nParsVIni; p->nPars)
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Prepare network to check the given function.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ifn_Prepare( Ifn_Ntk_t * p, word * pTruth, int nVars )
|
|
{
|
|
int i, fVerbose = 0;
|
|
assert( nVars <= p->nInps );
|
|
p->pTruth = pTruth;
|
|
p->nVars = nVars;
|
|
p->nWords = Abc_TtWordNum(nVars);
|
|
p->nPars = p->nObjs;
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
{
|
|
if ( p->Nodes[i].Type != IFN_DSD_PRIME )
|
|
continue;
|
|
p->Nodes[i].iFirst = p->nPars;
|
|
p->nPars += (1 << p->Nodes[i].nFanins);
|
|
if ( fVerbose )
|
|
printf( "Node %d Start %d Vars %d\n", i, p->Nodes[i].iFirst, (1 << p->Nodes[i].nFanins) );
|
|
}
|
|
if ( fVerbose )
|
|
printf( "Groups start %d\n", p->nPars );
|
|
p->nParsVIni = p->nPars;
|
|
p->nParsVNum = Abc_Base2Log(nVars);
|
|
p->nPars += p->nParsVNum * p->nInps;
|
|
assert( p->nPars <= IFN_PAR );
|
|
memset( p->Values, 0xFF, sizeof(int) * p->nPars );
|
|
return p->nPars;
|
|
}
|
|
void Ifn_NtkPrint( Ifn_Ntk_t * p )
|
|
{
|
|
int i, k;
|
|
if ( p == NULL )
|
|
printf( "String is empty.\n" );
|
|
if ( p == NULL )
|
|
return;
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
{
|
|
printf( "%c=", 'a'+i );
|
|
printf( "%c", Ifn_Symbs[p->Nodes[i].Type][0] );
|
|
for ( k = 0; k < (int)p->Nodes[i].nFanins; k++ )
|
|
printf( "%c", 'a'+p->Nodes[i].Fanins[k] );
|
|
printf( "%c", Ifn_Symbs[p->Nodes[i].Type][1] );
|
|
printf( ";" );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
int Ifn_NtkLutSizeMax( Ifn_Ntk_t * p )
|
|
{
|
|
int i, LutSize = 0;
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
if ( p->Nodes[i].Type == IFN_DSD_PRIME )
|
|
LutSize = Abc_MaxInt( LutSize, (int)p->Nodes[i].nFanins );
|
|
return LutSize;
|
|
}
|
|
int Ifn_NtkInputNum( Ifn_Ntk_t * p )
|
|
{
|
|
return p->nInps;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ifn_ErrorMessage( const char * format, ... )
|
|
{
|
|
char * pMessage;
|
|
va_list args;
|
|
va_start( args, format );
|
|
pMessage = vnsprintf( format, args );
|
|
va_end( args );
|
|
printf( "%s", pMessage );
|
|
ABC_FREE( pMessage );
|
|
return 0;
|
|
}
|
|
int Inf_ManOpenSymb( char * pStr )
|
|
{
|
|
if ( pStr[0] == '(' )
|
|
return 3;
|
|
if ( pStr[0] == '[' )
|
|
return 4;
|
|
if ( pStr[0] == '<' )
|
|
return 5;
|
|
if ( pStr[0] == '{' )
|
|
return 6;
|
|
return 0;
|
|
}
|
|
int Ifn_ManStrCheck( char * pStr, int * pnInps, int * pnObjs )
|
|
{
|
|
int i, nNodes = 0, Marks[32] = {0}, MaxVar = -1;
|
|
for ( i = 0; pStr[i]; i++ )
|
|
{
|
|
if ( Inf_ManOpenSymb(pStr+i) )
|
|
nNodes++;
|
|
if ( pStr[i] == ';' ||
|
|
pStr[i] == '(' || pStr[i] == ')' ||
|
|
pStr[i] == '[' || pStr[i] == ']' ||
|
|
pStr[i] == '<' || pStr[i] == '>' ||
|
|
pStr[i] == '{' || pStr[i] == '}' )
|
|
continue;
|
|
if ( pStr[i] >= 'A' && pStr[i] <= 'Z' )
|
|
continue;
|
|
if ( pStr[i] >= 'a' && pStr[i] <= 'z' )
|
|
{
|
|
MaxVar = Abc_MaxInt( MaxVar, (int)(pStr[i] - 'a') );
|
|
Marks[pStr[i] - 'a'] = 1;
|
|
continue;
|
|
}
|
|
return Ifn_ErrorMessage( "String \"%s\" contains unrecognized symbol \'%c\'.\n", pStr, pStr[i] );
|
|
}
|
|
for ( i = 0; i <= MaxVar; i++ )
|
|
if ( Marks[i] == 0 )
|
|
return Ifn_ErrorMessage( "String \"%s\" has no symbol \'%c\'.\n", pStr, 'a' + i );
|
|
*pnInps = MaxVar + 1;
|
|
*pnObjs = MaxVar + 1 + nNodes;
|
|
return 1;
|
|
}
|
|
static inline char * Ifn_NtkParseFindClosingParenthesis( char * pStr, char Open, char Close )
|
|
{
|
|
int Counter = 0;
|
|
assert( *pStr == Open );
|
|
for ( ; *pStr; pStr++ )
|
|
{
|
|
if ( *pStr == Open )
|
|
Counter++;
|
|
if ( *pStr == Close )
|
|
Counter--;
|
|
if ( Counter == 0 )
|
|
return pStr;
|
|
}
|
|
return NULL;
|
|
}
|
|
int Ifn_NtkParseInt_rec( char * pStr, Ifn_Ntk_t * p, char ** ppFinal, int * piNode )
|
|
{
|
|
Ifn_Obj_t * pObj;
|
|
int nFanins = 0, pFanins[IFN_INS];
|
|
int Type = Inf_ManOpenSymb( pStr );
|
|
char * pLim = Ifn_NtkParseFindClosingParenthesis( pStr++, Ifn_Symbs[Type][0], Ifn_Symbs[Type][1] );
|
|
*ppFinal = NULL;
|
|
if ( pLim == NULL )
|
|
return Ifn_ErrorMessage( "For symbol \'%c\' cannot find matching symbol \'%c\'.\n", Ifn_Symbs[Type][0], Ifn_Symbs[Type][1] );
|
|
while ( pStr < pLim )
|
|
{
|
|
assert( nFanins < IFN_INS );
|
|
if ( pStr[0] >= 'a' && pStr[0] <= 'z' )
|
|
pFanins[nFanins++] = pStr[0] - 'a', pStr++;
|
|
else if ( Inf_ManOpenSymb(pStr) )
|
|
{
|
|
if ( !Ifn_NtkParseInt_rec( pStr, p, &pStr, piNode ) )
|
|
return 0;
|
|
pFanins[nFanins++] = *piNode - 1;
|
|
}
|
|
else
|
|
return Ifn_ErrorMessage( "Substring \"%s\" contans unrecognized symbol \'%c\'.\n", pStr, pStr[0] );
|
|
}
|
|
assert( pStr == pLim );
|
|
pObj = p->Nodes + (*piNode)++;
|
|
pObj->Type = Type;
|
|
assert( pObj->nFanins == 0 );
|
|
pObj->nFanins = nFanins;
|
|
memcpy( pObj->Fanins, pFanins, sizeof(int) * nFanins );
|
|
*ppFinal = pLim + 1;
|
|
if ( Type == IFN_DSD_MUX && nFanins != 3 )
|
|
return Ifn_ErrorMessage( "MUX should have exactly three fanins.\n" );
|
|
return 1;
|
|
}
|
|
int Ifn_NtkParseInt( char * pStr, Ifn_Ntk_t * p )
|
|
{
|
|
char * pFinal; int iNode;
|
|
if ( !Ifn_ManStrCheck(pStr, &p->nInps, &p->nObjs) )
|
|
return 0;
|
|
if ( p->nInps > IFN_INS )
|
|
return Ifn_ErrorMessage( "The number of variables (%d) exceeds predefined limit (%d). Recompile with different value of IFN_INS.\n", p->nInps, IFN_INS );
|
|
assert( p->nInps > 1 && p->nInps < p->nObjs && p->nInps <= IFN_INS && p->nObjs < 2*IFN_INS );
|
|
if ( !Inf_ManOpenSymb(pStr) )
|
|
return Ifn_ErrorMessage( "The first symbol should be one of the symbols: (, [, <, {.\n" );
|
|
iNode = p->nInps;
|
|
if ( !Ifn_NtkParseInt_rec( pStr, p, &pFinal, &iNode ) )
|
|
return 0;
|
|
if ( pFinal[0] && pFinal[0] != ';' )
|
|
return Ifn_ErrorMessage( "The last symbol should be \';\'.\n" );
|
|
if ( iNode != p->nObjs )
|
|
return Ifn_ErrorMessage( "Mismatch in the number of nodes.\n" );
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ifn_ManStrType2( char * pStr )
|
|
{
|
|
int i;
|
|
for ( i = 0; pStr[i]; i++ )
|
|
if ( pStr[i] == '=' )
|
|
return 1;
|
|
return 0;
|
|
}
|
|
int Ifn_ManStrCheck2( char * pStr, int * pnInps, int * pnObjs )
|
|
{
|
|
int i, Marks[32] = {0}, MaxVar = 0, MaxDef = 0;
|
|
for ( i = 0; pStr[i]; i++ )
|
|
{
|
|
if ( pStr[i] == '=' || pStr[i] == ';' ||
|
|
pStr[i] == '(' || pStr[i] == ')' ||
|
|
pStr[i] == '[' || pStr[i] == ']' ||
|
|
pStr[i] == '<' || pStr[i] == '>' ||
|
|
pStr[i] == '{' || pStr[i] == '}' )
|
|
continue;
|
|
if ( pStr[i] >= 'A' && pStr[i] <= 'Z' )
|
|
continue;
|
|
if ( pStr[i] >= 'a' && pStr[i] <= 'z' )
|
|
{
|
|
if ( pStr[i+1] == '=' )
|
|
Marks[pStr[i] - 'a'] = 2, MaxDef = Abc_MaxInt(MaxDef, pStr[i] - 'a');
|
|
continue;
|
|
}
|
|
return Ifn_ErrorMessage( "String \"%s\" contains unrecognized symbol \'%c\'.\n", pStr, pStr[i] );
|
|
}
|
|
for ( i = 0; pStr[i]; i++ )
|
|
{
|
|
if ( pStr[i] == '=' || pStr[i] == ';' ||
|
|
pStr[i] == '(' || pStr[i] == ')' ||
|
|
pStr[i] == '[' || pStr[i] == ']' ||
|
|
pStr[i] == '<' || pStr[i] == '>' ||
|
|
pStr[i] == '{' || pStr[i] == '}' )
|
|
continue;
|
|
if ( pStr[i] >= 'A' && pStr[i] <= 'Z' )
|
|
continue;
|
|
if ( pStr[i] >= 'a' && pStr[i] <= 'z' )
|
|
{
|
|
if ( pStr[i+1] != '=' && Marks[pStr[i] - 'a'] != 2 )
|
|
Marks[pStr[i] - 'a'] = 1, MaxVar = Abc_MaxInt(MaxVar, pStr[i] - 'a');
|
|
continue;
|
|
}
|
|
return Ifn_ErrorMessage( "String \"%s\" contains unrecognized symbol \'%c\'.\n", pStr, pStr[i] );
|
|
}
|
|
MaxVar++;
|
|
MaxDef++;
|
|
for ( i = 0; i < MaxDef; i++ )
|
|
if ( Marks[i] == 0 )
|
|
return Ifn_ErrorMessage( "String \"%s\" has no symbol \'%c\'.\n", pStr, 'a' + i );
|
|
for ( i = 0; i < MaxVar; i++ )
|
|
if ( Marks[i] == 2 )
|
|
return Ifn_ErrorMessage( "String \"%s\" has definition of input variable \'%c\'.\n", pStr, 'a' + i );
|
|
for ( i = MaxVar; i < MaxDef; i++ )
|
|
if ( Marks[i] == 1 )
|
|
return Ifn_ErrorMessage( "String \"%s\" has no definition for internal variable \'%c\'.\n", pStr, 'a' + i );
|
|
*pnInps = MaxVar;
|
|
*pnObjs = MaxDef;
|
|
return 1;
|
|
}
|
|
int Ifn_NtkParseInt2( char * pStr, Ifn_Ntk_t * p )
|
|
{
|
|
int i, k, n, f, nFans, iFan;
|
|
if ( !Ifn_ManStrCheck2(pStr, &p->nInps, &p->nObjs) )
|
|
return 0;
|
|
if ( p->nInps > IFN_INS )
|
|
return Ifn_ErrorMessage( "The number of variables (%d) exceeds predefined limit (%d). Recompile with different value of IFN_INS.\n", p->nInps, IFN_INS );
|
|
assert( p->nInps > 1 && p->nInps < p->nObjs && p->nInps <= IFN_INS && p->nObjs < 2*IFN_INS );
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
{
|
|
char Next = 0;
|
|
for ( k = 0; pStr[k]; k++ )
|
|
if ( pStr[k] == 'a' + i && pStr[k+1] == '=' )
|
|
break;
|
|
if ( pStr[k] == 0 )
|
|
return Ifn_ErrorMessage( "Cannot find definition of signal \'%c\'.\n", 'a' + i );
|
|
if ( pStr[k+2] == '(' )
|
|
p->Nodes[i].Type = IFN_DSD_AND, Next = ')';
|
|
else if ( pStr[k+2] == '[' )
|
|
p->Nodes[i].Type = IFN_DSD_XOR, Next = ']';
|
|
else if ( pStr[k+2] == '<' )
|
|
p->Nodes[i].Type = IFN_DSD_MUX, Next = '>';
|
|
else if ( pStr[k+2] == '{' )
|
|
p->Nodes[i].Type = IFN_DSD_PRIME, Next = '}';
|
|
else
|
|
return Ifn_ErrorMessage( "Cannot find openning operation symbol in the definition of signal \'%c\'.\n", 'a' + i );
|
|
for ( n = k + 3; pStr[n]; n++ )
|
|
if ( pStr[n] == Next )
|
|
break;
|
|
if ( pStr[n] == 0 )
|
|
return Ifn_ErrorMessage( "Cannot find closing operation symbol in the definition of signal \'%c\'.\n", 'a' + i );
|
|
nFans = n - k - 3;
|
|
if ( nFans > 8 )
|
|
return Ifn_ErrorMessage( "Cannot find matching operation symbol in the definition of signal \'%c\'.\n", 'a' + i );
|
|
for ( f = 0; f < nFans; f++ )
|
|
{
|
|
iFan = pStr[k + 3 + f] - 'a';
|
|
if ( iFan < 0 || iFan >= i )
|
|
return Ifn_ErrorMessage( "Fanin number %d is signal %d is out of range.\n", f, 'a' + i );
|
|
p->Nodes[i].Fanins[f] = iFan;
|
|
}
|
|
p->Nodes[i].nFanins = nFans;
|
|
}
|
|
return 1;
|
|
}
|
|
void Ifn_NtkParseConstraints( char * pStr, Ifn_Ntk_t * p )
|
|
{
|
|
int i, k;
|
|
// parse constraints
|
|
p->nConstr = 0;
|
|
for ( i = 0; i < p->nInps; i++ )
|
|
for ( k = 0; pStr[k]; k++ )
|
|
if ( pStr[k] == 'A' + i && pStr[k-1] == ';' )
|
|
{
|
|
p->pConstr[p->nConstr++] = ((int)(pStr[k] - 'A') << 16) | (int)(pStr[k+1] - 'A');
|
|
// printf( "Added constraint (%c < %c)\n", pStr[k], pStr[k+1] );
|
|
}
|
|
// if ( p->nConstr )
|
|
// printf( "Total constraints = %d\n", p->nConstr );
|
|
}
|
|
|
|
Ifn_Ntk_t * Ifn_NtkParse( char * pStr )
|
|
{
|
|
Ifn_Ntk_t * p = ABC_CALLOC( Ifn_Ntk_t, 1 );
|
|
if ( Ifn_ManStrType2(pStr) )
|
|
{
|
|
if ( !Ifn_NtkParseInt2( pStr, p ) )
|
|
{
|
|
ABC_FREE( p );
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !Ifn_NtkParseInt( pStr, p ) )
|
|
{
|
|
ABC_FREE( p );
|
|
return NULL;
|
|
}
|
|
}
|
|
Ifn_NtkParseConstraints( pStr, p );
|
|
Abc_TtElemInit2( p->pTtElems, p->nInps );
|
|
// printf( "Finished parsing: " ); Ifn_NtkPrint(p);
|
|
return p;
|
|
}
|
|
int Ifn_NtkTtBits( char * pStr )
|
|
{
|
|
int i, Counter = 0;
|
|
Ifn_Ntk_t * pNtk = Ifn_NtkParse( pStr );
|
|
for ( i = pNtk->nInps; i < pNtk->nObjs; i++ )
|
|
if ( pNtk->Nodes[i].Type == IFN_DSD_PRIME )
|
|
Counter += (1 << pNtk->Nodes[i].nFanins);
|
|
ABC_FREE( pNtk );
|
|
return Counter;
|
|
}
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derive AIG.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
Gia_Man_t * Ifn_ManStrFindModel( Ifn_Ntk_t * p )
|
|
{
|
|
Gia_Man_t * pNew, * pTemp;
|
|
int i, k, iLit, * pVarMap = ABC_FALLOC( int, p->nParsVIni );
|
|
pNew = Gia_ManStart( 1000 );
|
|
pNew->pName = Abc_UtilStrsav( "model" );
|
|
Gia_ManHashStart( pNew );
|
|
for ( i = 0; i < p->nInps; i++ )
|
|
pVarMap[i] = Gia_ManAppendCi(pNew);
|
|
for ( i = p->nObjs; i < p->nParsVIni; i++ )
|
|
pVarMap[i] = Gia_ManAppendCi(pNew);
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
{
|
|
int Type = p->Nodes[i].Type;
|
|
int nFans = p->Nodes[i].nFanins;
|
|
int * pFans = p->Nodes[i].Fanins;
|
|
int iFanin = p->Nodes[i].iFirst;
|
|
if ( Type == IFN_DSD_AND )
|
|
{
|
|
iLit = 1;
|
|
for ( k = 0; k < nFans; k++ )
|
|
iLit = Gia_ManHashAnd( pNew, iLit, pVarMap[pFans[k]] );
|
|
pVarMap[i] = iLit;
|
|
}
|
|
else if ( Type == IFN_DSD_XOR )
|
|
{
|
|
iLit = 0;
|
|
for ( k = 0; k < nFans; k++ )
|
|
iLit = Gia_ManHashXor( pNew, iLit, pVarMap[pFans[k]] );
|
|
pVarMap[i] = iLit;
|
|
}
|
|
else if ( Type == IFN_DSD_MUX )
|
|
{
|
|
assert( nFans == 3 );
|
|
pVarMap[i] = Gia_ManHashMux( pNew, pVarMap[pFans[0]], pVarMap[pFans[1]], pVarMap[pFans[2]] );
|
|
}
|
|
else if ( Type == IFN_DSD_PRIME )
|
|
{
|
|
int n, Step, pVarsData[256];
|
|
int nMints = (1 << nFans);
|
|
assert( nFans >= 0 && nFans <= 8 );
|
|
for ( k = 0; k < nMints; k++ )
|
|
pVarsData[k] = pVarMap[iFanin + k];
|
|
for ( Step = 1, k = 0; k < nFans; k++, Step <<= 1 )
|
|
for ( n = 0; n < nMints; n += Step << 1 )
|
|
pVarsData[n] = Gia_ManHashMux( pNew, pVarMap[pFans[k]], pVarsData[n+Step], pVarsData[n] );
|
|
assert( Step == nMints );
|
|
pVarMap[i] = pVarsData[0];
|
|
}
|
|
else assert( 0 );
|
|
}
|
|
Gia_ManAppendCo( pNew, pVarMap[p->nObjs-1] );
|
|
ABC_FREE( pVarMap );
|
|
pNew = Gia_ManCleanup( pTemp = pNew );
|
|
Gia_ManStop( pTemp );
|
|
assert( Gia_ManPiNum(pNew) == p->nParsVIni - (p->nObjs - p->nInps) );
|
|
assert( Gia_ManPoNum(pNew) == 1 );
|
|
return pNew;
|
|
}
|
|
// compute cofactors w.r.t. the first nIns variables
|
|
Gia_Man_t * Ifn_ManStrFindCofactors( int nIns, Gia_Man_t * p )
|
|
{
|
|
Gia_Man_t * pNew, * pTemp;
|
|
Gia_Obj_t * pObj;
|
|
int i, m, nMints = 1 << nIns;
|
|
pNew = Gia_ManStart( Gia_ManObjNum(p) );
|
|
pNew->pName = Abc_UtilStrsav( p->pName );
|
|
Gia_ManHashAlloc( pNew );
|
|
Gia_ManConst0(p)->Value = 0;
|
|
Gia_ManForEachCi( p, pObj, i )
|
|
if ( i >= nIns )
|
|
pObj->Value = Gia_ManAppendCi( pNew );
|
|
for ( m = 0; m < nMints; m++ )
|
|
{
|
|
Gia_ManForEachCi( p, pObj, i )
|
|
if ( i < nIns )
|
|
pObj->Value = ((m >> i) & 1);
|
|
Gia_ManForEachAnd( p, pObj, i )
|
|
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
|
Gia_ManForEachPo( p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
|
}
|
|
pNew = Gia_ManCleanup( pTemp = pNew );
|
|
Gia_ManStop( pTemp );
|
|
return pNew;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derive SAT solver.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p )
|
|
{
|
|
Cnf_Dat_t * pCnf;
|
|
Aig_Man_t * pAig = Gia_ManToAigSimple( p );
|
|
pAig->nRegs = 0;
|
|
pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) );
|
|
Aig_ManStop( pAig );
|
|
return pCnf;
|
|
}
|
|
sat_solver * Ifn_ManStrFindSolver( Gia_Man_t * p, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars )
|
|
{
|
|
sat_solver * pSat;
|
|
Gia_Obj_t * pObj;
|
|
Cnf_Dat_t * pCnf;
|
|
int i;
|
|
pCnf = Cnf_DeriveGiaRemapped( p );
|
|
// start the SAT solver
|
|
pSat = sat_solver_new();
|
|
sat_solver_setnvars( pSat, pCnf->nVars );
|
|
// add timeframe clauses
|
|
for ( i = 0; i < pCnf->nClauses; i++ )
|
|
if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
|
|
assert( 0 );
|
|
// inputs/outputs
|
|
*pvPiVars = Vec_IntAlloc( Gia_ManPiNum(p) );
|
|
Gia_ManForEachCi( p, pObj, i )
|
|
Vec_IntPush( *pvPiVars, pCnf->pVarNums[Gia_ObjId(p, pObj)] );
|
|
*pvPoVars = Vec_IntAlloc( Gia_ManPoNum(p) );
|
|
Gia_ManForEachCo( p, pObj, i )
|
|
Vec_IntPush( *pvPoVars, pCnf->pVarNums[Gia_ObjId(p, pObj)] );
|
|
Cnf_DataFree( pCnf );
|
|
return pSat;
|
|
}
|
|
sat_solver * Ifn_ManSatBuild( Ifn_Ntk_t * p, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars )
|
|
{
|
|
Gia_Man_t * p1, * p2;
|
|
sat_solver * pSat = NULL;
|
|
*pvPiVars = *pvPoVars = NULL;
|
|
p1 = Ifn_ManStrFindModel( p );
|
|
// Gia_AigerWrite( p1, "satbuild.aig", 0, 0 );
|
|
p2 = Ifn_ManStrFindCofactors( p->nInps, p1 );
|
|
Gia_ManStop( p1 );
|
|
// Gia_AigerWrite( p2, "satbuild2.aig", 0, 0 );
|
|
pSat = Ifn_ManStrFindSolver( p2, pvPiVars, pvPoVars );
|
|
Gia_ManStop( p2 );
|
|
return pSat;
|
|
}
|
|
void * If_ManSatBuildFromCell( char * pStr, Vec_Int_t ** pvPiVars, Vec_Int_t ** pvPoVars, Ifn_Ntk_t ** ppNtk )
|
|
{
|
|
Ifn_Ntk_t * p = Ifn_NtkParse( pStr );
|
|
Ifn_Prepare( p, NULL, p->nInps );
|
|
*ppNtk = p;
|
|
if ( p == NULL )
|
|
return NULL;
|
|
// Ifn_NtkPrint( p );
|
|
return Ifn_ManSatBuild( p, pvPiVars, pvPoVars );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ifn_ManSatPrintPerm( char * pPerms, int nVars )
|
|
{
|
|
int i;
|
|
for ( i = 0; i < nVars; i++ )
|
|
printf( "%c", 'a' + pPerms[i] );
|
|
printf( "\n" );
|
|
}
|
|
int Ifn_ManSatCheckOne( sat_solver * pSat, Vec_Int_t * vPoVars, word * pTruth, int nVars, int * pPerm, int nInps, Vec_Int_t * vLits )
|
|
{
|
|
int v, Value, m, mNew, nMints = (1 << nVars); // (1 << nInps);
|
|
assert( (1 << nInps) == Vec_IntSize(vPoVars) );
|
|
assert( nVars <= nInps );
|
|
// remap minterms
|
|
Vec_IntFill( vLits, Vec_IntSize(vPoVars), -1 );
|
|
for ( m = 0; m < nMints; m++ )
|
|
{
|
|
mNew = 0;
|
|
for ( v = 0; v < nInps; v++ )
|
|
{
|
|
assert( pPerm[v] < nVars );
|
|
if ( ((m >> pPerm[v]) & 1) )
|
|
mNew |= (1 << v);
|
|
}
|
|
assert( Vec_IntEntry(vLits, mNew) == -1 );
|
|
Vec_IntWriteEntry( vLits, mNew, Abc_TtGetBit(pTruth, m) );
|
|
}
|
|
// find assumptions
|
|
v = 0;
|
|
Vec_IntForEachEntry( vLits, Value, m )
|
|
if ( Value >= 0 )
|
|
Vec_IntWriteEntry( vLits, v++, Abc_Var2Lit(Vec_IntEntry(vPoVars, m), !Value) );
|
|
Vec_IntShrink( vLits, v );
|
|
// run SAT solver
|
|
Value = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), 0, 0, 0, 0 );
|
|
return (int)(Value == l_True);
|
|
}
|
|
void Ifn_ManSatDeriveOne( sat_solver * pSat, Vec_Int_t * vPiVars, Vec_Int_t * vValues )
|
|
{
|
|
int i, iVar;
|
|
Vec_IntClear( vValues );
|
|
Vec_IntForEachEntry( vPiVars, iVar, i )
|
|
Vec_IntPush( vValues, sat_solver_var_value(pSat, iVar) );
|
|
}
|
|
int If_ManSatFindCofigBits( void * pSat, Vec_Int_t * vPiVars, Vec_Int_t * vPoVars, word * pTruth, int nVars, word Perm, int nInps, Vec_Int_t * vValues )
|
|
{
|
|
// extract permutation
|
|
int RetValue, i, pPerm[IF_MAX_FUNC_LUTSIZE];
|
|
assert( nInps <= IF_MAX_FUNC_LUTSIZE );
|
|
for ( i = 0; i < nInps; i++ )
|
|
{
|
|
pPerm[i] = Abc_TtGetHex( &Perm, i );
|
|
assert( pPerm[i] < nVars );
|
|
}
|
|
// perform SAT check
|
|
RetValue = Ifn_ManSatCheckOne( (sat_solver *)pSat, vPoVars, pTruth, nVars, pPerm, nInps, vValues );
|
|
Vec_IntClear( vValues );
|
|
if ( RetValue == 0 )
|
|
return 0;
|
|
Ifn_ManSatDeriveOne( (sat_solver*)pSat, vPiVars, vValues );
|
|
return 1;
|
|
}
|
|
int Ifn_ManSatFindCofigBitsTest( Ifn_Ntk_t * p, word * pTruth, int nVars, word Perm )
|
|
{
|
|
Vec_Int_t * vValues = Vec_IntAlloc( 100 );
|
|
Vec_Int_t * vPiVars, * vPoVars;
|
|
sat_solver * pSat = Ifn_ManSatBuild( p, &vPiVars, &vPoVars );
|
|
int RetValue = If_ManSatFindCofigBits( pSat, vPiVars, vPoVars, pTruth, nVars, Perm, p->nInps, vValues );
|
|
Vec_IntPrint( vValues );
|
|
// cleanup
|
|
sat_solver_delete( pSat );
|
|
Vec_IntFreeP( &vPiVars );
|
|
Vec_IntFreeP( &vPoVars );
|
|
Vec_IntFreeP( &vValues );
|
|
return RetValue;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derive GIA using programmable bits.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int If_ManSatDeriveGiaFromBits( void * pGia, Ifn_Ntk_t * p, word * pConfigData, Vec_Int_t * vLeaves, Vec_Int_t * vCover )
|
|
{
|
|
Gia_Man_t * pNew = (Gia_Man_t *)pGia;
|
|
int i, k, iLit, iVar = 0, nVarsNew, pVarMap[1000];
|
|
int nTtBits = p->nParsVIni - p->nObjs;
|
|
int nPermBits = Abc_Base2Log(p->nInps + 1) + 1;
|
|
int fCompl = Abc_TtGetBit( pConfigData, nTtBits + nPermBits * p->nInps );
|
|
assert( Vec_IntSize(vLeaves) <= p->nInps && p->nParsVIni < 1000 );
|
|
for ( i = 0; i < p->nInps; i++ )
|
|
{
|
|
for ( iLit = k = 0; k < nPermBits; k++ )
|
|
if ( Abc_TtGetBit(pConfigData, nTtBits + i * nPermBits + k) )
|
|
iLit |= (1 << k);
|
|
assert( Abc_Lit2Var(iLit) < Vec_IntSize(vLeaves) );
|
|
pVarMap[i] = Abc_Lit2LitL( Vec_IntArray(vLeaves), iLit );
|
|
}
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
{
|
|
int Type = p->Nodes[i].Type;
|
|
int nFans = p->Nodes[i].nFanins;
|
|
int * pFans = p->Nodes[i].Fanins;
|
|
//int iFanin = p->Nodes[i].iFirst;
|
|
assert( nFans <= 6 );
|
|
if ( Type == IFN_DSD_AND )
|
|
{
|
|
iLit = 1;
|
|
for ( k = 0; k < nFans; k++ )
|
|
iLit = Gia_ManHashAnd( pNew, iLit, pVarMap[pFans[k]] );
|
|
pVarMap[i] = iLit;
|
|
}
|
|
else if ( Type == IFN_DSD_XOR )
|
|
{
|
|
iLit = 0;
|
|
for ( k = 0; k < nFans; k++ )
|
|
iLit = Gia_ManHashXor( pNew, iLit, pVarMap[pFans[k]] );
|
|
pVarMap[i] = iLit;
|
|
}
|
|
else if ( Type == IFN_DSD_MUX )
|
|
{
|
|
assert( nFans == 3 );
|
|
pVarMap[i] = Gia_ManHashMux( pNew, pVarMap[pFans[0]], pVarMap[pFans[1]], pVarMap[pFans[2]] );
|
|
}
|
|
else if ( Type == IFN_DSD_PRIME )
|
|
{
|
|
int pFaninLits[16];
|
|
// collect truth table
|
|
word uTruth = 0;
|
|
int nMints = (1 << nFans);
|
|
for ( k = 0; k < nMints; k++ )
|
|
if ( Abc_TtGetBit(pConfigData, iVar++) )
|
|
uTruth |= ((word)1 << k);
|
|
uTruth = Abc_Tt6Stretch( uTruth, nFans );
|
|
// collect function
|
|
for ( k = 0; k < nFans; k++ )
|
|
pFaninLits[k] = pVarMap[pFans[k]];
|
|
// implement the function
|
|
nVarsNew = Abc_TtMinBase( &uTruth, pFaninLits, nFans, 6 );
|
|
if ( nVarsNew == 0 )
|
|
pVarMap[i] = (int)(uTruth & 1);
|
|
else
|
|
{
|
|
extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash );
|
|
Vec_Int_t Leaves = { nVarsNew, nVarsNew, pFaninLits };
|
|
pVarMap[i] = Kit_TruthToGia( pNew, (unsigned *)&uTruth, nVarsNew, vCover, &Leaves, 1 ); // hashing enabled!!!
|
|
}
|
|
}
|
|
else assert( 0 );
|
|
}
|
|
assert( iVar == nTtBits );
|
|
return Abc_LitNotCond( pVarMap[p->nObjs - 1], fCompl );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derive GIA using programmable bits.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void * If_ManDeriveGiaFromCells( void * pGia )
|
|
{
|
|
Gia_Man_t * p = (Gia_Man_t *)pGia;
|
|
Gia_Man_t * pNew, * pTemp;
|
|
Vec_Int_t * vCover, * vLeaves;
|
|
Ifn_Ntk_t * pNtkCell;
|
|
Gia_Obj_t * pObj;
|
|
word * pConfigData;
|
|
//word * pTruth;
|
|
int k, i, iLut, iVar;
|
|
int nConfigInts, Count = 0;
|
|
assert( p->vConfigs != NULL );
|
|
assert( p->pCellStr != NULL );
|
|
assert( Gia_ManHasMapping(p) );
|
|
// derive cell network
|
|
pNtkCell = Ifn_NtkParse( p->pCellStr );
|
|
Ifn_Prepare( pNtkCell, NULL, pNtkCell->nInps );
|
|
nConfigInts = Vec_IntEntry( p->vConfigs, 1 );
|
|
// create new manager
|
|
pNew = Gia_ManStart( 6*Gia_ManObjNum(p)/5 + 100 );
|
|
pNew->pName = Abc_UtilStrsav( p->pName );
|
|
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
|
|
// map primary inputs
|
|
Gia_ManFillValue(p);
|
|
Gia_ManConst0(p)->Value = 0;
|
|
Gia_ManForEachCi( p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
// iterate through nodes used in the mapping
|
|
vLeaves = Vec_IntAlloc( 16 );
|
|
vCover = Vec_IntAlloc( 1 << 16 );
|
|
Gia_ManHashStart( pNew );
|
|
//Gia_ObjComputeTruthTableStart( p, Gia_ManLutSizeMax(p) );
|
|
Gia_ManForEachAnd( p, pObj, iLut )
|
|
{
|
|
if ( Gia_ObjIsBuf(pObj) )
|
|
{
|
|
pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) );
|
|
continue;
|
|
}
|
|
if ( !Gia_ObjIsLut(p, iLut) )
|
|
continue;
|
|
// collect leaves
|
|
//Vec_IntClear( vLeaves );
|
|
//Gia_LutForEachFanin( p, iLut, iVar, k )
|
|
// Vec_IntPush( vLeaves, iVar );
|
|
//pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, iLut), vLeaves );
|
|
// collect incoming literals
|
|
Vec_IntClear( vLeaves );
|
|
Gia_LutForEachFanin( p, iLut, iVar, k )
|
|
Vec_IntPush( vLeaves, Gia_ManObj(p, iVar)->Value );
|
|
pConfigData = (word *)Vec_IntEntryP( p->vConfigs, 2 + nConfigInts * Count++ );
|
|
Gia_ManObj(p, iLut)->Value = If_ManSatDeriveGiaFromBits( pNew, pNtkCell, pConfigData, vLeaves, vCover );
|
|
}
|
|
assert( Vec_IntEntry(p->vConfigs, 0) == Count );
|
|
assert( Vec_IntSize(p->vConfigs) == 2 + nConfigInts * Count );
|
|
//Gia_ObjComputeTruthTableStop( p );
|
|
Gia_ManForEachCo( p, pObj, i )
|
|
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
|
Gia_ManHashStop( pNew );
|
|
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
|
|
Vec_IntFree( vLeaves );
|
|
Vec_IntFree( vCover );
|
|
ABC_FREE( pNtkCell );
|
|
// perform cleanup
|
|
pNew = Gia_ManCleanup( pTemp = pNew );
|
|
Gia_ManStop( pTemp );
|
|
return pNew;
|
|
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derive truth table given the configulation values.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
word * Ifn_NtkDeriveTruth( Ifn_Ntk_t * p, int * pValues )
|
|
{
|
|
int i, v, f, iVar, iStart;
|
|
// elementary variables
|
|
for ( i = 0; i < p->nInps; i++ )
|
|
{
|
|
// find variable
|
|
iStart = p->nParsVIni + i * p->nParsVNum;
|
|
for ( v = iVar = 0; v < p->nParsVNum; v++ )
|
|
if ( p->Values[iStart+v] )
|
|
iVar += (1 << v);
|
|
// assign variable
|
|
Abc_TtCopy( Ifn_ObjTruth(p, i), Ifn_ElemTruth(p, iVar), p->nWords, 0 );
|
|
}
|
|
// internal variables
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
{
|
|
int nFans = p->Nodes[i].nFanins;
|
|
int * pFans = p->Nodes[i].Fanins;
|
|
word * pTruth = Ifn_ObjTruth( p, i );
|
|
if ( p->Nodes[i].Type == IFN_DSD_AND )
|
|
{
|
|
Abc_TtFill( pTruth, p->nWords );
|
|
for ( f = 0; f < nFans; f++ )
|
|
Abc_TtAnd( pTruth, pTruth, Ifn_ObjTruth(p, pFans[f]), p->nWords, 0 );
|
|
}
|
|
else if ( p->Nodes[i].Type == IFN_DSD_XOR )
|
|
{
|
|
Abc_TtClear( pTruth, p->nWords );
|
|
for ( f = 0; f < nFans; f++ )
|
|
Abc_TtXor( pTruth, pTruth, Ifn_ObjTruth(p, pFans[f]), p->nWords, 0 );
|
|
}
|
|
else if ( p->Nodes[i].Type == IFN_DSD_MUX )
|
|
{
|
|
assert( nFans == 3 );
|
|
Abc_TtMux( pTruth, Ifn_ObjTruth(p, pFans[0]), Ifn_ObjTruth(p, pFans[1]), Ifn_ObjTruth(p, pFans[2]), p->nWords );
|
|
}
|
|
else if ( p->Nodes[i].Type == IFN_DSD_PRIME )
|
|
{
|
|
int nValues = (1 << nFans);
|
|
word * pTemp = Ifn_ObjTruth(p, p->nObjs);
|
|
Abc_TtClear( pTruth, p->nWords );
|
|
for ( v = 0; v < nValues; v++ )
|
|
{
|
|
if ( pValues[p->Nodes[i].iFirst + v] == 0 )
|
|
continue;
|
|
Abc_TtFill( pTemp, p->nWords );
|
|
for ( f = 0; f < nFans; f++ )
|
|
if ( (v >> f) & 1 )
|
|
Abc_TtAnd( pTemp, pTemp, Ifn_ObjTruth(p, pFans[f]), p->nWords, 0 );
|
|
else
|
|
Abc_TtSharp( pTemp, pTemp, Ifn_ObjTruth(p, pFans[f]), p->nWords );
|
|
Abc_TtOr( pTruth, pTruth, pTemp, p->nWords );
|
|
}
|
|
}
|
|
else assert( 0 );
|
|
//Dau_DsdPrintFromTruth( pTruth, p->nVars );
|
|
}
|
|
return Ifn_ObjTruth(p, p->nObjs-1);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Compute more or equal]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ifn_TtComparisonConstr( word * pTruth, int nVars, int fMore, int fEqual )
|
|
{
|
|
word Cond[4], Equa[4], Temp[4];
|
|
word s_TtElems[8][4] = {
|
|
{ ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA) },
|
|
{ ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC) },
|
|
{ ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0) },
|
|
{ ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00) },
|
|
{ ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000) },
|
|
{ ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000) },
|
|
{ ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF) },
|
|
{ ABC_CONST(0x0000000000000000),ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF),ABC_CONST(0xFFFFFFFFFFFFFFFF) }
|
|
};
|
|
int i, nWords = Abc_TtWordNum(2*nVars);
|
|
assert( nVars > 0 && nVars <= 4 );
|
|
Abc_TtClear( pTruth, nWords );
|
|
Abc_TtFill( Equa, nWords );
|
|
for ( i = nVars - 1; i >= 0; i-- )
|
|
{
|
|
if ( fMore )
|
|
Abc_TtSharp( Cond, s_TtElems[2*i+1], s_TtElems[2*i+0], nWords );
|
|
else
|
|
Abc_TtSharp( Cond, s_TtElems[2*i+0], s_TtElems[2*i+1], nWords );
|
|
Abc_TtAnd( Temp, Equa, Cond, nWords, 0 );
|
|
Abc_TtOr( pTruth, pTruth, Temp, nWords );
|
|
Abc_TtXor( Temp, s_TtElems[2*i+0], s_TtElems[2*i+1], nWords, 1 );
|
|
Abc_TtAnd( Equa, Equa, Temp, nWords, 0 );
|
|
}
|
|
if ( fEqual )
|
|
Abc_TtNot( pTruth, nWords );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Adds parameter constraints.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ifn_AddClause( sat_solver * pSat, int * pBeg, int * pEnd )
|
|
{
|
|
int fVerbose = 0;
|
|
int RetValue = sat_solver_addclause( pSat, pBeg, pEnd );
|
|
if ( fVerbose )
|
|
{
|
|
for ( ; pBeg < pEnd; pBeg++ )
|
|
printf( "%c%d ", Abc_LitIsCompl(*pBeg) ? '-':'+', Abc_Lit2Var(*pBeg) );
|
|
printf( "\n" );
|
|
}
|
|
return RetValue;
|
|
}
|
|
void Ifn_NtkAddConstrOne( sat_solver * pSat, Vec_Int_t * vCover, int * pVars, int nVars )
|
|
{
|
|
int RetValue, k, c, Cube, Literal, nLits, pLits[IFN_INS];
|
|
Vec_IntForEachEntry( vCover, Cube, c )
|
|
{
|
|
nLits = 0;
|
|
for ( k = 0; k < nVars; k++ )
|
|
{
|
|
Literal = 3 & (Cube >> (k << 1));
|
|
if ( Literal == 1 ) // '0' -> pos lit
|
|
pLits[nLits++] = Abc_Var2Lit(pVars[k], 0);
|
|
else if ( Literal == 2 ) // '1' -> neg lit
|
|
pLits[nLits++] = Abc_Var2Lit(pVars[k], 1);
|
|
else if ( Literal != 0 )
|
|
assert( 0 );
|
|
}
|
|
RetValue = Ifn_AddClause( pSat, pLits, pLits + nLits );
|
|
assert( RetValue );
|
|
}
|
|
}
|
|
void Ifn_NtkAddConstraints( Ifn_Ntk_t * p, sat_solver * pSat )
|
|
{
|
|
int fAddConstr = 1;
|
|
Vec_Int_t * vCover = Vec_IntAlloc( 0 );
|
|
word uTruth = Abc_Tt6Stretch( ~Abc_Tt6Mask(p->nVars), p->nParsVNum );
|
|
assert( p->nParsVNum <= 4 );
|
|
if ( uTruth )
|
|
{
|
|
int i, k, pVars[IFN_INS];
|
|
int RetValue = Kit_TruthIsop( (unsigned *)&uTruth, p->nParsVNum, vCover, 0 );
|
|
assert( RetValue == 0 );
|
|
// Dau_DsdPrintFromTruth( &uTruth, p->nParsVNum );
|
|
// add capacity constraints
|
|
for ( i = 0; i < p->nInps; i++ )
|
|
{
|
|
for ( k = 0; k < p->nParsVNum; k++ )
|
|
pVars[k] = p->nParsVIni + i * p->nParsVNum + k;
|
|
Ifn_NtkAddConstrOne( pSat, vCover, pVars, p->nParsVNum );
|
|
}
|
|
}
|
|
// ordering constraints
|
|
if ( fAddConstr && p->nConstr )
|
|
{
|
|
word pTruth[4];
|
|
int i, k, RetValue, pVars[2*IFN_INS];
|
|
int fForceDiff = (p->nVars == p->nInps);
|
|
Ifn_TtComparisonConstr( pTruth, p->nParsVNum, fForceDiff, fForceDiff );
|
|
RetValue = Kit_TruthIsop( (unsigned *)pTruth, 2*p->nParsVNum, vCover, 0 );
|
|
assert( RetValue == 0 );
|
|
// Kit_TruthIsopPrintCover( vCover, 2*p->nParsVNum, 0 );
|
|
for ( i = 0; i < p->nConstr; i++ )
|
|
{
|
|
int iVar1 = p->pConstr[i] >> 16;
|
|
int iVar2 = p->pConstr[i] & 0xFFFF;
|
|
for ( k = 0; k < p->nParsVNum; k++ )
|
|
{
|
|
pVars[2*k+0] = p->nParsVIni + iVar1 * p->nParsVNum + k;
|
|
pVars[2*k+1] = p->nParsVIni + iVar2 * p->nParsVNum + k;
|
|
}
|
|
Ifn_NtkAddConstrOne( pSat, vCover, pVars, 2*p->nParsVNum );
|
|
// printf( "added constraint with %d clauses for %d and %d\n", Vec_IntSize(vCover), iVar1, iVar2 );
|
|
}
|
|
}
|
|
Vec_IntFree( vCover );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Derive clauses given variable assignment.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ifn_NtkAddClauses( Ifn_Ntk_t * p, int * pValues, sat_solver * pSat )
|
|
{
|
|
int i, f, v, nLits, pLits[IFN_INS+2], pLits2[IFN_INS+2];
|
|
// assign new variables
|
|
int nSatVars = sat_solver_nvars(pSat);
|
|
// for ( i = 0; i < p->nObjs-1; i++ )
|
|
for ( i = 0; i < p->nObjs; i++ )
|
|
p->Nodes[i].Var = nSatVars++;
|
|
//p->Nodes[p->nObjs-1].Var = 0xFFFF;
|
|
sat_solver_setnvars( pSat, nSatVars );
|
|
// verify variable values
|
|
for ( i = 0; i < p->nVars; i++ )
|
|
assert( pValues[i] != -1 );
|
|
for ( i = p->nVars; i < p->nObjs-1; i++ )
|
|
assert( pValues[i] == -1 );
|
|
assert( pValues[p->nObjs-1] != -1 );
|
|
// internal variables
|
|
//printf( "\n" );
|
|
for ( i = 0; i < p->nInps; i++ )
|
|
{
|
|
int iParStart = p->nParsVIni + i * p->nParsVNum;
|
|
for ( v = 0; v < p->nVars; v++ )
|
|
{
|
|
// add output literal
|
|
pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, pValues[v]==0 );
|
|
// add clause literals
|
|
for ( f = 0; f < p->nParsVNum; f++ )
|
|
pLits[f+1] = Abc_Var2Lit( iParStart + f, (v >> f) & 1 );
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits+p->nParsVNum+1 ) )
|
|
return 0;
|
|
}
|
|
}
|
|
//printf( "\n" );
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
{
|
|
int nFans = p->Nodes[i].nFanins;
|
|
int * pFans = p->Nodes[i].Fanins;
|
|
if ( p->Nodes[i].Type == IFN_DSD_AND )
|
|
{
|
|
nLits = 0;
|
|
pLits[nLits++] = Abc_Var2Lit( p->Nodes[i].Var, 0 );
|
|
for ( f = 0; f < nFans; f++ )
|
|
{
|
|
pLits[nLits++] = Abc_Var2Lit( p->Nodes[pFans[f]].Var, 1 );
|
|
// add small clause
|
|
pLits2[0] = Abc_Var2Lit( p->Nodes[i].Var, 1 );
|
|
pLits2[1] = Abc_Var2Lit( p->Nodes[pFans[f]].Var, 0 );
|
|
if ( !Ifn_AddClause( pSat, pLits2, pLits2 + 2 ) )
|
|
return 0;
|
|
}
|
|
// add big clause
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits + nLits ) )
|
|
return 0;
|
|
}
|
|
else if ( p->Nodes[i].Type == IFN_DSD_XOR )
|
|
{
|
|
int m, nMints = (1 << (nFans+1));
|
|
for ( m = 0; m < nMints; m++ )
|
|
{
|
|
// skip even
|
|
int Count = 0;
|
|
for ( v = 0; v <= nFans; v++ )
|
|
Count += ((m >> v) & 1);
|
|
if ( (Count & 1) == 0 )
|
|
continue;
|
|
// generate minterm
|
|
pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, (m >> nFans) & 1 );
|
|
for ( v = 0; v < nFans; v++ )
|
|
pLits[v+1] = Abc_Var2Lit( p->Nodes[pFans[v]].Var, (m >> v) & 1 );
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits + nFans + 1 ) )
|
|
return 0;
|
|
}
|
|
}
|
|
else if ( p->Nodes[i].Type == IFN_DSD_MUX )
|
|
{
|
|
pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, 0 );
|
|
pLits[1] = Abc_Var2Lit( p->Nodes[pFans[0]].Var, 1 ); // ctrl
|
|
pLits[2] = Abc_Var2Lit( p->Nodes[pFans[1]].Var, 1 );
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits + 3 ) )
|
|
return 0;
|
|
|
|
pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, 1 );
|
|
pLits[1] = Abc_Var2Lit( p->Nodes[pFans[0]].Var, 1 ); // ctrl
|
|
pLits[2] = Abc_Var2Lit( p->Nodes[pFans[1]].Var, 0 );
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits + 3 ) )
|
|
return 0;
|
|
|
|
pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, 0 );
|
|
pLits[1] = Abc_Var2Lit( p->Nodes[pFans[0]].Var, 0 ); // ctrl
|
|
pLits[2] = Abc_Var2Lit( p->Nodes[pFans[2]].Var, 1 );
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits + 3 ) )
|
|
return 0;
|
|
|
|
pLits[0] = Abc_Var2Lit( p->Nodes[i].Var, 1 );
|
|
pLits[1] = Abc_Var2Lit( p->Nodes[pFans[0]].Var, 0 ); // ctrl
|
|
pLits[2] = Abc_Var2Lit( p->Nodes[pFans[2]].Var, 0 );
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits + 3 ) )
|
|
return 0;
|
|
}
|
|
else if ( p->Nodes[i].Type == IFN_DSD_PRIME )
|
|
{
|
|
int nValues = (1 << nFans);
|
|
int iParStart = p->Nodes[i].iFirst;
|
|
for ( v = 0; v < nValues; v++ )
|
|
{
|
|
nLits = 0;
|
|
if ( pValues[i] == -1 )
|
|
{
|
|
pLits[nLits] = Abc_Var2Lit( p->Nodes[i].Var, 0 );
|
|
pLits2[nLits] = Abc_Var2Lit( p->Nodes[i].Var, 1 );
|
|
nLits++;
|
|
}
|
|
for ( f = 0; f < nFans; f++, nLits++ )
|
|
pLits[nLits] = pLits2[nLits] = Abc_Var2Lit( p->Nodes[pFans[f]].Var, (v >> f) & 1 );
|
|
pLits[nLits] = Abc_Var2Lit( iParStart + v, 1 );
|
|
pLits2[nLits] = Abc_Var2Lit( iParStart + v, 0 );
|
|
nLits++;
|
|
if ( pValues[i] != 0 )
|
|
{
|
|
if ( !Ifn_AddClause( pSat, pLits2, pLits2 + nLits ) )
|
|
return 0;
|
|
}
|
|
if ( pValues[i] != 1 )
|
|
{
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits + nLits ) )
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
else assert( 0 );
|
|
//printf( "\n" );
|
|
}
|
|
// add last clause (not needed if the root node is IFN_DSD_PRIME)
|
|
pLits[0] = Abc_Var2Lit( p->Nodes[p->nObjs-1].Var, pValues[p->nObjs-1]==0 );
|
|
if ( !Ifn_AddClause( pSat, pLits, pLits + 1 ) )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Returns the minterm number for which there is a mismatch.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ifn_NtkMatchPrintStatus( sat_solver * p, int Iter, int status, int iMint, int Value, abctime clk )
|
|
{
|
|
printf( "Iter = %5d ", Iter );
|
|
printf( "Mint = %5d ", iMint );
|
|
printf( "Value = %2d ", Value );
|
|
printf( "Var = %6d ", sat_solver_nvars(p) );
|
|
printf( "Cla = %6d ", sat_solver_nclauses(p) );
|
|
printf( "Conf = %6d ", sat_solver_nconflicts(p) );
|
|
if ( status == l_False )
|
|
printf( "status = unsat" );
|
|
else if ( status == l_True )
|
|
printf( "status = sat " );
|
|
else
|
|
printf( "status = undec" );
|
|
Abc_PrintTime( 1, "Time", clk );
|
|
}
|
|
void Ifn_NtkMatchPrintConfig( Ifn_Ntk_t * p, sat_solver * pSat )
|
|
{
|
|
int v, i;
|
|
for ( v = p->nObjs; v < p->nPars; v++ )
|
|
{
|
|
for ( i = p->nInps; i < p->nObjs; i++ )
|
|
if ( p->Nodes[i].Type == IFN_DSD_PRIME && (int)p->Nodes[i].iFirst == v )
|
|
break;
|
|
if ( i < p->nObjs )
|
|
printf( " " );
|
|
else if ( v >= p->nParsVIni && (v - p->nParsVIni) % p->nParsVNum == 0 )
|
|
printf( " %d=", (v - p->nParsVIni) / p->nParsVNum );
|
|
printf( "%d", sat_solver_var_value(pSat, v) );
|
|
}
|
|
}
|
|
word Ifn_NtkMatchCollectPerm( Ifn_Ntk_t * p, sat_solver * pSat )
|
|
{
|
|
word Perm = 0;
|
|
int i, v, Mint;
|
|
assert( p->nParsVNum <= 4 );
|
|
for ( i = 0; i < p->nInps; i++ )
|
|
{
|
|
for ( Mint = v = 0; v < p->nParsVNum; v++ )
|
|
if ( sat_solver_var_value(pSat, p->nParsVIni + i * p->nParsVNum + v) )
|
|
Mint |= (1 << v);
|
|
Abc_TtSetHex( &Perm, i, Mint );
|
|
}
|
|
return Perm;
|
|
}
|
|
void Ifn_NtkMatchCollectConfig( Ifn_Ntk_t * p, sat_solver * pSat, word * pConfig )
|
|
{
|
|
int i, v, Mint;
|
|
assert( p->nParsVNum <= 4 );
|
|
for ( i = 0; i < p->nInps; i++ )
|
|
{
|
|
for ( Mint = v = 0; v < p->nParsVNum; v++ )
|
|
if ( sat_solver_var_value(pSat, p->nParsVIni + i * p->nParsVNum + v) )
|
|
Mint |= (1 << v);
|
|
Abc_TtSetHex( pConfig, i, Mint );
|
|
}
|
|
for ( v = p->nObjs; v < p->nParsVIni; v++ )
|
|
if ( sat_solver_var_value(pSat, v) )
|
|
Abc_TtSetBit( pConfig + 1, v - p->nObjs );
|
|
}
|
|
void Ifn_NtkMatchPrintPerm( word Perm, int nInps )
|
|
{
|
|
int i;
|
|
assert( nInps <= 16 );
|
|
for ( i = 0; i < nInps; i++ )
|
|
printf( "%c", 'a' + Abc_TtGetHex(&Perm, i) );
|
|
printf( "\n" );
|
|
}
|
|
int Ifn_NtkMatch( Ifn_Ntk_t * p, word * pTruth, int nVars, int nConfls, int fVerbose, int fVeryVerbose, word * pConfig )
|
|
{
|
|
word * pTruth1;
|
|
int RetValue = 0;
|
|
int nIterMax = (1<<nVars);
|
|
int i, v, status, iMint = 0;
|
|
abctime clk = Abc_Clock();
|
|
// abctime clkTru = 0, clkSat = 0, clk2;
|
|
sat_solver * pSat;
|
|
if ( nVars == 0 )
|
|
return 1;
|
|
pSat = sat_solver_new();
|
|
Ifn_Prepare( p, pTruth, nVars );
|
|
sat_solver_setnvars( pSat, p->nPars );
|
|
Ifn_NtkAddConstraints( p, pSat );
|
|
if ( fVeryVerbose )
|
|
Ifn_NtkMatchPrintStatus( pSat, 0, l_True, -1, -1, Abc_Clock() - clk );
|
|
if ( pConfig ) assert( *pConfig == 0 );
|
|
for ( i = 0; i < nIterMax; i++ )
|
|
{
|
|
// get variable assignment
|
|
for ( v = 0; v < p->nObjs; v++ )
|
|
p->Values[v] = v < p->nVars ? (iMint >> v) & 1 : -1;
|
|
p->Values[p->nObjs-1] = Abc_TtGetBit( pTruth, iMint );
|
|
// derive clauses
|
|
if ( !Ifn_NtkAddClauses( p, p->Values, pSat ) )
|
|
break;
|
|
// find assignment of parameters
|
|
// clk2 = Abc_Clock();
|
|
status = sat_solver_solve( pSat, NULL, NULL, nConfls, 0, 0, 0 );
|
|
// clkSat += Abc_Clock() - clk2;
|
|
if ( fVeryVerbose )
|
|
Ifn_NtkMatchPrintStatus( pSat, i+1, status, iMint, p->Values[p->nObjs-1], Abc_Clock() - clk );
|
|
if ( status != l_True )
|
|
break;
|
|
// collect assignment
|
|
for ( v = p->nObjs; v < p->nPars; v++ )
|
|
p->Values[v] = sat_solver_var_value(pSat, v);
|
|
// find truth table
|
|
// clk2 = Abc_Clock();
|
|
pTruth1 = Ifn_NtkDeriveTruth( p, p->Values );
|
|
// clkTru += Abc_Clock() - clk2;
|
|
Abc_TtXor( pTruth1, pTruth1, p->pTruth, p->nWords, 0 );
|
|
// find mismatch if present
|
|
iMint = Abc_TtFindFirstBit( pTruth1, p->nVars );
|
|
if ( iMint == -1 )
|
|
{
|
|
if ( pConfig )
|
|
Ifn_NtkMatchCollectConfig( p, pSat, pConfig );
|
|
/*
|
|
if ( pPerm )
|
|
{
|
|
int RetValue = Ifn_ManSatFindCofigBitsTest( p, pTruth, nVars, *pPerm );
|
|
Ifn_NtkMatchPrintPerm( *pPerm, p->nInps );
|
|
if ( RetValue == 0 )
|
|
printf( "Verification failed.\n" );
|
|
}
|
|
*/
|
|
RetValue = 1;
|
|
break;
|
|
}
|
|
}
|
|
assert( i < nIterMax );
|
|
if ( fVerbose )
|
|
{
|
|
printf( "%s Iter =%4d. Confl = %6d. ", RetValue ? "yes":"no ", i, sat_solver_nconflicts(pSat) );
|
|
if ( RetValue )
|
|
Ifn_NtkMatchPrintConfig( p, pSat );
|
|
printf( "\n" );
|
|
}
|
|
sat_solver_delete( pSat );
|
|
// Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
|
|
// Abc_PrintTime( 1, "Sat", clkSat );
|
|
// Abc_PrintTime( 1, "Tru", clkTru );
|
|
return RetValue;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ifn_NtkRead()
|
|
{
|
|
int RetValue;
|
|
int nVars = 8;
|
|
// word * pTruth = Dau_DsdToTruth( "(abcdefghi)", nVars );
|
|
word * pTruth = Dau_DsdToTruth( "1008{(1008{(ab)cde}f)ghi}", nVars );
|
|
// word * pTruth = Dau_DsdToTruth( "18{(1008{(ab)cde}f)gh}", nVars );
|
|
// word * pTruth = Dau_DsdToTruth( "1008{(1008{[ab]cde}f)ghi}", nVars );
|
|
// word * pTruth = Dau_DsdToTruth( "(abcd)", nVars );
|
|
// word * pTruth = Dau_DsdToTruth( "(abc)", nVars );
|
|
// word * pTruth = Dau_DsdToTruth( "18{(1008{(ab)cde}f)gh}", nVars );
|
|
// char * pStr = "e={abc};f={ed};";
|
|
// char * pStr = "d={ab};e={cd};";
|
|
// char * pStr = "j=(ab);k={jcde};l=(kf);m={lghi};";
|
|
// char * pStr = "i={abc};j={ide};k={ifg};l={jkh};";
|
|
// char * pStr = "h={abcde};i={abcdf};j=<ghi>;";
|
|
// char * pStr = "g=<abc>;h=<ade>;i={fgh};";
|
|
// char * pStr = "i=<abc>;j=(def);k=[gh];l={ijk};";
|
|
char * pStr = "{({(ab)cde}f)ghi};AB;CD;DE;GH;HI";
|
|
Ifn_Ntk_t * p = Ifn_NtkParse( pStr );
|
|
word Perm = 0;
|
|
if ( p == NULL )
|
|
return;
|
|
Ifn_NtkPrint( p );
|
|
Dau_DsdPrintFromTruth( pTruth, nVars );
|
|
// get the given function
|
|
RetValue = Ifn_NtkMatch( p, pTruth, nVars, 0, 1, 1, &Perm );
|
|
ABC_FREE( p );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|