blob: 353e7aae60e62e9ce1f8d05a71259958b6c08725 [file] [log] [blame]
/**CFile****************************************************************
FileName [covBuild.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Mapping into network of SOPs/ESOPs.]
Synopsis [Network construction procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: covBuild.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cov.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkCovDeriveCube( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, Min_Cube_t * pCube, Vec_Int_t * vSupp, int fCompl )
{
Vec_Int_t * vLits;
Abc_Obj_t * pNodeNew, * pFanin;
int i, iFanin, Lit;
// create empty cube
if ( pCube->nLits == 0 )
{
if ( fCompl )
return Abc_NtkCreateNodeConst0(pNtkNew);
return Abc_NtkCreateNodeConst1(pNtkNew);
}
// get the literals of this cube
vLits = Vec_IntAlloc( 10 );
Min_CubeGetLits( pCube, vLits );
assert( pCube->nLits == (unsigned)vLits->nSize );
// create special case when there is only one literal
if ( pCube->nLits == 1 )
{
iFanin = Vec_IntEntry(vLits,0);
pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) );
Lit = Min_CubeGetVar(pCube, iFanin);
assert( Lit == 1 || Lit == 2 );
Vec_IntFree( vLits );
if ( (Lit == 1) ^ fCompl )// negative
return Abc_NtkCreateNodeInv( pNtkNew, pFanin->pCopy );
return pFanin->pCopy;
}
assert( pCube->nLits > 1 );
// create the AND cube
pNodeNew = Abc_NtkCreateNode( pNtkNew );
for ( i = 0; i < vLits->nSize; i++ )
{
iFanin = Vec_IntEntry(vLits,i);
pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) );
Lit = Min_CubeGetVar(pCube, iFanin);
assert( Lit == 1 || Lit == 2 );
Vec_IntWriteEntry( vLits, i, Lit==1 );
Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
}
pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, vLits->pArray );
if ( fCompl )
Abc_SopComplement( (char *)pNodeNew->pData );
Vec_IntFree( vLits );
return pNodeNew;
}
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkCovDeriveNode_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int Level )
{
Min_Cube_t * pCover = NULL, * pCube;
Abc_Obj_t * pFaninNew, * pNodeNew, * pFanin;
Vec_Int_t * vSupp;
int Entry, nCubes, i;
if ( Abc_ObjIsCi(pObj) )
return pObj->pCopy;
assert( Abc_ObjIsNode(pObj) );
// skip if already computed
if ( pObj->pCopy )
return pObj->pCopy;
// get the support and the cover
vSupp = Abc_ObjGetSupp( pObj );
pCover = Abc_ObjGetCover2( pObj );
assert( vSupp );
/*
if ( pCover && pCover->nVars - Min_CoverSuppVarNum(p->pManMin, pCover) > 0 )
{
printf( "%d\n ", pCover->nVars - Min_CoverSuppVarNum(p->pManMin, pCover) );
Min_CoverWrite( stdout, pCover );
}
*/
/*
// print the support of this node
printf( "{ " );
Vec_IntForEachEntry( vSupp, Entry, i )
printf( "%d ", Entry );
printf( "} cubes = %d\n", Min_CoverCountCubes( pCover ) );
*/
// process the fanins
Vec_IntForEachEntry( vSupp, Entry, i )
{
pFanin = Abc_NtkObj(pObj->pNtk, Entry);
Abc_NtkCovDeriveNode_rec( p, pNtkNew, pFanin, Level+1 );
}
// for each cube, construct the node
nCubes = Min_CoverCountCubes( pCover );
if ( nCubes == 0 )
pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew);
else if ( nCubes == 1 )
pNodeNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCover, vSupp, 0 );
else
{
pNodeNew = Abc_NtkCreateNode( pNtkNew );
Min_CoverForEachCube( pCover, pCube )
{
pFaninNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCube, vSupp, 0 );
Abc_ObjAddFanin( pNodeNew, pFaninNew );
}
pNodeNew->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, nCubes );
}
/*
printf( "Created node %d(%d) at level %d: ", pNodeNew->Id, pObj->Id, Level );
Vec_IntForEachEntry( vSupp, Entry, i )
{
pFanin = Abc_NtkObj(pObj->pNtk, Entry);
printf( "%d(%d) ", pFanin->pCopy->Id, pFanin->Id );
}
printf( "\n" );
Min_CoverWrite( stdout, pCover );
*/
pObj->pCopy = pNodeNew;
return pNodeNew;
}
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkCovDerive( Cov_Man_t * p, Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj;
int i;
assert( Abc_NtkIsStrash(pNtk) );
// perform strashing
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
// reconstruct the network
Abc_NtkForEachCo( pNtk, pObj, i )
{
Abc_NtkCovDeriveNode_rec( p, pNtkNew, Abc_ObjFanin0(pObj), 0 );
// printf( "*** CO %s : %d -> %d \n", Abc_ObjName(pObj), pObj->pCopy->Id, Abc_ObjFanin0(pObj)->pCopy->Id );
}
// add the COs
Abc_NtkFinalize( pNtk, pNtkNew );
Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 );
// make sure everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
printf( "Abc_NtkCovDerive: The network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkCovDeriveInv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCompl )
{
assert( pObj->pCopy );
if ( !fCompl )
return pObj->pCopy;
if ( pObj->pCopy->pCopy == NULL )
pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
return pObj->pCopy->pCopy;
}
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkCovDeriveCubeInv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, Min_Cube_t * pCube, Vec_Int_t * vSupp )
{
Vec_Int_t * vLits;
Abc_Obj_t * pNodeNew, * pFanin;
int i, iFanin, Lit;
// create empty cube
if ( pCube->nLits == 0 )
return Abc_NtkCreateNodeConst1(pNtkNew);
// get the literals of this cube
vLits = Vec_IntAlloc( 10 );
Min_CubeGetLits( pCube, vLits );
assert( pCube->nLits == (unsigned)vLits->nSize );
// create special case when there is only one literal
if ( pCube->nLits == 1 )
{
iFanin = Vec_IntEntry(vLits,0);
pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) );
Lit = Min_CubeGetVar(pCube, iFanin);
assert( Lit == 1 || Lit == 2 );
Vec_IntFree( vLits );
// if ( Lit == 1 )// negative
// return Abc_NtkCreateNodeInv( pNtkNew, pFanin->pCopy );
// return pFanin->pCopy;
return Abc_NtkCovDeriveInv( pNtkNew, pFanin, Lit==1 );
}
assert( pCube->nLits > 1 );
// create the AND cube
pNodeNew = Abc_NtkCreateNode( pNtkNew );
for ( i = 0; i < vLits->nSize; i++ )
{
iFanin = Vec_IntEntry(vLits,i);
pFanin = Abc_NtkObj( pObj->pNtk, Vec_IntEntry(vSupp, iFanin) );
Lit = Min_CubeGetVar(pCube, iFanin);
assert( Lit == 1 || Lit == 2 );
Vec_IntWriteEntry( vLits, i, Lit==1 );
// Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
Abc_ObjAddFanin( pNodeNew, Abc_NtkCovDeriveInv( pNtkNew, pFanin, Lit==1 ) );
}
// pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, vLits->pArray );
pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, vLits->nSize, NULL );
Vec_IntFree( vLits );
return pNodeNew;
}
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkCovDeriveNodeInv_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCompl )
{
Min_Cube_t * pCover, * pCube;
Abc_Obj_t * pFaninNew, * pNodeNew, * pFanin;
Vec_Int_t * vSupp;
int Entry, nCubes, i;
// skip if already computed
if ( pObj->pCopy )
return Abc_NtkCovDeriveInv( pNtkNew, pObj, fCompl );
assert( Abc_ObjIsNode(pObj) );
// get the support and the cover
vSupp = Abc_ObjGetSupp( pObj );
pCover = Abc_ObjGetCover2( pObj );
assert( vSupp );
// process the fanins
Vec_IntForEachEntry( vSupp, Entry, i )
{
pFanin = Abc_NtkObj(pObj->pNtk, Entry);
Abc_NtkCovDeriveNodeInv_rec( p, pNtkNew, pFanin, 0 );
}
// for each cube, construct the node
nCubes = Min_CoverCountCubes( pCover );
if ( nCubes == 0 )
pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew);
else if ( nCubes == 1 )
pNodeNew = Abc_NtkCovDeriveCubeInv( pNtkNew, pObj, pCover, vSupp );
else
{
pNodeNew = Abc_NtkCreateNode( pNtkNew );
Min_CoverForEachCube( pCover, pCube )
{
pFaninNew = Abc_NtkCovDeriveCubeInv( pNtkNew, pObj, pCube, vSupp );
Abc_ObjAddFanin( pNodeNew, pFaninNew );
}
pNodeNew->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, nCubes );
}
pObj->pCopy = pNodeNew;
return Abc_NtkCovDeriveInv( pNtkNew, pObj, fCompl );
}
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description [The resulting network contains only pure AND/OR/EXOR gates
and inverters. This procedure is usedful to generate Verilog.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkCovDeriveClean( Cov_Man_t * p, Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pNodeNew;
int i;
assert( Abc_NtkIsStrash(pNtk) );
// perform strashing
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
// reconstruct the network
Abc_NtkForEachCo( pNtk, pObj, i )
{
pNodeNew = Abc_NtkCovDeriveNodeInv_rec( p, pNtkNew, Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) );
Abc_ObjAddFanin( pObj->pCopy, pNodeNew );
}
// add the COs
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
// make sure everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
printf( "Abc_NtkCovDeriveInv: The network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkCovDerive_rec( Cov_Man_t * p, Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
{
int fVerbose = 0;
Min_Cube_t * pCover, * pCovers[3];
Abc_Obj_t * pNodeNew, * pFanin;
Vec_Int_t * vSupp;
Vec_Str_t * vCover;
int i, Entry, nCubes, Type = 0;
// skip if already computed
if ( pObj->pCopy )
return pObj->pCopy;
assert( Abc_ObjIsNode(pObj) );
// get the support and the cover
vSupp = Abc_ObjGetSupp( pObj );
assert( vSupp );
// choose the cover to implement
pCovers[0] = Abc_ObjGetCover( pObj, 0 );
pCovers[1] = Abc_ObjGetCover( pObj, 1 );
pCovers[2] = Abc_ObjGetCover2( pObj );
// use positive polarity
if ( pCovers[0]
&& (!pCovers[1] || Min_CoverCountCubes(pCovers[0]) <= Min_CoverCountCubes(pCovers[1]))
&& (!pCovers[2] || Min_CoverCountCubes(pCovers[0]) <= Min_CoverCountCubes(pCovers[2])) )
{
pCover = pCovers[0];
Type = '1';
}
else
// use negative polarity
if ( pCovers[1]
&& (!pCovers[0] || Min_CoverCountCubes(pCovers[1]) <= Min_CoverCountCubes(pCovers[0]))
&& (!pCovers[2] || Min_CoverCountCubes(pCovers[1]) <= Min_CoverCountCubes(pCovers[2])) )
{
pCover = pCovers[1];
Type = '0';
}
else
// use XOR polarity
if ( pCovers[2]
&& (!pCovers[0] || Min_CoverCountCubes(pCovers[2]) < Min_CoverCountCubes(pCovers[0]))
&& (!pCovers[1] || Min_CoverCountCubes(pCovers[2]) < Min_CoverCountCubes(pCovers[1])) )
{
pCover = pCovers[2];
Type = 'x';
}
else
assert( 0 );
// print the support of this node
if ( fVerbose )
{
printf( "{ " );
Vec_IntForEachEntry( vSupp, Entry, i )
printf( "%d ", Entry );
printf( "} cubes = %d\n", Min_CoverCountCubes( pCover ) );
}
// process the fanins
Vec_IntForEachEntry( vSupp, Entry, i )
{
pFanin = Abc_NtkObj(pObj->pNtk, Entry);
Abc_NtkCovDerive_rec( p, pNtkNew, pFanin );
}
// for each cube, construct the node
nCubes = Min_CoverCountCubes( pCover );
if ( nCubes == 0 )
pNodeNew = Abc_NtkCreateNodeConst0(pNtkNew);
else if ( nCubes == 1 )
pNodeNew = Abc_NtkCovDeriveCube( pNtkNew, pObj, pCover, vSupp, Type == '0' );
else
{
// create the node
pNodeNew = Abc_NtkCreateNode( pNtkNew );
Vec_IntForEachEntry( vSupp, Entry, i )
{
pFanin = Abc_NtkObj(pObj->pNtk, Entry);
Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
}
// derive the function
vCover = Vec_StrAlloc( 100 );
Min_CoverCreate( vCover, pCover, (char)Type );
pNodeNew->pData = Abc_SopRegister((Mem_Flex_t *)pNtkNew->pManFunc, Vec_StrArray(vCover) );
Vec_StrFree( vCover );
}
/*
printf( "Created node %d(%d) at level %d: ", pNodeNew->Id, pObj->Id, Level );
Vec_IntForEachEntry( vSupp, Entry, i )
{
pFanin = Abc_NtkObj(pObj->pNtk, Entry);
printf( "%d(%d) ", pFanin->pCopy->Id, pFanin->Id );
}
printf( "\n" );
Min_CoverWrite( stdout, pCover );
*/
return pObj->pCopy = pNodeNew;
}
/**Function*************************************************************
Synopsis [Derives the decomposed network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkCovDeriveRegular( Cov_Man_t * p, Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pNodeNew;
int i;
assert( Abc_NtkIsStrash(pNtk) );
// perform strashing
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
// reconstruct the network
if ( Abc_ObjFanoutNum(Abc_AigConst1(pNtk)) > 0 )
Abc_AigConst1(pNtk)->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
Abc_NtkForEachCo( pNtk, pObj, i )
{
pNodeNew = Abc_NtkCovDerive_rec( p, pNtkNew, Abc_ObjFanin0(pObj) );
if ( Abc_ObjFaninC0(pObj) )
{
if ( pNodeNew->pData && Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 1 )
Abc_SopComplement( (char *)pNodeNew->pData );
else
pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew );
}
Abc_ObjAddFanin( pObj->pCopy, pNodeNew );
}
// add the COs
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
// make sure everything is okay
if ( !Abc_NtkCheck( pNtkNew ) )
{
printf( "Abc_NtkCovDerive: The network check has failed.\n" );
Abc_NtkDelete( pNtkNew );
return NULL;
}
return pNtkNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END