blob: 676617a18dfd75c967126b4daf29eedc59bdb9f9 [file] [log] [blame]
/**CFile****************************************************************
FileName [ioWritePla.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Command processing package.]
Synopsis [Procedures to write the network in BENCH format.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: ioWritePla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "ioAbc.h"
#ifdef ABC_USE_CUDD
#include "bdd/extrab/extraBdd.h"
#endif
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Writes the network in PLA format.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk )
{
ProgressBar * pProgress;
Abc_Obj_t * pNode, * pFanin, * pDriver;
char * pCubeIn, * pCubeOut, * pCube;
int i, k, nProducts, nInputs, nOutputs, nFanins;
nProducts = 0;
Abc_NtkForEachCo( pNtk, pNode, i )
{
pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) );
if ( !Abc_ObjIsNode(pDriver) )
{
nProducts++;
continue;
}
if ( Abc_NodeIsConst(pDriver) )
{
if ( Abc_NodeIsConst1(pDriver) )
nProducts++;
continue;
}
nProducts += Abc_SopGetCubeNum((char *)pDriver->pData);
}
// collect the parameters
nInputs = Abc_NtkCiNum(pNtk);
nOutputs = Abc_NtkCoNum(pNtk);
pCubeIn = ABC_ALLOC( char, nInputs + 1 );
pCubeOut = ABC_ALLOC( char, nOutputs + 1 );
memset( pCubeIn, '-', nInputs ); pCubeIn[nInputs] = 0;
memset( pCubeOut, '0', nOutputs ); pCubeOut[nOutputs] = 0;
// write the header
fprintf( pFile, ".i %d\n", nInputs );
fprintf( pFile, ".o %d\n", nOutputs );
fprintf( pFile, ".ilb" );
Abc_NtkForEachCi( pNtk, pNode, i )
fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pNode)) );
fprintf( pFile, "\n" );
fprintf( pFile, ".ob" );
Abc_NtkForEachCo( pNtk, pNode, i )
fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pNode)) );
fprintf( pFile, "\n" );
fprintf( pFile, ".p %d\n", nProducts );
// mark the CI nodes
Abc_NtkForEachCi( pNtk, pNode, i )
pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)i;
// write the cubes
pProgress = Extra_ProgressBarStart( stdout, nOutputs );
Abc_NtkForEachCo( pNtk, pNode, i )
{
// prepare the output cube
if ( i - 1 >= 0 )
pCubeOut[i-1] = '0';
pCubeOut[i] = '1';
// consider special cases of nodes
pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) );
if ( !Abc_ObjIsNode(pDriver) )
{
assert( Abc_ObjIsCi(pDriver) );
pCubeIn[(int)(ABC_PTRUINT_T)pDriver->pCopy] = '1' - Abc_ObjFaninC0(pNode);
fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
pCubeIn[(int)(ABC_PTRUINT_T)pDriver->pCopy] = '-';
continue;
}
if ( Abc_NodeIsConst(pDriver) )
{
if ( Abc_NodeIsConst1(pDriver) )
fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
continue;
}
// make sure the cover is not complemented
assert( !Abc_SopIsComplement( (char *)pDriver->pData ) );
// write the cubes
nFanins = Abc_ObjFaninNum(pDriver);
Abc_SopForEachCube( (char *)pDriver->pData, nFanins, pCube )
{
Abc_ObjForEachFanin( pDriver, pFanin, k )
{
pFanin = Abc_ObjFanin0Ntk(pFanin);
assert( (int)(ABC_PTRUINT_T)pFanin->pCopy < nInputs );
pCubeIn[(int)(ABC_PTRUINT_T)pFanin->pCopy] = pCube[k];
}
fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut );
}
// clean the cube for future writing
Abc_ObjForEachFanin( pDriver, pFanin, k )
{
pFanin = Abc_ObjFanin0Ntk(pFanin);
assert( Abc_ObjIsCi(pFanin) );
pCubeIn[(int)(ABC_PTRUINT_T)pFanin->pCopy] = '-';
}
Extra_ProgressBarUpdate( pProgress, i, NULL );
}
Extra_ProgressBarStop( pProgress );
fprintf( pFile, ".e\n" );
// clean the CI nodes
Abc_NtkForEachCi( pNtk, pNode, i )
pNode->pCopy = NULL;
ABC_FREE( pCubeIn );
ABC_FREE( pCubeOut );
return 1;
}
/**Function*************************************************************
Synopsis [Writes the network in PLA format.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName )
{
Abc_Ntk_t * pExdc;
FILE * pFile;
assert( Abc_NtkIsSopNetlist(pNtk) );
assert( Abc_NtkLevel(pNtk) == 1 );
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
{
fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" );
return 0;
}
fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
// write the network
Io_WritePlaOne( pFile, pNtk );
// write EXDC network if it exists
pExdc = Abc_NtkExdc( pNtk );
if ( pExdc )
printf( "Io_WritePla: EXDC is not written (warning).\n" );
// finalize the file
fclose( pFile );
return 1;
}
#ifdef ABC_USE_CUDD
/**Function*************************************************************
Synopsis [Writes the network in PLA format.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Io_WriteMoPlaOneInt( FILE * pFile, Abc_Ntk_t * pNtk, DdManager * dd, Vec_Ptr_t * vFuncs )
{
Abc_Obj_t * pNode;
DdNode * bOnset, * bOffset, * bCube, * bFunc, * bTemp, * zCover;
int i, k, nInputs, nOutputs;
int nCubes, fPhase;
assert( Vec_PtrSize(vFuncs) == Abc_NtkCoNum(pNtk) );
assert( dd->size == Abc_NtkCiNum(pNtk) );
assert( dd->size <= 1000 );
// collect the parameters
nInputs = Abc_NtkCiNum(pNtk);
nOutputs = Abc_NtkCoNum(pNtk);
assert( nOutputs > 1 );
// create extra variables
for ( i = 0; i < nOutputs; i++ )
Cudd_bddNewVarAtLevel( dd, i );
assert( dd->size == nInputs + nOutputs );
// create ON and OFF sets
bOnset = Cudd_ReadLogicZero( dd ); Cudd_Ref(bOnset);
bOffset = Cudd_ReadLogicZero( dd ); Cudd_Ref(bOffset);
for ( i = 0; i < nOutputs; i++ )
{
bFunc = (DdNode *)Vec_PtrEntry(vFuncs, i);
// create onset
bCube = Cudd_bddAnd( dd, Cudd_bddIthVar(dd, nInputs+i), bFunc ); Cudd_Ref(bCube);
for ( k = 0; k < nOutputs; k++ )
if ( k != i )
{
bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(Cudd_bddIthVar(dd, nInputs+k)) ); Cudd_Ref(bCube);
Cudd_RecursiveDeref( dd, bTemp );
}
bOnset = Cudd_bddOr( dd, bTemp = bOnset, bCube ); Cudd_Ref(bOnset);
Cudd_RecursiveDeref( dd, bTemp );
Cudd_RecursiveDeref( dd, bCube );
// create offset
bCube = Cudd_bddAnd( dd, Cudd_bddIthVar(dd, nInputs+i), Cudd_Not(bFunc) ); Cudd_Ref(bCube);
bOffset = Cudd_bddOr( dd, bTemp = bOffset, bCube ); Cudd_Ref(bOffset);
Cudd_RecursiveDeref( dd, bTemp );
Cudd_RecursiveDeref( dd, bCube );
printf( "Trying %d output.\n", i );
printf( "Onset = %d nodes.\n", Cudd_DagSize(bOnset) );
printf( "Offset = %d nodes.\n", Cudd_DagSize(bOffset) );
}
Cudd_zddVarsFromBddVars( dd, 2 );
// derive ISOP
{
extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover );
DdNode * bCover, * zCover0, * zCover1;
int nCubes0, nCubes1;
// get the ZDD of the negative polarity
bCover = Cudd_zddIsop( dd, bOffset, Cudd_Not(bOnset), &zCover0 );
Cudd_Ref( zCover0 );
Cudd_Ref( bCover );
Cudd_RecursiveDeref( dd, bCover );
nCubes0 = Abc_CountZddCubes( dd, zCover0 );
// get the ZDD of the positive polarity
bCover = Cudd_zddIsop( dd, bOnset, Cudd_Not(bOffset), &zCover1 );
Cudd_Ref( zCover1 );
Cudd_Ref( bCover );
Cudd_RecursiveDeref( dd, bCover );
nCubes1 = Abc_CountZddCubes( dd, zCover1 );
// compare the number of cubes
if ( nCubes1 <= nCubes0 )
{ // use positive polarity
nCubes = nCubes1;
zCover = zCover1;
Cudd_RecursiveDerefZdd( dd, zCover0 );
fPhase = 1;
}
else
{ // use negative polarity
nCubes = nCubes0;
zCover = zCover0;
Cudd_RecursiveDerefZdd( dd, zCover1 );
fPhase = 0;
}
}
Cudd_RecursiveDeref( dd, bOnset );
Cudd_RecursiveDeref( dd, bOffset );
Cudd_RecursiveDerefZdd( dd, zCover );
printf( "Cover = %d nodes.\n", Cudd_DagSize(zCover) );
printf( "ISOP = %d\n", nCubes );
// write the header
fprintf( pFile, ".i %d\n", nInputs );
fprintf( pFile, ".o %d\n", nOutputs );
fprintf( pFile, ".ilb" );
Abc_NtkForEachCi( pNtk, pNode, i )
fprintf( pFile, " %s", Abc_ObjName(pNode) );
fprintf( pFile, "\n" );
fprintf( pFile, ".ob" );
Abc_NtkForEachCo( pNtk, pNode, i )
fprintf( pFile, " %s", Abc_ObjName(pNode) );
fprintf( pFile, "\n" );
fprintf( pFile, ".p %d\n", nCubes );
fprintf( pFile, ".e\n" );
return 1;
}
/**Function*************************************************************
Synopsis [Writes the network in PLA format.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Io_WriteMoPlaOneIntMinterms( FILE * pFile, Abc_Ntk_t * pNtk, DdManager * dd, Vec_Ptr_t * vFuncs )
{
int pValues[1000];
Abc_Obj_t * pNode;
int i, k, nProducts, nInputs, nOutputs;
assert( Vec_PtrSize(vFuncs) == Abc_NtkCoNum(pNtk) );
assert( dd->size == Abc_NtkCiNum(pNtk) );
assert( dd->size <= 1000 );
// collect the parameters
nInputs = Abc_NtkCiNum(pNtk);
nOutputs = Abc_NtkCoNum(pNtk);
nProducts = (1 << nInputs);
// write the header
fprintf( pFile, ".i %d\n", nInputs );
fprintf( pFile, ".o %d\n", nOutputs );
fprintf( pFile, ".ilb" );
Abc_NtkForEachCi( pNtk, pNode, i )
fprintf( pFile, " %s", Abc_ObjName(pNode) );
fprintf( pFile, "\n" );
fprintf( pFile, ".ob" );
Abc_NtkForEachCo( pNtk, pNode, i )
fprintf( pFile, " %s", Abc_ObjName(pNode) );
fprintf( pFile, "\n" );
fprintf( pFile, ".p %d\n", nProducts );
// iterate through minterms
for ( k = 0; k < nProducts; k++ )
{
for ( i = 0; i < nInputs; i++ )
fprintf( pFile, "%c", '0' + (pValues[i] = ((k >> i) & 1)) );
fprintf( pFile, " " );
for ( i = 0; i < nOutputs; i++ )
fprintf( pFile, "%c", '0' + (Cudd_ReadOne(dd) == Cudd_Eval(dd, (DdNode *)Vec_PtrEntry(vFuncs, i), pValues)) );
fprintf( pFile, "\n" );
}
fprintf( pFile, ".e\n" );
return 1;
}
/**Function*************************************************************
Synopsis [Writes the network in PLA format.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Io_WriteMoPlaOne( FILE * pFile, Abc_Ntk_t * pNtk )
{
int fVerbose = 1;
DdManager * dd;
DdNode * bFunc;
Vec_Ptr_t * vFuncsGlob;
Abc_Obj_t * pObj;
int i;
assert( Abc_NtkIsStrash(pNtk) );
dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
if ( dd == NULL )
return 0;
if ( fVerbose )
printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
// complement the global functions
vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pObj, i )
Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) );
// consider minterms
Io_WriteMoPlaOneIntMinterms( pFile, pNtk, dd, vFuncsGlob );
Abc_NtkFreeGlobalBdds( pNtk, 0 );
// cleanup
Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i )
Cudd_RecursiveDeref( dd, bFunc );
Vec_PtrFree( vFuncsGlob );
Extra_StopManager( dd );
return 1;
}
/**Function*************************************************************
Synopsis [Writes the network in PLA format.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName )
{
FILE * pFile;
assert( Abc_NtkIsStrash(pNtk) );
if ( Abc_NtkCiNum(pNtk) > 16 )
{
printf( "Cannot write multi-output PLA for more than 16 inputs.\n" );
return 0;
}
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
{
fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" );
return 0;
}
fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() );
Io_WriteMoPlaOne( pFile, pNtk );
fclose( pFile );
return 1;
}
#else
int Io_WriteMoPla( Abc_Ntk_t * pNtk, char * pFileName ) { return 1; }
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END