Added Exorcism package, reading ESOP (read_pla -x file.esop) and deriving AIG (cubes -x; st).

This commit is contained in:
Alan Mishchenko 2016-04-11 21:42:00 -07:00
parent 2d1d315ece
commit 2d6a6f6654
16 changed files with 3921 additions and 33 deletions

View File

@ -954,6 +954,38 @@ SOURCE=.\src\base\cba\cbaWriteBlif.c
SOURCE=.\src\base\cba\cbaWriteVer.c
# End Source File
# End Group
# Begin Group "exor"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\base\exor\exor.c
# End Source File
# Begin Source File
SOURCE=.\src\base\exor\exor.h
# End Source File
# Begin Source File
SOURCE=.\src\base\exor\exorBits.c
# End Source File
# Begin Source File
SOURCE=.\src\base\exor\exorCubes.c
# End Source File
# Begin Source File
SOURCE=.\src\base\exor\exorLink.c
# End Source File
# Begin Source File
SOURCE=.\src\base\exor\exorList.c
# End Source File
# Begin Source File
SOURCE=.\src\base\exor\exorUtil.c
# End Source File
# End Group
# End Group
# Begin Group "bdd"

View File

@ -143,6 +143,33 @@ void Eso_ManCoverPrint( Eso_Man_t * p, Vec_Int_t * vEsop )
printf( "\n" );
Vec_StrFree( vStr );
}
Vec_Wec_t * Eso_ManCoverDerive( Eso_Man_t * p, Vec_Ptr_t * vCover )
{
Vec_Wec_t * vRes;
Vec_Int_t * vEsop, * vLevel; int i;
vRes = Vec_WecAlloc( Vec_VecSizeSize((Vec_Vec_t *)vCover) );
Vec_PtrForEachEntry( Vec_Int_t *, vCover, vEsop, i )
{
if ( Vec_IntSize(vEsop) > 0 )
{
int c, Cube;
Vec_IntForEachEntry( vEsop, Cube, c )
{
vLevel = Vec_WecPushLevel( vRes );
if ( Cube != p->Cube1 )
{
int k, Lit;
Vec_Int_t * vCube = Eso_ManCube( p, Cube );
Vec_IntForEachEntry( vCube, Lit, k )
Vec_IntPush( vLevel, Lit );
}
Vec_IntPush( vLevel, -i-1 );
}
}
}
assert( Vec_WecSize(vRes) == Vec_WecCap(vRes) );
return vRes;
}
Gia_Man_t * Eso_ManCoverConvert( Eso_Man_t * p, Vec_Ptr_t * vCover )
{
Vec_Int_t * vEsop;
@ -459,14 +486,15 @@ Vec_Int_t * Eso_ManTransformOne( Eso_Man_t * p, Vec_Int_t * vEsop, int fCompl, V
SeeAlso []
***********************************************************************/
Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose )
Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes )
{
abctime clk = Abc_Clock();
Vec_Ptr_t * vCover;
Gia_Man_t * pNew;
Gia_Obj_t * pObj; int i, nCubes = 0, nCubesUsed = 0;
Gia_Man_t * pNew = NULL;
Gia_Obj_t * pObj;
int i, nCubes = 0, nCubesUsed = 0;
Vec_Int_t * vEsop1, * vEsop2, * vEsop;
Eso_Man_t * p = Eso_ManAlloc( pGia );
Eso_Man_t * p = Eso_ManAlloc( pGia );
Gia_ManForEachAnd( pGia, pObj, i )
{
vEsop1 = Vec_WecEntry( p->vEsops, Gia_ObjFaninId0(pObj, i) );
@ -482,16 +510,23 @@ Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose )
{
vEsop1 = Vec_WecEntry( p->vEsops, Gia_ObjFaninId0p(pGia, pObj) );
vEsop1 = Eso_ManTransformOne( p, vEsop1, Gia_ObjFaninC0(pObj), p->vCube1 );
printf( "Output %3d: ESOP has %5d cubes\n", i, Vec_IntSize(vEsop1) );
if ( fVerbose )
Eso_ManCoverPrint( p, vEsop1 );
printf( "Output %3d: ESOP has %5d cubes\n", i, Vec_IntSize(vEsop1) );
// if ( fVerbose )
// Eso_ManCoverPrint( p, vEsop1 );
Vec_PtrPush( vCover, Vec_IntDup(vEsop1) );
nCubesUsed += Vec_IntSize(vEsop1);
}
printf( "Outs = %d. Cubes = %d. Used = %d. Hashed = %d. ",
Gia_ManCoNum(pGia), nCubes, nCubesUsed, Hsh_VecSize(p->pHash) );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
pNew = Eso_ManCoverConvert( p, vCover );
if ( fVerbose )
{
printf( "Outs = %d. Cubes = %d. Used = %d. Hashed = %d. ",
Gia_ManCoNum(pGia), nCubes, nCubesUsed, Hsh_VecSize(p->pHash) );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
if ( pvRes )
*pvRes = Eso_ManCoverDerive( p, vCover );
else
pNew = Eso_ManCoverConvert( p, vCover );
Vec_VecFree( (Vec_Vec_t *)vCover );
Eso_ManStop( p );
return pNew;

View File

@ -2501,7 +2501,7 @@ float Abc_NtkComputeDelay( Abc_Ntk_t * pNtk )
SeeAlso []
***********************************************************************/
void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, int fXor )
{
Abc_Obj_t * pNodeOr, * pNodeNew, * pFanin;
char * pCube, * pSop = (char *)pNodeOld->pData;
@ -2517,7 +2517,10 @@ void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
}
// add the OR gate
pNodeOr = Abc_NtkCreateNode( pNtkNew );
pNodeOr->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop), NULL );
if ( fXor )
pNodeOr->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop) );
else
pNodeOr->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop), NULL );
// check the logic function of the node
Abc_SopForEachCube( pSop, nVars, pCube )
{
@ -2525,6 +2528,12 @@ void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
Abc_CubeForEachVar( pCube, Value, v )
if ( Value == '0' || Value == '1' )
nFanins++;
if ( nFanins == 0 ) // const1 cube in ESOP
{
pNodeNew = Abc_NtkCreateNodeConst1( pNtkNew );
Abc_ObjAddFanin( pNodeOr, pNodeNew );
continue;
}
assert( nFanins > 0 );
// create node
pNodeNew = Abc_NtkCreateNode( pNtkNew );
@ -2548,7 +2557,7 @@ void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew )
assert( pNodeOld->pCopy == NULL );
pNodeOld->pCopy = pNodeOr;
}
Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk )
Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk, int fXor )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pNode;
@ -2560,7 +2569,7 @@ Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk )
// perform conversion in the topological order
vNodes = Abc_NtkDfs( pNtk, 0 );
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
Abc_NodeSopToCubes( pNode, pNtkNew );
Abc_NodeSopToCubes( pNode, pNtkNew, fXor );
Vec_PtrFree( vNodes );
// make sure everything is okay
Abc_NtkFinalize( pNtk, pNtkNew );

View File

@ -465,6 +465,7 @@ static int Abc_CommandAbc9PoXsim ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandAbc9Demiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Fadds ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Esop ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Exorcism ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Mfs ( Abc_Frame_t * pAbc, int argc, char ** argv );
//static int Abc_CommandAbc9PoPart2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
//static int Abc_CommandAbc9CexCut ( Abc_Frame_t * pAbc, int argc, char ** argv );
@ -1092,6 +1093,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "ABC9", "&demiter", Abc_CommandAbc9Demiter, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&fadds", Abc_CommandAbc9Fadds, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&esop", Abc_CommandAbc9Esop, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&exorcism", Abc_CommandAbc9Exorcism, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&mfs", Abc_CommandAbc9Mfs, 0 );
// Cmd_CommandAdd( pAbc, "ABC9", "&popart2", Abc_CommandAbc9PoPart2, 0 );
// Cmd_CommandAdd( pAbc, "ABC9", "&cexcut", Abc_CommandAbc9CexCut, 0 );
@ -8826,17 +8828,20 @@ usage:
***********************************************************************/
int Abc_CommandCubes( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk, int fXor );
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
int c, fXor = 0;
pNtk = Abc_FrameReadNtk(pAbc);
// set defaults
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF )
{
switch ( c )
{
case 'x':
fXor ^= 1;
break;
case 'h':
goto usage;
default:
@ -8857,7 +8862,7 @@ int Abc_CommandCubes( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
pNtkRes = Abc_NtkSopToCubes( pNtk );
pNtkRes = Abc_NtkSopToCubes( pNtk, fXor );
if ( pNtkRes == NULL )
{
Abc_Print( -1, "Converting to cubes has failed.\n" );
@ -8868,9 +8873,10 @@ int Abc_CommandCubes( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
Abc_Print( -2, "usage: cubes [-h]\n" );
Abc_Print( -2, "usage: cubes [-xh]\n" );
Abc_Print( -2, "\t converts the current network into a network derived by creating\n" );
Abc_Print( -2, "\t a separate node for each product and sum in the local SOPs\n" );
Abc_Print( -2, "\t-v : toggle using XOR instead of OR [default = %s]\n", fXor? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
@ -39186,7 +39192,7 @@ usage:
***********************************************************************/
int Abc_CommandAbc9Esop( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose );
extern Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes );
Gia_Man_t * pTemp;
int c, fVerbose = 0;
Extra_UtilGetoptReset();
@ -39208,7 +39214,7 @@ int Abc_CommandAbc9Esop( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Print( -1, "Abc_CommandAbc9Esop(): There is no AIG.\n" );
return 0;
}
pTemp = Eso_ManCompute( pAbc->pGia, fVerbose );
pTemp = Eso_ManCompute( pAbc->pGia, fVerbose, NULL );
Abc_FrameUpdateGia( pAbc, pTemp );
return 0;
@ -39220,6 +39226,86 @@ usage:
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandAbc9Exorcism( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern int Abc_ExorcismMain( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOut, int Quality, int Verbosity );
extern Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes );
Vec_Wec_t * vEsop = NULL;
char * pFileNameOut = NULL;
int c, Quality = 2, Verbosity = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "QVvh" ) ) != EOF )
{
switch ( c )
{
case 'Q':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" );
goto usage;
}
Quality = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( Quality < 0 )
goto usage;
break;
case 'V':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" );
goto usage;
}
Verbosity = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( Verbosity < 0 )
goto usage;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( pAbc->pGia == NULL )
{
Abc_Print( -1, "Abc_CommandAbc9Exorcism(): There is no AIG.\n" );
return 0;
}
// get the output file name
if ( argc == globalUtilOptind + 1 )
pFileNameOut = argv[globalUtilOptind];
// generate starting cover and run minimization
Eso_ManCompute( pAbc->pGia, fVerbose, &vEsop );
Abc_ExorcismMain( vEsop, Gia_ManCiNum(pAbc->pGia), Gia_ManCoNum(pAbc->pGia), pFileNameOut, Quality, Verbosity );
Vec_WecFree( vEsop );
return 0;
usage:
Abc_Print( -2, "usage: &exorcism [-Q N] [-V N] <file>\n" );
Abc_Print( -2, " performs heuristic exclusive sum-of-project minimization\n" );
Abc_Print( -2, " -Q N : minimization quality [default = 0]\n");
Abc_Print( -2, " increasing this number improves quality and adds to runtime\n");
Abc_Print( -2, " -Q N : verbosity level [default = 0]\n");
Abc_Print( -2, " 0 = no output; 1 = outline; 2 = verbose\n");
Abc_Print( -2, " <file>: the output file name in ESOP-PLA format\n");
Abc_Print( -2, "\n" );
return 1;
}
/**Function*************************************************************
Synopsis []

832
src/base/exor/exor.c Normal file
View File

@ -0,0 +1,832 @@
/**CFile****************************************************************
FileName [exor.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Exclusive sum-of-product minimization.]
Synopsis [Main procedure.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: exor.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// ///
/// Implementation of EXORCISM - 4 ///
/// An Exclusive Sum-of-Product Minimizer ///
/// Alan Mishchenko <alanmi@ee.pdx.edu> ///
/// ///
////////////////////////////////////////////////////////////////////////
/// ///
/// Main Module ///
/// ESOP Minimization Task Coordinator ///
/// ///
/// 1) interprets command line ///
/// 2) calls the approapriate reading procedure ///
/// 3) calls the minimization module ///
/// ///
/// Ver. 1.0. Started - July 18, 2000. Last update - July 20, 2000 ///
/// Ver. 1.1. Started - July 24, 2000. Last update - July 29, 2000 ///
/// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 26, 2000 ///
/// Ver. 1.6. Started - Sep 11, 2000. Last update - Sep 15, 2000 ///
/// Ver. 1.7. Started - Sep 20, 2000. Last update - Sep 23, 2000 ///
/// ///
////////////////////////////////////////////////////////////////////////
/// This software was tested with the BDD package "CUDD", v.2.3.0 ///
/// by Fabio Somenzi ///
/// http://vlsi.colorado.edu/~fabio/ ///
////////////////////////////////////////////////////////////////////////
#include "exor.h"
ABC_NAMESPACE_IMPL_START
///////////////////////////////////////////////////////////////////////
/// GLOBAL VARIABLES ///
////////////////////////////////////////////////////////////////////////
// information about the cube cover
cinfo g_CoverInfo;
extern int s_fDecreaseLiterals;
////////////////////////////////////////////////////////////////////////
/// EXTERNAL FUNCTIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION main() ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int ReduceEsopCover()
{
///////////////////////////////////////////////////////////////
// SIMPLIFICATION
////////////////////////////////////////////////////////////////////
long clk1 = clock();
int nIterWithoutImprovement = 0;
int nIterCount = 0;
int GainTotal;
int z;
do
{
//START:
if ( g_CoverInfo.Verbosity == 2 )
printf( "\nITERATION #%d\n\n", ++nIterCount );
else if ( g_CoverInfo.Verbosity == 1 )
printf( "." );
GainTotal = 0;
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
if ( nIterWithoutImprovement > (int)(g_CoverInfo.Quality>0) )
{
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|0 );
}
if ( GainTotal )
nIterWithoutImprovement = 0;
else
nIterWithoutImprovement++;
// if ( g_CoverInfo.Quality >= 2 && nIterWithoutImprovement == 2 )
// s_fDecreaseLiterals = 1;
}
while ( nIterWithoutImprovement < 1 + g_CoverInfo.Quality );
// improve the literal count
s_fDecreaseLiterals = 1;
for ( z = 0; z < 1; z++ )
{
if ( g_CoverInfo.Verbosity == 2 )
printf( "\nITERATION #%d\n\n", ++nIterCount );
else if ( g_CoverInfo.Verbosity == 1 )
printf( "." );
GainTotal = 0;
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
// if ( GainTotal )
// {
// nIterWithoutImprovement = 0;
// goto START;
// }
}
/* ////////////////////////////////////////////////////////////////////
// Print statistics
printf( "\nShallow simplification time is ";
cout << (float)(clk2 - clk1)/(float)(CLOCKS_PER_SEC) << " sec\n" );
printf( "Deep simplification time is ";
cout << (float)(clock() - clk2)/(float)(CLOCKS_PER_SEC) << " sec\n" );
printf( "Cover after iterative simplification = " << s_nCubesInUse << endl;
printf( "Reduced by initial cube writing = " << g_CoverInfo.nCubesBefore-nCubesAfterWriting << endl;
printf( "Reduced by shallow simplification = " << nCubesAfterWriting-nCubesAfterShallow << endl;
printf( "Reduced by deep simplification = " << nCubesAfterWriting-s_nCubesInUse << endl;
// printf( "\nThe total number of cubes created = " << g_CoverInfo.cIDs << endl;
// printf( "Total number of places in a queque = " << s_nPosAlloc << endl;
// printf( "Minimum free places in queque-2 = " << s_nPosMax[0] << endl;
// printf( "Minimum free places in queque-3 = " << s_nPosMax[1] << endl;
// printf( "Minimum free places in queque-4 = " << s_nPosMax[2] << endl;
*/ ////////////////////////////////////////////////////////////////////
// write the number of cubes into cover information
assert ( g_CoverInfo.nCubesInUse + g_CoverInfo.nCubesFree == g_CoverInfo.nCubesAlloc );
// printf( "\nThe output cover is\n" );
// PrintCoverDebug( cout );
return 0;
}
//////////////////////////////////////////////////////////////////
// quite a good script
//////////////////////////////////////////////////////////////////
/*
long clk1 = clock();
int nIterWithoutImprovement = 0;
do
{
PrintQuequeStats();
GainTotal = 0;
GainTotal += IterativelyApplyExorLink( DIST2, 0|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 0|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
if ( nIterWithoutImprovement > 2 )
{
GainTotal += IterativelyApplyExorLink( DIST2, 0|0|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 0|2|4 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 );
}
if ( nIterWithoutImprovement > 6 )
{
GainTotal += IterativelyApplyExorLink( DIST2, 0|0|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 0|0|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 0|0|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 );
}
if ( GainTotal )
nIterWithoutImprovement = 0;
else
nIterWithoutImprovement++;
}
while ( nIterWithoutImprovement < 12 );
nCubesAfterShallow = s_nCubesInUse;
*/
/*
// alu4 - 439
long clk1 = clock();
int nIterWithoutImprovement = 0;
do
{
PrintQuequeStats();
GainTotal = 0;
GainTotal += IterativelyApplyExorLink( DIST2, 1|0|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
if ( nIterWithoutImprovement > 2 )
{
GainTotal += IterativelyApplyExorLink( DIST2, 0|0|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 0|2|4 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 );
}
if ( nIterWithoutImprovement > 6 )
{
GainTotal += IterativelyApplyExorLink( DIST2, 0|0|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 0|0|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 0|0|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 );
}
if ( GainTotal )
nIterWithoutImprovement = 0;
else
nIterWithoutImprovement++;
}
while ( nIterWithoutImprovement < 12 );
*/
/*
// alu4 - 412 cubes, 700 sec
long clk1 = clock();
int nIterWithoutImprovement = 0;
int nIterCount = 0;
do
{
printf( "\nITERATION #" << ++nIterCount << endl << endl;
GainTotal = 0;
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
if ( nIterWithoutImprovement > 3 )
{
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
}
if ( nIterWithoutImprovement > 7 )
{
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
}
if ( GainTotal )
nIterWithoutImprovement = 0;
else
nIterWithoutImprovement++;
}
while ( nIterWithoutImprovement < 12 );
*/
/*
// pretty good script
// alu4 = 424 in 250 sec
long clk1 = clock();
int nIterWithoutImprovement = 0;
int nIterCount = 0;
do
{
printf( "\nITERATION #" << ++nIterCount << " |";
for ( int k = 0; k < nIterWithoutImprovement; k++ )
printf( "*";
for ( ; k < 11; k++ )
printf( "_";
printf( "|" << endl << endl;
GainTotal = 0;
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
if ( nIterWithoutImprovement > 2 )
{
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
}
if ( nIterWithoutImprovement > 4 )
{
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
}
if ( GainTotal )
nIterWithoutImprovement = 0;
else
nIterWithoutImprovement++;
}
while ( nIterWithoutImprovement < 7 );
*/
/*
alu4 = 435 70 secs
long clk1 = clock();
int nIterWithoutImprovement = 0;
int nIterCount = 0;
do
{
printf( "\nITERATION #" << ++nIterCount << endl << endl;
GainTotal = 0;
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
if ( GainTotal )
nIterWithoutImprovement = 0;
else
nIterWithoutImprovement++;
}
while ( nIterWithoutImprovement < 4 );
*/
/*
// the best previous
long clk1 = clock();
int nIterWithoutImprovement = 0;
int nIterCount = 0;
int GainTotal;
do
{
if ( g_CoverInfo.Verbosity == 2 )
printf( "\nITERATION #" << ++nIterCount << endl << endl;
else if ( g_CoverInfo.Verbosity == 1 )
cout << '.';
GainTotal = 0;
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
if ( nIterWithoutImprovement > 1 )
{
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|0 );
GainTotal += IterativelyApplyExorLink( DIST3, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST2, 1|2|4 );
GainTotal += IterativelyApplyExorLink( DIST4, 1|2|0 );
}
if ( GainTotal )
nIterWithoutImprovement = 0;
else
nIterWithoutImprovement++;
}
// while ( nIterWithoutImprovement < 20 );
// while ( nIterWithoutImprovement < 7 );
while ( nIterWithoutImprovement < 1 + g_CoverInfo.Quality );
*/
/*
// the last tried
long clk1 = clock();
int nIterWithoutImprovement = 0;
int nIterCount = 0;
int GainTotal;
do
{
if ( g_CoverInfo.Verbosity == 2 )
printf( "\nITERATION #" << ++nIterCount << endl << endl;
else if ( g_CoverInfo.Verbosity == 1 )
cout << '.';
GainTotal = 0;
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
if ( nIterWithoutImprovement > (int)(g_CoverInfo.Quality>0) )
{
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|0 );
GainTotal += IterativelyApplyExorLink2( 1|2|0 );
GainTotal += IterativelyApplyExorLink3( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|4 );
GainTotal += IterativelyApplyExorLink2( 1|2|4 );
GainTotal += IterativelyApplyExorLink4( 1|2|0 );
}
if ( GainTotal )
nIterWithoutImprovement = 0;
else
nIterWithoutImprovement++;
}
while ( nIterWithoutImprovement < 1 + g_CoverInfo.Quality );
*/
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void AddCubesToStartingCover( Vec_Wec_t * vEsop )
{
Vec_Int_t * vCube;
Cube * pNew;
int * s_Level2Var;
int * s_LevelValues;
int c, i, k, Lit, Out;
s_Level2Var = ABC_ALLOC( int, g_CoverInfo.nVarsIn );
s_LevelValues = ABC_ALLOC( int, g_CoverInfo.nVarsIn );
for ( i = 0; i < g_CoverInfo.nVarsIn; i++ )
s_Level2Var[i] = i;
g_CoverInfo.nLiteralsBefore = 0;
Vec_WecForEachLevel( vEsop, vCube, c )
{
// get the output of this cube
Out = -Vec_IntPop(vCube) - 1;
// fill in the cube with blanks
for ( i = 0; i < g_CoverInfo.nVarsIn; i++ )
s_LevelValues[i] = VAR_ABS;
Vec_IntForEachEntry( vCube, Lit, k )
{
if ( Abc_LitIsCompl(Lit) )
s_LevelValues[Abc_Lit2Var(Lit)] = VAR_NEG;
else
s_LevelValues[Abc_Lit2Var(Lit)] = VAR_POS;
}
// get the new cube
pNew = GetFreeCube();
// consider the need to clear the cube
if ( pNew->pCubeDataIn[0] ) // this is a recycled cube
{
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
pNew->pCubeDataIn[i] = 0;
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
pNew->pCubeDataOut[i] = 0;
}
InsertVarsWithoutClearing( pNew, s_Level2Var, g_CoverInfo.nVarsIn, s_LevelValues, Out );
// set literal counts
pNew->a = Vec_IntSize(vCube);
pNew->z = 1;
// set the ID
pNew->ID = g_CoverInfo.cIDs++;
// skip through zero-ID
if ( g_CoverInfo.cIDs == 256 )
g_CoverInfo.cIDs = 1;
// add this cube to storage
CheckForCloseCubes( pNew, 1 );
g_CoverInfo.nLiteralsBefore += Vec_IntSize(vCube);
}
ABC_FREE( s_Level2Var );
ABC_FREE( s_LevelValues );
assert ( g_CoverInfo.nCubesInUse + g_CoverInfo.nCubesFree == g_CoverInfo.nCubesAlloc );
}
/**Function*************************************************************
Synopsis [Performs heuristic minimization of ESOPs.]
Description [Returns 1 on success, 0 on failure.]
SideEffects []
SeeAlso []
***********************************************************************/
int Exorcism( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOut )
{
long clk1;
int RemainderBits;
int TotalWords;
int MemTemp, MemTotal;
///////////////////////////////////////////////////////////////////////
// STEPS of HEURISTIC ESOP MINIMIZATION
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// STEP 1: determine the size of the starting cover
///////////////////////////////////////////////////////////////////////
assert( nIns > 0 );
// inputs
RemainderBits = (nIns*2)%(sizeof(unsigned)*8);
TotalWords = (nIns*2)/(sizeof(unsigned)*8) + (RemainderBits > 0);
g_CoverInfo.nVarsIn = nIns;
g_CoverInfo.nWordsIn = TotalWords;
// outputs
RemainderBits = (nOuts)%(sizeof(unsigned)*8);
TotalWords = (nOuts)/(sizeof(unsigned)*8) + (RemainderBits > 0);
g_CoverInfo.nVarsOut = nOuts;
g_CoverInfo.nWordsOut = TotalWords;
g_CoverInfo.cIDs = 1;
// cubes
clk1 = clock();
// g_CoverInfo.nCubesBefore = CountTermsInPseudoKroneckerCover( g_Func.dd, nOuts );
g_CoverInfo.nCubesBefore = Vec_WecSize(vEsop);
g_CoverInfo.TimeStart = clock() - clk1;
if ( g_CoverInfo.Verbosity )
{
printf( "Starting cover generation time is %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeStart) );
printf( "The number of cubes in the starting cover is %d\n", g_CoverInfo.nCubesBefore );
}
if ( g_CoverInfo.nCubesBefore > 20000 )
{
printf( "\nThe size of the starting cover is more than 20000 cubes. Quitting...\n" );
return 0;
}
///////////////////////////////////////////////////////////////////////
// STEP 2: prepare internal data structures
///////////////////////////////////////////////////////////////////////
g_CoverInfo.nCubesAlloc = g_CoverInfo.nCubesBefore + ADDITIONAL_CUBES;
// allocate cube cover
MemTotal = 0;
MemTemp = AllocateCover( g_CoverInfo.nCubesAlloc, g_CoverInfo.nWordsIn, g_CoverInfo.nWordsOut );
if ( MemTemp == 0 )
{
printf( "Unexpected memory allocation problem. Quitting...\n" );
return 0;
}
else
MemTotal += MemTemp;
// allocate cube sets
MemTemp = AllocateCubeSets( g_CoverInfo.nVarsIn, g_CoverInfo.nVarsOut );
if ( MemTemp == 0 )
{
printf( "Unexpected memory allocation problem. Quitting...\n" );
return 0;
}
else
MemTotal += MemTemp;
// allocate adjacency queques
MemTemp = AllocateQueques( g_CoverInfo.nCubesAlloc*g_CoverInfo.nCubesAlloc/CUBE_PAIR_FACTOR );
if ( MemTemp == 0 )
{
printf( "Unexpected memory allocation problem. Quitting...\n" );
return 0;
}
else
MemTotal += MemTemp;
if ( g_CoverInfo.Verbosity )
printf( "Dynamically allocated memory is %dK\n", MemTotal/1000 );
///////////////////////////////////////////////////////////////////////
// STEP 3: write the cube cover into the allocated storage
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
clk1 = clock();
if ( g_CoverInfo.Verbosity )
printf( "Generating the starting cover...\n" );
AddCubesToStartingCover( vEsop );
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// STEP 4: iteratively improve the cover
///////////////////////////////////////////////////////////////////////
if ( g_CoverInfo.Verbosity )
printf( "Performing minimization...\n" );
clk1 = clock();
ReduceEsopCover();
g_CoverInfo.TimeMin = clock() - clk1;
// g_Func.TimeMin = (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC);
if ( g_CoverInfo.Verbosity )
{
printf( "\nMinimization time is %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeMin) );
printf( "\nThe number of cubes after minimization is %d\n", g_CoverInfo.nCubesInUse );
}
///////////////////////////////////////////////////////////////////////
// STEP 5: save the cover into file
///////////////////////////////////////////////////////////////////////
// if option is MULTI_OUTPUT, the output is written into the output file;
// if option is SINGLE_NODE, the output is added to the input file
// and written into the output file; in this case, the minimized nodes is
// also stored in the temporary file "temp.blif" for verification
// create the file name and write the output
{
char Buffer[1000];
sprintf( Buffer, "%s", pFileNameOut ? pFileNameOut : "temp.esop" );
WriteResultIntoFile( Buffer );
//if ( g_CoverInfo.Verbosity )
printf( "Minimum cover has been written into file <%s>\n", Buffer );
}
///////////////////////////////////////////////////////////////////////
// STEP 6: delocate memory
///////////////////////////////////////////////////////////////////////
DelocateCubeSets();
DelocateCover();
DelocateQueques();
// return success
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_ExorcismMain( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOut, int Quality, int Verbosity )
{
memset( &g_CoverInfo, 0, sizeof(cinfo) );
g_CoverInfo.Quality = Quality;
g_CoverInfo.Verbosity = Verbosity;
printf( "EXORCISM, Ver.4.7: Exclusive Sum-of-Product Minimizer\n" );
printf( "by Alan Mishchenko, Portland State University, July-September 2000\n" );
if ( g_CoverInfo.Verbosity )
printf( "Incoming ESOP has %d inputs, %d outputs, and %d cubes.\n", nIns, nOuts, Vec_WecSize(vEsop) );
PrepareBitSetModule();
if ( Exorcism( vEsop, nIns, nOuts, pFileNameOut ) == 0 )
{
printf( "Something went wrong when minimizing the cover\n" );
return 0;
}
return 1;
}
///////////////////////////////////////////////////////////////////
//////////// End of File /////////////////
///////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

178
src/base/exor/exor.h Normal file
View File

@ -0,0 +1,178 @@
/**CFile****************************************************************
FileName [exor.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Exclusive sum-of-product minimization.]
Synopsis [Internal declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: exor.h,v 1.0 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// ///
/// Interface of EXORCISM - 4 ///
/// An Exclusive Sum-of-Product Minimizer ///
/// Alan Mishchenko <alanmi@ee.pdx.edu> ///
/// ///
////////////////////////////////////////////////////////////////////////
/// ///
/// Main Module ///
/// ///
/// Ver. 1.0. Started - July 15, 2000. Last update - July 20, 2000 ///
/// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 10, 2000 ///
/// Ver. 1.7. Started - Sep 20, 2000. Last update - Sep 23, 2000 ///
/// ///
////////////////////////////////////////////////////////////////////////
/// This software was tested with the BDD package "CUDD", v.2.3.0 ///
/// by Fabio Somenzi ///
/// http://vlsi.colorado.edu/~fabio/ ///
////////////////////////////////////////////////////////////////////////
#ifndef __EXORMAIN_H__
#define __EXORMAIN_H__
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include "misc/vec/vec.h"
#include "misc/vec/vecWec.h"
ABC_NAMESPACE_HEADER_START
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// the number of bits per integer (can be 16, 32, 64 - tested for 32)
#define BPI 32
#define BPIMASK 31
#define LOGBPI 5
// the maximum number of input variables
#define MAXVARS 1000
// the number of cubes that are allocated additionally
#define ADDITIONAL_CUBES 33
// the factor showing how many cube pairs will be allocated
#define CUBE_PAIR_FACTOR 20
// the following number of cube pairs are allocated:
// nCubesAlloc/CUBE_PAIR_FACTOR
#if BPI == 64
#define DIFFERENT 0x5555555555555555
#define BIT_COUNT(w) (BitCount[(w)&0xffff] + BitCount[((w)>>16)&0xffff] + BitCount[((w)>>32)&0xffff] + BitCount[(w)>>48])
#elif BPI == 32
#define DIFFERENT 0x55555555
#define BIT_COUNT(w) (BitCount[(w)&0xffff] + BitCount[(w)>>16])
#else
#define DIFFERENT 0x5555
#define BIT_COUNT(w) (BitCount[(w)])
#endif
#define VarWord(element) ((element)>>LOGBPI)
#define VarBit(element) ((element)&BPIMASK)
#define TICKS_TO_SECONDS(time) ((float)(time)/(float)(CLOCKS_PER_SEC))
////////////////////////////////////////////////////////////////////////
/// CUBE COVER and CUBE typedefs ///
////////////////////////////////////////////////////////////////////////
typedef enum { MULTI_OUTPUT = 1, SINGLE_NODE, MULTI_NODE } type;
// infomation about the cover
typedef struct cinfo_tag
{
int nVarsIn; // number of input binary variables in the cubes
int nVarsOut; // number of output binary variables in the cubes
int nWordsIn; // number of input words used to represent the cover
int nWordsOut; // number of output words used to represent the cover
int nCubesAlloc; // the number of allocated cubes
int nCubesBefore; // number of cubes before simplification
int nCubesInUse; // number of cubes after simplification
int nCubesFree; // number of free cubes
int nLiteralsBefore;// number of literals before
int nLiteralsAfter; // number of literals before
int cIDs; // the counter of cube IDs
int Verbosity; // verbosity level
int Quality; // quality
int TimeRead; // reading time
int TimeStart; // starting cover computation time
int TimeMin; // pure minimization time
} cinfo;
// representation of one cube (24 bytes + bit info)
typedef unsigned int drow;
typedef unsigned char byte;
typedef struct cube
{
byte fMark; // the flag which is TRUE if the cubes is enabled
byte ID; // (almost) unique ID of the cube
short a; // the number of literals
short z; // the number of 1's in the output part
drow* pCubeDataIn; // a pointer to the bit string representing literals
drow* pCubeDataOut; // a pointer to the bit string representing literals
struct cube* Prev; // pointers to the previous/next cubes in the list/ring
struct cube* Next;
} Cube;
// preparation
extern void PrepareBitSetModule();
extern int WriteResultIntoFile( char * pFileName );
// iterative ExorLink
extern int IterativelyApplyExorLink2( char fDistEnable );
extern int IterativelyApplyExorLink3( char fDistEnable );
extern int IterativelyApplyExorLink4( char fDistEnable );
// cube storage allocation/delocation
extern int AllocateCubeSets( int nVarsIn, int nVarsOut );
extern void DelocateCubeSets();
// adjacency queque allocation/delocation procedures
extern int AllocateQueques( int nPlaces );
extern void DelocateQueques();
extern int AllocateCover( int nCubes, int nWordsIn, int nWordsOut );
extern void DelocateCover();
extern void AddToFreeCubes( Cube* pC );
extern Cube* GetFreeCube();
// getting and returning free cubes to the heap
extern void InsertVarsWithoutClearing( Cube * pC, int * pVars, int nVarsIn, int * pVarValues, int Output );
extern int CheckForCloseCubes( Cube* p, int fAddCube );
extern int FindDiffVars( int *pDiffVars, Cube* pC1, Cube* pC2 );
// determines the variables that are different in cubes pC1 and pC2
// returns the number of variables
////////////////////////////////////////////////////////////////////////
/// VARVALUE and CUBEDIST enum typedefs ///
////////////////////////////////////////////////////////////////////////
// literal values
typedef enum { VAR_NEG = 1, VAR_POS, VAR_ABS } varvalue;
// the flag in some function calls can take one of the follwing values
typedef enum { DIST2, DIST3, DIST4 } cubedist;
ABC_NAMESPACE_HEADER_END
#endif

425
src/base/exor/exorBits.c Normal file
View File

@ -0,0 +1,425 @@
/**CFile****************************************************************
FileName [exorBits.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Exclusive sum-of-product minimization.]
Synopsis [Bit-level procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: exorBits.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// ///
/// Implementation of EXORCISM - 4 ///
/// An Exclusive Sum-of-Product Minimizer ///
/// ///
/// Alan Mishchenko <alanmi@ee.pdx.edu> ///
/// ///
////////////////////////////////////////////////////////////////////////
/// ///
/// EXOR-Oriented Bit String Manipulation ///
/// ///
/// Ver. 1.0. Started - July 18, 2000. Last update - July 20, 2000 ///
/// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 10, 2000 ///
/// ///
////////////////////////////////////////////////////////////////////////
/// This software was tested with the BDD package "CUDD", v.2.3.0 ///
/// by Fabio Somenzi ///
/// http://vlsi.colorado.edu/~fabio/ ///
////////////////////////////////////////////////////////////////////////
#include "exor.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// EXTERNAL VARIABLES ///
////////////////////////////////////////////////////////////////////////
// information about the cube cover
// the number of cubes is constantly updated when the cube cover is processed
// in this module, only the number of variables (nVarsIn) and integers (nWordsIn)
// is used, which do not change
extern cinfo g_CoverInfo;
////////////////////////////////////////////////////////////////////////
/// FUNCTIONS OF THIS MODULE ///
////////////////////////////////////////////////////////////////////////
int GetDistance( Cube * pC1, Cube * pC2 );
// return the distance between two cubes
int GetDistancePlus( Cube * pC1, Cube * pC2 );
int FindDiffVars( int * pDiffVars, Cube * pC1, Cube * pC2 );
// determine different variables in cubes from pCubes[] and writes them into pDiffVars
// returns the number of different variables
void InsertVars( Cube * pC, int * pVars, int nVarsIn, int * pVarValues );
//inline int VarWord( int element );
//inline int VarBit( int element );
varvalue GetVar( Cube * pC, int Var );
void ExorVar( Cube * pC, int Var, varvalue Val );
////////////////////////////////////////////////////////////////////////
/// STATIC VARIABLES ///
////////////////////////////////////////////////////////////////////////
// the bit count for the first 256 integer numbers
static unsigned char BitCount8[256] = {
0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
};
static int SparseNumbers[163] = {
0,1,4,5,16,17,20,21,64,65,68,69,80,81,84,85,256,257,260,
261,272,273,276,277,320,321,324,325,336,337,340,1024,1025,
1028,1029,1040,1041,1044,1045,1088,1089,1092,1093,1104,1105,
1108,1280,1281,1284,1285,1296,1297,1300,1344,1345,1348,1360,
4096,4097,4100,4101,4112,4113,4116,4117,4160,4161,4164,4165,
4176,4177,4180,4352,4353,4356,4357,4368,4369,4372,4416,4417,
4420,4432,5120,5121,5124,5125,5136,5137,5140,5184,5185,5188,
5200,5376,5377,5380,5392,5440,16384,16385,16388,16389,16400,
16401,16404,16405,16448,16449,16452,16453,16464,16465,16468,
16640,16641,16644,16645,16656,16657,16660,16704,16705,16708,
16720,17408,17409,17412,17413,17424,17425,17428,17472,17473,
17476,17488,17664,17665,17668,17680,17728,20480,20481,20484,
20485,20496,20497,20500,20544,20545,20548,20560,20736,20737,
20740,20752,20800,21504,21505,21508,21520,21568,21760
};
static unsigned char GroupLiterals[163][4] = {
{0}, {0}, {1}, {0,1}, {2}, {0,2}, {1,2}, {0,1,2}, {3}, {0,3},
{1,3}, {0,1,3}, {2,3}, {0,2,3}, {1,2,3}, {0,1,2,3}, {4}, {0,4},
{1,4}, {0,1,4}, {2,4}, {0,2,4}, {1,2,4}, {0,1,2,4}, {3,4},
{0,3,4}, {1,3,4}, {0,1,3,4}, {2,3,4}, {0,2,3,4}, {1,2,3,4}, {5},
{0,5}, {1,5}, {0,1,5}, {2,5}, {0,2,5}, {1,2,5}, {0,1,2,5}, {3,5},
{0,3,5}, {1,3,5}, {0,1,3,5}, {2,3,5}, {0,2,3,5}, {1,2,3,5},
{4,5}, {0,4,5}, {1,4,5}, {0,1,4,5}, {2,4,5}, {0,2,4,5},
{1,2,4,5}, {3,4,5}, {0,3,4,5}, {1,3,4,5}, {2,3,4,5}, {6}, {0,6},
{1,6}, {0,1,6}, {2,6}, {0,2,6}, {1,2,6}, {0,1,2,6}, {3,6},
{0,3,6}, {1,3,6}, {0,1,3,6}, {2,3,6}, {0,2,3,6}, {1,2,3,6},
{4,6}, {0,4,6}, {1,4,6}, {0,1,4,6}, {2,4,6}, {0,2,4,6},
{1,2,4,6}, {3,4,6}, {0,3,4,6}, {1,3,4,6}, {2,3,4,6}, {5,6},
{0,5,6}, {1,5,6}, {0,1,5,6}, {2,5,6}, {0,2,5,6}, {1,2,5,6},
{3,5,6}, {0,3,5,6}, {1,3,5,6}, {2,3,5,6}, {4,5,6}, {0,4,5,6},
{1,4,5,6}, {2,4,5,6}, {3,4,5,6}, {7}, {0,7}, {1,7}, {0,1,7},
{2,7}, {0,2,7}, {1,2,7}, {0,1,2,7}, {3,7}, {0,3,7}, {1,3,7},
{0,1,3,7}, {2,3,7}, {0,2,3,7}, {1,2,3,7}, {4,7}, {0,4,7},
{1,4,7}, {0,1,4,7}, {2,4,7}, {0,2,4,7}, {1,2,4,7}, {3,4,7},
{0,3,4,7}, {1,3,4,7}, {2,3,4,7}, {5,7}, {0,5,7}, {1,5,7},
{0,1,5,7}, {2,5,7}, {0,2,5,7}, {1,2,5,7}, {3,5,7}, {0,3,5,7},
{1,3,5,7}, {2,3,5,7}, {4,5,7}, {0,4,5,7}, {1,4,5,7}, {2,4,5,7},
{3,4,5,7}, {6,7}, {0,6,7}, {1,6,7}, {0,1,6,7}, {2,6,7},
{0,2,6,7}, {1,2,6,7}, {3,6,7}, {0,3,6,7}, {1,3,6,7}, {2,3,6,7},
{4,6,7}, {0,4,6,7}, {1,4,6,7}, {2,4,6,7}, {3,4,6,7}, {5,6,7},
{0,5,6,7}, {1,5,6,7}, {2,5,6,7}, {3,5,6,7}, {4,5,6,7}
};
// the bit count to 16-bit numbers
#define FULL16BITS 0x10000
#define MARKNUMBER 200
static unsigned char BitGroupNumbers[FULL16BITS];
unsigned char BitCount[FULL16BITS];
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
void PrepareBitSetModule()
// this function should be called before anything is done with the cube cover
{
// prepare bit count
int i, k;
int nLimit;
nLimit = FULL16BITS;
for ( i = 0; i < nLimit; i++ )
{
BitCount[i] = BitCount8[ i & 0xff ] + BitCount8[ i>>8 ];
BitGroupNumbers[i] = MARKNUMBER;
}
// prepare bit groups
for ( k = 0; k < 163; k++ )
BitGroupNumbers[ SparseNumbers[k] ] = k;
/*
// verify bit groups
int n = 4368;
char Buff[100];
cout << "The number is " << n << endl;
cout << "The binary is " << itoa(n,Buff,2) << endl;
cout << "BitGroupNumbers[n] is " << (int)BitGroupNumbers[n] << endl;
cout << "The group literals are ";
for ( int g = 0; g < 4; g++ )
cout << " " << (int)GroupLiterals[BitGroupNumbers[n]][g];
*/
}
////////////////////////////////////////////////////////////////////////
/// INLINE FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/*
int VarWord( int element )
{
return ( element >> LOGBPI );
}
int VarBit( int element )
{
return ( element & BPIMASK );
}
*/
varvalue GetVar( Cube * pC, int Var )
// returns VAR_NEG if var is neg, VAR_POS if var is pos, VAR_ABS if var is absent
{
int Bit = (Var<<1);
int Value = ((pC->pCubeDataIn[VarWord(Bit)] >> VarBit(Bit)) & 3);
assert( Value == VAR_NEG || Value == VAR_POS || Value == VAR_ABS );
return (varvalue)Value;
}
void ExorVar( Cube * pC, int Var, varvalue Val )
// EXORs the value Val with the value of variable Var in the given cube
// ((cube[VAR_WORD((v)<<1)]) ^ ( (pol)<<VAR_BIT((v)<<1) ))
{
int Bit = (Var<<1);
pC->pCubeDataIn[VarWord(Bit)] ^= ( Val << VarBit(Bit) );
}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
static int DiffVarCounter, cVars;
static drow Temp1, Temp2, Temp;
static drow LastNonZeroWord;
static int LastNonZeroWordNum;
int GetDistance( Cube * pC1, Cube * pC2 )
// finds and returns the distance between two cubes pC1 and pC2
{
int i;
DiffVarCounter = 0;
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
{
Temp1 = pC1->pCubeDataIn[i] ^ pC2->pCubeDataIn[i];
Temp2 = (Temp1|(Temp1>>1)) & DIFFERENT;
// count how many bits are one in this var difference
DiffVarCounter += BIT_COUNT(Temp2);
if ( DiffVarCounter > 4 )
return 5;
}
// check whether the output parts are different
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
if ( pC1->pCubeDataOut[i] ^ pC2->pCubeDataOut[i] )
{
DiffVarCounter++;
break;
}
return DiffVarCounter;
}
// place to put the number of the different variable and its value in the second cube
extern int s_DiffVarNum;
extern int s_DiffVarValueP_old;
extern int s_DiffVarValueP_new;
extern int s_DiffVarValueQ;
int GetDistancePlus( Cube * pC1, Cube * pC2 )
// finds and returns the distance between two cubes pC1 and pC2
// if the distance is 1, returns the number of diff variable in VarNum
{
int i;
DiffVarCounter = 0;
LastNonZeroWordNum = -1;
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
{
Temp1 = pC1->pCubeDataIn[i] ^ pC2->pCubeDataIn[i];
Temp2 = (Temp1|(Temp1>>1)) & DIFFERENT;
// save the value of var difference, in case
// the distance is one and we need to return the var number
if ( Temp2 )
{
LastNonZeroWordNum = i;
LastNonZeroWord = Temp2;
}
// count how many bits are one in this var difference
DiffVarCounter += BIT_COUNT(Temp2);
if ( DiffVarCounter > 4 )
return 5;
}
// check whether the output parts are different
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
if ( pC1->pCubeDataOut[i] ^ pC2->pCubeDataOut[i] )
{
DiffVarCounter++;
break;
}
if ( DiffVarCounter == 1 )
{
if ( LastNonZeroWordNum == -1 ) // the output is the only different variable
s_DiffVarNum = -1;
else
{
Temp = (LastNonZeroWord>>2);
for ( i = 0; Temp; Temp>>=2, i++ );
s_DiffVarNum = LastNonZeroWordNum*BPI/2 + i;
// save the old var value
s_DiffVarValueP_old = GetVar( pC1, s_DiffVarNum );
s_DiffVarValueQ = GetVar( pC2, s_DiffVarNum );
// EXOR this value with the corresponding value in p cube
ExorVar( pC1, s_DiffVarNum, (varvalue)s_DiffVarValueQ );
s_DiffVarValueP_new = GetVar( pC1, s_DiffVarNum );
}
}
return DiffVarCounter;
}
int FindDiffVars( int * pDiffVars, Cube * pC1, Cube * pC2 )
// determine different variables in two cubes and
// writes them into pDiffVars[]
// -1 is written into pDiffVars[0] if the cubes have different outputs
// returns the number of different variables (including the output)
{
int i, v;
DiffVarCounter = 0;
// check whether the output parts of the cubes are different
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
if ( pC1->pCubeDataOut[i] != pC2->pCubeDataOut[i] )
{ // they are different
pDiffVars[0] = -1;
DiffVarCounter = 1;
break;
}
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
{
Temp1 = pC1->pCubeDataIn[i] ^ pC2->pCubeDataIn[i];
Temp2 = (Temp1|(Temp1>>1)) & DIFFERENT;
// check the first part of this word
Temp = Temp2 & 0xffff;
cVars = BitCount[ Temp ];
if ( cVars )
{
if ( cVars < 5 )
for ( v = 0; v < cVars; v++ )
{
assert( BitGroupNumbers[Temp] != MARKNUMBER );
pDiffVars[ DiffVarCounter++ ] = i*16 + GroupLiterals[ BitGroupNumbers[Temp] ][v];
}
else
return 5;
}
if ( DiffVarCounter > 4 )
return 5;
// check the second part of this word
Temp = Temp2 >> 16;
cVars = BitCount[ Temp ];
if ( cVars )
{
if ( cVars < 5 )
for ( v = 0; v < cVars; v++ )
{
assert( BitGroupNumbers[Temp] != MARKNUMBER );
pDiffVars[ DiffVarCounter++ ] = i*16 + 8 + GroupLiterals[ BitGroupNumbers[Temp] ][v];
}
else
return 5;
}
if ( DiffVarCounter > 4 )
return 5;
}
return DiffVarCounter;
}
void InsertVars( Cube * pC, int * pVars, int nVarsIn, int * pVarValues )
// corrects the given number of variables (nVarsIn) in pC->pCubeDataIn[]
// variable numbers are given in pVarNumbers[], their values are in pVarValues[]
// arrays pVarNumbers[] and pVarValues[] are provided by the user
{
int GlobalBit;
int LocalWord;
int LocalBit;
int i;
assert( nVarsIn > 0 && nVarsIn <= g_CoverInfo.nVarsIn );
for ( i = 0; i < nVarsIn; i++ )
{
assert( pVars[i] >= 0 && pVars[i] < g_CoverInfo.nVarsIn );
assert( pVarValues[i] == VAR_NEG || pVarValues[i] == VAR_POS || pVarValues[i] == VAR_ABS );
GlobalBit = (pVars[i]<<1);
LocalWord = VarWord(GlobalBit);
LocalBit = VarBit(GlobalBit);
// correct this variables
pC->pCubeDataIn[LocalWord] = ((pC->pCubeDataIn[LocalWord]&(~(3<<LocalBit)))|(pVarValues[i]<<LocalBit));
}
}
void InsertVarsWithoutClearing( Cube * pC, int * pVars, int nVarsIn, int * pVarValues, int Output )
// corrects the given number of variables (nVarsIn) in pC->pCubeDataIn[]
// variable numbers are given in pVarNumbers[], their values are in pVarValues[]
// arrays pVarNumbers[] and pVarValues[] are provided by the user
{
int GlobalBit;
int LocalWord;
int LocalBit;
int i;
assert( nVarsIn > 0 && nVarsIn <= g_CoverInfo.nVarsIn );
for ( i = 0; i < nVarsIn; i++ )
{
assert( pVars[i] >= 0 && pVars[i] < g_CoverInfo.nVarsIn );
assert( pVarValues[i] == VAR_NEG || pVarValues[i] == VAR_POS || pVarValues[i] == VAR_ABS );
GlobalBit = (pVars[i]<<1);
LocalWord = VarWord(GlobalBit);
LocalBit = VarBit(GlobalBit);
// correct this variables
pC->pCubeDataIn[LocalWord] |= ( pVarValues[i] << LocalBit );
}
// insert the output bit
pC->pCubeDataOut[VarWord(Output)] |= ( 1 << VarBit(Output) );
}
///////////////////////////////////////////////////////////////////
//////////// End of File /////////////////
///////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

190
src/base/exor/exorCubes.c Normal file
View File

@ -0,0 +1,190 @@
/**CFile****************************************************************
FileName [exorCubes.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Exclusive sum-of-product minimization.]
Synopsis [Cube manipulation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: exorCubes.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// ///
/// Implementation of EXORCISM - 4 ///
/// An Exclusive Sum-of-Product Minimizer ///
/// ///
/// Alan Mishchenko <alanmi@ee.pdx.edu> ///
/// ///
////////////////////////////////////////////////////////////////////////
/// ///
/// Cube Allocation and Free Cube Management ///
/// ///
/// Ver. 1.0. Started - July 18, 2000. Last update - July 20, 2000 ///
/// Ver. 1.1. Started - July 24, 2000. Last update - July 29, 2000 ///
/// Ver. 1.2. Started - July 30, 2000. Last update - July 30, 2000 ///
/// Ver. 1.5. Started - Aug 19, 2000. Last update - Aug 19, 2000 ///
/// ///
////////////////////////////////////////////////////////////////////////
/// This software was tested with the BDD package "CUDD", v.2.3.0 ///
/// by Fabio Somenzi ///
/// http://vlsi.colorado.edu/~fabio/ ///
////////////////////////////////////////////////////////////////////////
#include "exor.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// EXTERNAL FUNCTIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// EXTERNAL VARIABLES ///
////////////////////////////////////////////////////////////////////////
// information about the cube cover before and after simplification
extern cinfo g_CoverInfo;
////////////////////////////////////////////////////////////////////////
/// FUNCTIONS OF THIS MODULE ///
////////////////////////////////////////////////////////////////////////
// cube cover memory allocation/delocation procedures
// (called from the ExorMain module)
int AllocateCover( int nCubes, int nWordsIn, int nWordsOut );
void DelocateCover();
// manipulation of the free cube list
// (called from Pseudo-Kronecker, ExorList, and ExorLink modules)
void AddToFreeCubes( Cube * pC );
Cube * GetFreeCube();
////////////////////////////////////////////////////////////////////////
/// EXPORTED VARIABLES ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// STATIC VARIABLES ///
////////////////////////////////////////////////////////////////////////
// the pointer to the allocated memory
Cube ** s_pCoverMemory;
// the list of free cubes
Cube * s_CubesFree;
///////////////////////////////////////////////////////////////////
/// CUBE COVER MEMORY MANAGEMENT //
///////////////////////////////////////////////////////////////////
int AllocateCover( int nCubes, int nWordsIn, int nWordsOut )
// uses the cover parameters nCubes and nWords
// to allocate-and-clean the cover in one large piece
{
int OneCubeSize;
int OneInputSetSize;
Cube ** pp;
int TotalSize;
int i, k;
// determine the size of one cube WITH storage for bits
OneCubeSize = sizeof(Cube) + (nWordsIn+nWordsOut)*sizeof(unsigned);
// determine what is the amount of storage for the input part of the cube
OneInputSetSize = nWordsIn*sizeof(unsigned);
// allocate memory for the array of pointers
pp = (Cube **)ABC_ALLOC( Cube *, nCubes );
if ( pp == NULL )
return 0;
// determine the size of the total cube cover
TotalSize = nCubes*OneCubeSize;
// allocate and clear memory for the cover in one large piece
pp[0] = (Cube *)ABC_ALLOC( char, TotalSize );
if ( pp[0] == NULL )
return 0;
memset( pp[0], 0, TotalSize );
// assign pointers to cubes and bit strings inside this piece
pp[0]->pCubeDataIn = (unsigned*)(pp[0] + 1);
pp[0]->pCubeDataOut = (unsigned*)((char*)pp[0]->pCubeDataIn + OneInputSetSize);
for ( i = 1; i < nCubes; i++ )
{
pp[i] = (Cube *)((char*)pp[i-1] + OneCubeSize);
pp[i]->pCubeDataIn = (unsigned*)(pp[i] + 1);
pp[i]->pCubeDataOut = (unsigned*)((char*)pp[i]->pCubeDataIn + OneInputSetSize);
}
// connect the cubes into the list using Next pointers
for ( k = 0; k < nCubes-1; k++ )
pp[k]->Next = pp[k+1];
// the last pointer is already set to NULL
// assign the head of the free list
s_CubesFree = pp[0];
// set the counters of the used and free cubes
g_CoverInfo.nCubesInUse = 0;
g_CoverInfo.nCubesFree = nCubes;
// save the pointer to the allocated memory
s_pCoverMemory = pp;
assert ( g_CoverInfo.nCubesInUse + g_CoverInfo.nCubesFree == g_CoverInfo.nCubesAlloc );
return nCubes*sizeof(Cube *) + TotalSize;
}
void DelocateCover()
{
ABC_FREE( s_pCoverMemory[0] );
ABC_FREE( s_pCoverMemory );
}
///////////////////////////////////////////////////////////////////
/// FREE CUBE LIST MANIPULATION FUNCTIONS ///
///////////////////////////////////////////////////////////////////
void AddToFreeCubes( Cube * p )
{
assert( p );
assert( p->Prev == NULL ); // the cube should not be in use
assert( p->Next == NULL );
assert( p->ID );
p->Next = s_CubesFree;
s_CubesFree = p;
// set the ID of the cube to 0,
// so that cube pair garbage collection could recognize it as different
p->ID = 0;
g_CoverInfo.nCubesFree++;
}
Cube * GetFreeCube()
{
Cube * p;
assert( s_CubesFree );
p = s_CubesFree;
s_CubesFree = s_CubesFree->Next;
p->Next = NULL;
g_CoverInfo.nCubesFree--;
return p;
}
///////////////////////////////////////////////////////////////////
//////////// End of File /////////////////
///////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

746
src/base/exor/exorLink.c Normal file
View File

@ -0,0 +1,746 @@
/**CFile****************************************************************
FileName [exorLink.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Exclusive sum-of-product minimization.]
Synopsis [Cube iterators.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: exorLink.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// ///
/// Implementation of EXORCISM - 4 ///
/// An Exclusive Sum-of-Product Minimizer ///
/// ///
/// Alan Mishchenko <alanmi@ee.pdx.edu> ///
/// ///
////////////////////////////////////////////////////////////////////////
/// ///
/// Generation of ExorLinked Cubes ///
/// ///
/// Ver. 1.0. Started - July 26, 2000. Last update - July 29, 2000 ///
/// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 12, 2000 ///
/// ///
////////////////////////////////////////////////////////////////////////
/// This software was tested with the BDD package "CUDD", v.2.3.0 ///
/// by Fabio Somenzi ///
/// http://vlsi.colorado.edu/~fabio/ ///
////////////////////////////////////////////////////////////////////////
#include "exor.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
#define LARGE_NUM 1000000
////////////////////////////////////////////////////////////////////////
/// EXTERNAL FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTIONS OF THIS MODULE ///
////////////////////////////////////////////////////////////////////////
int ExorLinkCubeIteratorStart( Cube** pGroup, Cube* pC1, Cube* pC2, cubedist Dist );
// this function starts the Exor-Link iterator, which iterates
// through the cube groups starting from the group with min literals
// returns 1 on success, returns 0 if the cubes have wrong distance
int ExorLinkCubeIteratorNext( Cube** pGroup );
// give the next group in the decreasing order of sum of literals
// returns 1 on success, returns 0 if there are no more groups
int ExorLinkCubeIteratorPick( Cube** pGroup, int g );
// gives the group #g in the order in which the groups were given
// during iteration
// returns 1 on success, returns 0 if something g is too large
void ExorLinkCubeIteratorCleanUp( int fTakeLastGroup );
// removes the cubes from the store back into the list of free cubes
// if fTakeLastGroup is 0, removes all cubes
// if fTakeLastGroup is 1, does not store the last group
////////////////////////////////////////////////////////////////////////
/// EXTERNAL VARIABLES ///
////////////////////////////////////////////////////////////////////////
// information about the cube cover before
extern cinfo g_CoverInfo;
// new IDs are assigned only when it is known that the cubes are useful
// this is done in ExorLinkCubeIteratorCleanUp();
// the head of the list of free cubes
extern Cube* g_CubesFree;
extern byte BitCount[];
////////////////////////////////////////////////////////////////////////
/// EXORLINK INFO ///
////////////////////////////////////////////////////////////////////////
const int s_ELMax = 4;
// ExorLink-2: there are 4 cubes, 2 literals each, combined into 2 groups
// ExorLink-3: there are 12 cubes, 3 literals each, combined into 6 groups
// ExorLink-4: there are 32 cubes, 4 literals each, combined into 24 groups
// ExorLink-5: there are 80 cubes, 5 literals each, combined into 120 groups
// Exorlink-n: there are n*2^(n-1) cubes, n literals each, combined into n! groups
const int s_ELnCubes[4] = { 4, 12, 32, 80 };
const int s_ELnGroups[4] = { 2, 6, 24, 120 };
// value sets of cubes X{a0}Y{b0}Z{c0}U{d0} and X{a1}Y{b1}Z{c1}U{d1}
// used to represent the ExorLink cube generation rules
enum { vs0, vs1, vsX };
// vs0 = 0, // the value set of the first cube
// vs1 = 1, // the value set of the second cube
// vsX = 2 // EXOR of the value sets of the first and second cubes
// representation of ExorLinked cubes
static int s_ELCubeRules[3][32][4] = {
{ // ExorLink-2 Cube Generating Rules
// | 0 | 1 | - sections
// |-------|
{vsX,vs0}, // cube 0 | | |
{vsX,vs1}, // cube 1 | | 0 |
{vs0,vsX}, // cube 2 | | |
{vs1,vsX} // cube 3 | 0 | |
},
{ // ExorLink-3 Cube Generating Rules
// | 0 | 1 | 2 | - sections
// |-----------|
{vsX,vs0,vs0}, // cube 0 | | | |
{vsX,vs0,vs1}, // cube 1 | | | 0 |
{vsX,vs1,vs0}, // cube 2 | | 0 | |
{vsX,vs1,vs1}, // cube 3 | | 1 | 1 |
{vs0,vsX,vs0}, // cube 4 | | | |
{vs0,vsX,vs1}, // cube 5 | | | 2 |
{vs1,vsX,vs0}, // cube 6 | 0 | | |
{vs1,vsX,vs1}, // cube 7 | 1 | | 3 |
{vs0,vs0,vsX}, // cube 8 | | | |
{vs0,vs1,vsX}, // cube 9 | | 2 | |
{vs1,vs0,vsX}, // cube 10 | 2 | | |
{vs1,vs1,vsX} // cube 11 | 3 | 3 | |
},
{ // ExorLink-4 Rules Generating Rules
// | 0 | 1 | 2 | 4 | - sections
// |---------------|
{vsX,vs0,vs0,vs0}, // cube 0 | | | | |
{vsX,vs0,vs0,vs1}, // cube 1 | | | | 0 |
{vsX,vs0,vs1,vs0}, // cube 2 | | | 0 | |
{vsX,vs0,vs1,vs1}, // cube 3 | | | 1 | 1 |
{vsX,vs1,vs0,vs0}, // cube 4 | | 0 | | |
{vsX,vs1,vs0,vs1}, // cube 5 | | 1 | | 2 |
{vsX,vs1,vs1,vs0}, // cube 6 | | 2 | 2 | |
{vsX,vs1,vs1,vs1}, // cube 7 | | 3 | 3 | 3 |
{vs0,vsX,vs0,vs0}, // cube 8 | | | | |
{vs0,vsX,vs0,vs1}, // cube 9 | | | | 4 |
{vs0,vsX,vs1,vs0}, // cube 10 | | | 4 | |
{vs0,vsX,vs1,vs1}, // cube 11 | | | 5 | 5 |
{vs1,vsX,vs0,vs0}, // cube 12 | 0 | | | |
{vs1,vsX,vs0,vs1}, // cube 13 | 1 | | | 6 |
{vs1,vsX,vs1,vs0}, // cube 14 | 2 | | 6 | |
{vs1,vsX,vs1,vs1}, // cube 15 | 3 | | 7 | 7 |
{vs0,vs0,vsX,vs0}, // cube 16 | | | | |
{vs0,vs0,vsX,vs1}, // cube 17 | | | | 8 |
{vs0,vs1,vsX,vs0}, // cube 18 | | 4 | | |
{vs0,vs1,vsX,vs1}, // cube 19 | | 5 | | 9 |
{vs1,vs0,vsX,vs0}, // cube 20 | 4 | | | |
{vs1,vs0,vsX,vs1}, // cube 21 | 5 | | | 10|
{vs1,vs1,vsX,vs0}, // cube 22 | 6 | 6 | | |
{vs1,vs1,vsX,vs1}, // cube 23 | 7 | 7 | | 11|
{vs0,vs0,vs0,vsX}, // cube 24 | | | | |
{vs0,vs0,vs1,vsX}, // cube 25 | | | 8 | |
{vs0,vs1,vs0,vsX}, // cube 26 | | 8 | | |
{vs0,vs1,vs1,vsX}, // cube 27 | | 9 | 9 | |
{vs1,vs0,vs0,vsX}, // cube 28 | 8 | | | |
{vs1,vs0,vs1,vsX}, // cube 29 | 9 | | 10| |
{vs1,vs1,vs0,vsX}, // cube 30 | 10| 10| | |
{vs1,vs1,vs1,vsX} // cube 31 | 11| 11| 11| |
}
};
// these cubes are combined into groups
static int s_ELGroupRules[3][24][4] = {
{ // ExorLink-2 Group Forming Rules
{0,3}, // group 0 - section 0
{2,1} // group 1 - section 1
},
{ // ExorLink-3 Group Forming Rules
{0,6,11}, // group 0 - section 0
{0,7,10}, // group 1
{4,2,11}, // group 2 - section 1
{4,3,9}, // group 3
{8,1,7}, // group 4 - section 2
{8,3,5} // group 5
},
{ // ExorLink-4 Group Forming Rules
// section 0: (0-12)(1-13)(2-14)(3-15)(4-20)(5-21)(6-22)(7-23)(8-28)(9-29)(10-30)(11-31)
{0,12,22,31}, // group 0 // {0,6,11}, // group 0 - section 0
{0,12,23,30}, // group 1 // {0,7,10}, // group 1
{0,20,14,31}, // group 2 // {4,2,11}, // group 2
{0,20,15,29}, // group 3 // {4,3,9}, // group 3
{0,28,13,23}, // group 4 // {8,1,7}, // group 4
{0,28,15,21}, // group 5 // {8,3,5} // group 5
// section 1: (0-4)(1-5)(2-6)(3-7)(4-18)(5-19)(6-22)(7-23)(8-26)(9-27)(10-30)(11-31)
{8,4,22,31}, // group 6
{8,4,23,30}, // group 7
{8,18,6,31}, // group 8
{8,18,7,27}, // group 9
{8,26,5,23}, // group 10
{8,26,7,19}, // group 11
// section 2: (0-2)(1-3)(2-6)(3-7)(4-10)(5-11)(6-14)(7-15)(8-25)(9-27)(10-29)(11-31)
{16,2,14,31}, // group 12
{16,2,15,29}, // group 13
{16,10,6,31}, // group 14
{16,10,7,27}, // group 15
{16,25,3,15}, // group 16
{16,25,7,11}, // group 17
// section 3: (0-1)(1-3)(2-5)(3-7)(4-9)(5-11)(6-13)(7-15)(8-17)(9-19)(10-21)(11-23)
{24,1,13,23}, // group 18
{24,1,15,21}, // group 19
{24,9, 5,23}, // group 20
{24,9, 7,19}, // group 21
{24,17,3,15}, // group 22
{24,17,7,11} // group 23
}
};
// it is assumed that if literals in the first cube, second cube
// and their EXOR are 0 or 1 (as opposed to -), they are written
// into a mask, which is used to count the number of literals in
// the cube groups cubes
//
// below is the set of masks selecting literals belonging
// to the given cube of the group
static drow s_CubeLitMasks[3][32] = {
{ // ExorLink-2 Literal Counting Masks
// v3 v2 v1 v0
// -xBA -xBA -xBA -xBA
// -------------------
0x14, // cube 0 <0000 0000 0001 0100> {vsX,vs0}
0x24, // cube 1 <0000 0000 0010 0100> {vsX,vs1}
0x41, // cube 2 <0000 0000 0100 0001> {vs0,vsX}
0x42, // cube 3 <0000 0000 0100 0010> {vs1,vsX}
},
{ // ExorLink-3 Literal Counting Masks
0x114, // cube 0 <0000 0001 0001 0100> {vsX,vs0,vs0}
0x214, // cube 1 <0000 0010 0001 0100> {vsX,vs0,vs1}
0x124, // cube 2 <0000 0001 0010 0100> {vsX,vs1,vs0}
0x224, // cube 3 <0000 0010 0010 0100> {vsX,vs1,vs1}
0x141, // cube 4 <0000 0001 0100 0001> {vs0,vsX,vs0}
0x241, // cube 5 <0000 0010 0100 0001> {vs0,vsX,vs1}
0x142, // cube 6 <0000 0001 0100 0010> {vs1,vsX,vs0}
0x242, // cube 7 <0000 0010 0100 0010> {vs1,vsX,vs1}
0x411, // cube 8 <0000 0100 0001 0001> {vs0,vs0,vsX}
0x421, // cube 9 <0000 0100 0010 0001> {vs0,vs1,vsX}
0x412, // cube 10 <0000 0100 0001 0010> {vs1,vs0,vsX}
0x422, // cube 11 <0000 0100 0010 0010> {vs1,vs1,vsX}
},
{ // ExorLink-4 Literal Counting Masks
0x1114, // cube 0 <0001 0001 0001 0100> {vsX,vs0,vs0,vs0}
0x2114, // cube 1 <0010 0001 0001 0100> {vsX,vs0,vs0,vs1}
0x1214, // cube 2 <0001 0010 0001 0100> {vsX,vs0,vs1,vs0}
0x2214, // cube 3 <0010 0010 0001 0100> {vsX,vs0,vs1,vs1}
0x1124, // cube 4 <0001 0001 0010 0100> {vsX,vs1,vs0,vs0}
0x2124, // cube 5 <0010 0001 0010 0100> {vsX,vs1,vs0,vs1}
0x1224, // cube 6 <0001 0010 0010 0100> {vsX,vs1,vs1,vs0}
0x2224, // cube 7 <0010 0010 0010 0100> {vsX,vs1,vs1,vs1}
0x1141, // cube 8 <0001 0001 0100 0001> {vs0,vsX,vs0,vs0}
0x2141, // cube 9 <0010 0001 0100 0001> {vs0,vsX,vs0,vs1}
0x1241, // cube 10 <0001 0010 0100 0001> {vs0,vsX,vs1,vs0}
0x2241, // cube 11 <0010 0010 0100 0001> {vs0,vsX,vs1,vs1}
0x1142, // cube 12 <0001 0001 0100 0010> {vs1,vsX,vs0,vs0}
0x2142, // cube 13 <0010 0001 0100 0010> {vs1,vsX,vs0,vs1}
0x1242, // cube 14 <0001 0010 0100 0010> {vs1,vsX,vs1,vs0}
0x2242, // cube 15 <0010 0010 0100 0010> {vs1,vsX,vs1,vs1}
0x1411, // cube 16 <0001 0100 0001 0001> {vs0,vs0,vsX,vs0}
0x2411, // cube 17 <0010 0100 0001 0001> {vs0,vs0,vsX,vs1}
0x1421, // cube 18 <0001 0100 0010 0001> {vs0,vs1,vsX,vs0}
0x2421, // cube 19 <0010 0100 0010 0001> {vs0,vs1,vsX,vs1}
0x1412, // cube 20 <0001 0100 0001 0010> {vs1,vs0,vsX,vs0}
0x2412, // cube 21 <0010 0100 0001 0010> {vs1,vs0,vsX,vs1}
0x1422, // cube 22 <0001 0100 0010 0010> {vs1,vs1,vsX,vs0}
0x2422, // cube 23 <0010 0100 0010 0010> {vs1,vs1,vsX,vs1}
0x4111, // cube 24 <0100 0001 0001 0001> {vs0,vs0,vs0,vsX}
0x4211, // cube 25 <0100 0010 0001 0001> {vs0,vs0,vs1,vsX}
0x4121, // cube 26 <0100 0001 0010 0001> {vs0,vs1,vs0,vsX}
0x4221, // cube 27 <0100 0010 0010 0001> {vs0,vs1,vs1,vsX}
0x4112, // cube 28 <0100 0001 0001 0010> {vs1,vs0,vs0,vsX}
0x4212, // cube 29 <0100 0010 0001 0010> {vs1,vs0,vs1,vsX}
0x4122, // cube 30 <0100 0001 0010 0010> {vs1,vs1,vs0,vsX}
0x4222, // cube 31 <0100 0010 0010 0010> {vs1,vs1,vs1,vsX}
}
};
static drow s_BitMasks[32] =
{
0x00000001,0x00000002,0x00000004,0x00000008,
0x00000010,0x00000020,0x00000040,0x00000080,
0x00000100,0x00000200,0x00000400,0x00000800,
0x00001000,0x00002000,0x00004000,0x00008000,
0x00010000,0x00020000,0x00040000,0x00080000,
0x00100000,0x00200000,0x00400000,0x00800000,
0x01000000,0x02000000,0x04000000,0x08000000,
0x10000000,0x20000000,0x40000000,0x80000000
};
////////////////////////////////////////////////////////////////////////
/// STATIC VARIABLES ///
////////////////////////////////////////////////////////////////////////
// this flag is TRUE as long as the storage is allocated
static int fWorking;
// set these flags to have minimum literal groups generated first
static int fMinLitGroupsFirst[4] = { 0 /*dist2*/, 0 /*dist3*/, 0 /*dist4*/};
static int nDist;
static int nCubes;
static int nCubesInGroup;
static int nGroups;
static Cube *pCA, *pCB;
// storage for variable numbers that are different in the cubes
static int DiffVars[5];
static int* pDiffVars;
static int nDifferentVars;
// storage for the bits and words of different input variables
static int nDiffVarsIn;
static int DiffVarWords[5];
static int DiffVarBits[5];
// literal mask used to count the number of literals in the cubes
static drow MaskLiterals;
// the base for counting literals
static int StartingLiterals;
// the number of literals in each cube
static int CubeLiterals[32];
static int BitShift;
static int DiffVarValues[4][3];
static int Value;
// the sorted array of groups in the increasing order of costs
static int GroupCosts[32];
static int GroupCostBest;
static int GroupCostBestNum;
static int CubeNum;
static int NewZ;
static drow Temp;
// the cubes currently created
static Cube* ELCubes[32];
// the bit string with 1's corresponding to cubes in ELCubes[]
// that constitute the last group
static drow LastGroup;
static int GroupOrder[24];
static drow VisitedGroups;
static int nVisitedGroups;
//int RemainderBits = (nVars*2)%(sizeof(drow)*8);
//int TotalWords = (nVars*2)/(sizeof(drow)*8) + (RemainderBits > 0);
static drow DammyBitData[(MAXVARS*2)/(sizeof(drow)*8)+(MAXVARS*2)%(sizeof(drow)*8)];
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINTIONS ///
////////////////////////////////////////////////////////////////////////
// IDEA! if we already used a cube to count distances and it did not improve
// there is no need to try it again with other group
// (this idea works only for ExorLink-2 and -3)
int ExorLinkCubeIteratorStart( Cube** pGroup, Cube* pC1, Cube* pC2, cubedist Dist )
// this function starts the Exor-Link iterator, which iterates
// through the cube groups starting from the group with min literals
// returns 1 on success, returns 0 if the cubes have wrong distance
{
int i, c;
// check that everything is okey
assert( pC1 != NULL );
assert( pC2 != NULL );
assert( !fWorking );
nDist = Dist;
nCubes = Dist + 2;
nCubesInGroup = s_ELnCubes[nDist];
nGroups = s_ELnGroups[Dist];
pCA = pC1;
pCB = pC2;
// find what variables are different in these two cubes
// FindDiffVars returns DiffVars[0] < 0, if the output is different
nDifferentVars = FindDiffVars( DiffVars, pCA, pCB );
if ( nCubes != nDifferentVars )
{
// cout << "ExorLinkCubeIterator(): Distance mismatch";
// cout << " nCubes = " << nCubes << " nDiffVars = " << nDifferentVars << endl;
fWorking = 0;
return 0;
}
// copy the input variable cube data into DammyBitData[]
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
DammyBitData[i] = pCA->pCubeDataIn[i];
// find the number of different input variables
nDiffVarsIn = ( DiffVars[0] >= 0 )? nCubes: nCubes-1;
// assign the pointer to the place where the number of diff input vars is stored
pDiffVars = ( DiffVars[0] >= 0 )? DiffVars: DiffVars+1;
// find the bit offsets and remove different variables
for ( i = 0; i < nDiffVarsIn; i++ )
{
DiffVarWords[i] = ((2*pDiffVars[i]) >> LOGBPI) ;
DiffVarBits[i] = ((2*pDiffVars[i]) & BPIMASK);
// clear this position
DammyBitData[ DiffVarWords[i] ] &= ~( 3 << DiffVarBits[i] );
}
// extract the values from the cubes and create the mask of literals
MaskLiterals = 0;
// initialize the base for literal counts
StartingLiterals = pCA->a;
for ( i = 0, BitShift = 0; i < nDiffVarsIn; i++, BitShift++ )
{
DiffVarValues[i][0] = ( pCA->pCubeDataIn[DiffVarWords[i]] >> DiffVarBits[i] ) & 3;
if ( DiffVarValues[i][0] != VAR_ABS )
{
MaskLiterals |= ( 1 << BitShift );
// update the base for literal counts
StartingLiterals--;
}
BitShift++;
DiffVarValues[i][1] = ( pCB->pCubeDataIn[DiffVarWords[i]] >> DiffVarBits[i] ) & 3;
if ( DiffVarValues[i][1] != VAR_ABS )
MaskLiterals |= ( 1 << BitShift );
BitShift++;
DiffVarValues[i][2] = DiffVarValues[i][0] ^ DiffVarValues[i][1];
if ( DiffVarValues[i][2] != VAR_ABS )
MaskLiterals |= ( 1 << BitShift );
BitShift++;
}
// count the number of additional literals in each cube of the group
for ( i = 0; i < nCubesInGroup; i++ )
CubeLiterals[i] = BitCount[ MaskLiterals & s_CubeLitMasks[Dist][i] ];
// compute the costs of all groups
for ( i = 0; i < nGroups; i++ )
// go over all cubes in the group
for ( GroupCosts[i] = 0, c = 0; c < nCubes; c++ )
GroupCosts[i] += CubeLiterals[ s_ELGroupRules[Dist][i][c] ];
// find the best cost group
if ( fMinLitGroupsFirst[Dist] )
{ // find the minimum cost group
GroupCostBest = LARGE_NUM;
for ( i = 0; i < nGroups; i++ )
if ( GroupCostBest > GroupCosts[i] )
{
GroupCostBest = GroupCosts[i];
GroupCostBestNum = i;
}
}
else
{ // find the maximum cost group
GroupCostBest = -1;
for ( i = 0; i < nGroups; i++ )
if ( GroupCostBest < GroupCosts[i] )
{
GroupCostBest = GroupCosts[i];
GroupCostBestNum = i;
}
}
// create the cubes with min number of literals needed for the group
LastGroup = 0;
for ( c = 0; c < nCubes; c++ )
{
CubeNum = s_ELGroupRules[Dist][GroupCostBestNum][c];
LastGroup |= s_BitMasks[CubeNum];
// bring a cube from the free cube list
ELCubes[CubeNum] = GetFreeCube();
// copy the input bit data into the cube
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
ELCubes[CubeNum]->pCubeDataIn[i] = DammyBitData[i];
// copy the output bit data into the cube
NewZ = 0;
if ( DiffVars[0] >= 0 ) // the output is not involved in ExorLink
{
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
ELCubes[CubeNum]->pCubeDataOut[i] = pCA->pCubeDataOut[i];
NewZ = pCA->z;
}
else // the output is involved
{ // determine where the output information comes from
Value = s_ELCubeRules[Dist][CubeNum][nDiffVarsIn];
if ( Value == vs0 )
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
{
Temp = pCA->pCubeDataOut[i];
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
NewZ += BIT_COUNT(Temp);
}
else if ( Value == vs1 )
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
{
Temp = pCB->pCubeDataOut[i];
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
NewZ += BIT_COUNT(Temp);
}
else if ( Value == vsX )
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
{
Temp = pCA->pCubeDataOut[i] ^ pCB->pCubeDataOut[i];
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
NewZ += BIT_COUNT(Temp);
}
}
// set the number of literals
ELCubes[CubeNum]->a = StartingLiterals + CubeLiterals[CubeNum];
ELCubes[CubeNum]->z = NewZ;
// set the variables that should be there
for ( i = 0; i < nDiffVarsIn; i++ )
{
Value = DiffVarValues[i][ s_ELCubeRules[Dist][CubeNum][i] ];
ELCubes[CubeNum]->pCubeDataIn[ DiffVarWords[i] ] |= ( Value << DiffVarBits[i] );
}
// assign the ID
ELCubes[CubeNum]->ID = g_CoverInfo.cIDs++;
// skip through zero-ID
if ( g_CoverInfo.cIDs == 256 )
g_CoverInfo.cIDs = 1;
// prepare the return array
pGroup[c] = ELCubes[CubeNum];
}
// mark this group as visited
VisitedGroups |= s_BitMasks[ GroupCostBestNum ];
// set the first visited group number
GroupOrder[0] = GroupCostBestNum;
// increment the counter of visited groups
nVisitedGroups = 1;
fWorking = 1;
return 1;
}
int ExorLinkCubeIteratorNext( Cube** pGroup )
// give the next group in the decreasing order of sum of literals
// returns 1 on success, returns 0 if there are no more groups
{
int i, c;
// check that everything is okey
assert( fWorking );
if ( nVisitedGroups == nGroups )
// we have iterated through all groups
return 0;
// find the min/max cost group
if ( fMinLitGroupsFirst[nDist] )
// if ( nCubes == 4 )
{ // find the minimum cost
// go through all groups
GroupCostBest = LARGE_NUM;
for ( i = 0; i < nGroups; i++ )
if ( !(VisitedGroups & s_BitMasks[i]) && GroupCostBest > GroupCosts[i] )
{
GroupCostBest = GroupCosts[i];
GroupCostBestNum = i;
}
assert( GroupCostBest != LARGE_NUM );
}
else
{ // find the maximum cost
// go through all groups
GroupCostBest = -1;
for ( i = 0; i < nGroups; i++ )
if ( !(VisitedGroups & s_BitMasks[i]) && GroupCostBest < GroupCosts[i] )
{
GroupCostBest = GroupCosts[i];
GroupCostBestNum = i;
}
assert( GroupCostBest != -1 );
}
// create the cubes needed for the group, if they are not created already
LastGroup = 0;
for ( c = 0; c < nCubes; c++ )
{
CubeNum = s_ELGroupRules[nDist][GroupCostBestNum][c];
LastGroup |= s_BitMasks[CubeNum];
if ( ELCubes[CubeNum] == NULL ) // this cube does not exist
{
// bring a cube from the free cube list
ELCubes[CubeNum] = GetFreeCube();
// copy the input bit data into the cube
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
ELCubes[CubeNum]->pCubeDataIn[i] = DammyBitData[i];
// copy the output bit data into the cube
NewZ = 0;
if ( DiffVars[0] >= 0 ) // the output is not involved in ExorLink
{
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
ELCubes[CubeNum]->pCubeDataOut[i] = pCA->pCubeDataOut[i];
NewZ = pCA->z;
}
else // the output is involved
{ // determine where the output information comes from
Value = s_ELCubeRules[nDist][CubeNum][nDiffVarsIn];
if ( Value == vs0 )
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
{
Temp = pCA->pCubeDataOut[i];
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
NewZ += BIT_COUNT(Temp);
}
else if ( Value == vs1 )
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
{
Temp = pCB->pCubeDataOut[i];
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
NewZ += BIT_COUNT(Temp);
}
else if ( Value == vsX )
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
{
Temp = pCA->pCubeDataOut[i] ^ pCB->pCubeDataOut[i];
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
NewZ += BIT_COUNT(Temp);
}
}
// set the number of literals and output ones
ELCubes[CubeNum]->a = StartingLiterals + CubeLiterals[CubeNum];
ELCubes[CubeNum]->z = NewZ;
assert( NewZ != 255 );
// set the variables that should be there
for ( i = 0; i < nDiffVarsIn; i++ )
{
Value = DiffVarValues[i][ s_ELCubeRules[nDist][CubeNum][i] ];
ELCubes[CubeNum]->pCubeDataIn[ DiffVarWords[i] ] |= ( Value << DiffVarBits[i] );
}
// assign the ID
ELCubes[CubeNum]->ID = g_CoverInfo.cIDs++;
// skip through zero-ID
if ( g_CoverInfo.cIDs == 256 )
g_CoverInfo.cIDs = 1;
}
// prepare the return array
pGroup[c] = ELCubes[CubeNum];
}
// mark this group as visited
VisitedGroups |= s_BitMasks[ GroupCostBestNum ];
// set the next visited group number and
// increment the counter of visited groups
GroupOrder[ nVisitedGroups++ ] = GroupCostBestNum;
return 1;
}
int ExorLinkCubeIteratorPick( Cube** pGroup, int g )
// gives the group #g in the order in which the groups were given
// during iteration
// returns 1 on success, returns 0 if something is wrong (g is too large)
{
int GroupNum, c;
assert( fWorking );
assert( g >= 0 && g < nGroups );
assert( VisitedGroups & s_BitMasks[g] );
GroupNum = GroupOrder[g];
// form the group
LastGroup = 0;
for ( c = 0; c < nCubes; c++ )
{
CubeNum = s_ELGroupRules[nDist][GroupNum][c];
// remember this group as the last one
LastGroup |= s_BitMasks[CubeNum];
assert( ELCubes[CubeNum] != NULL ); // this cube should exist
// prepare the return array
pGroup[c] = ELCubes[CubeNum];
}
return 1;
}
void ExorLinkCubeIteratorCleanUp( int fTakeLastGroup )
// removes the cubes from the store back into the list of free cubes
// if fTakeLastGroup is 0, removes all cubes
// if fTakeLastGroup is 1, does not store the last group
{
int c;
assert( fWorking );
// put cubes back
// set the cube pointers to zero
if ( fTakeLastGroup == 0 )
for ( c = 0; c < nCubesInGroup; c++ )
{
ELCubes[c]->fMark = 0;
AddToFreeCubes( ELCubes[c] );
ELCubes[c] = NULL;
}
else
for ( c = 0; c < nCubesInGroup; c++ )
if ( ELCubes[c] )
{
ELCubes[c]->fMark = 0;
if ( (LastGroup & s_BitMasks[c]) == 0 ) // does not belong to the last group
AddToFreeCubes( ELCubes[c] );
ELCubes[c] = NULL;
}
// set the cube groups to zero
VisitedGroups = 0;
// shut down the iterator
fWorking = 0;
}
///////////////////////////////////////////////////////////////////
//////////// End of File /////////////////
///////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

1140
src/base/exor/exorList.c Normal file

File diff suppressed because it is too large Load Diff

204
src/base/exor/exorUtil.c Normal file
View File

@ -0,0 +1,204 @@
/**CFile****************************************************************
FileName [exorUtil.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Exclusive sum-of-product minimization.]
Synopsis [Utilities.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: exorUtil.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// ///
/// Implementation of EXORCISM - 4 ///
/// An Exclusive Sum-of-Product Minimizer ///
/// Alan Mishchenko <alanmi@ee.pdx.edu> ///
/// ///
////////////////////////////////////////////////////////////////////////
/// ///
/// Utility Functions ///
/// ///
/// 1) allocating memory for and creating the ESOP cover ///
/// 2) writing the resultant cover into an ESOP PLA file ///
/// ///
/// Ver. 1.0. Started - July 15, 2000. Last update - July 20, 2000 ///
/// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 10, 2000 ///
/// Ver. 1.5. Started - Aug 19, 2000. Last update - Aug 19, 2000 ///
/// Ver. 1.7. Started - Sep 20, 2000. Last update - Sep 23, 2000 ///
/// ///
////////////////////////////////////////////////////////////////////////
/// This software was tested with the BDD package "CUDD", v.2.3.0 ///
/// by Fabio Somenzi ///
/// http://vlsi.colorado.edu/~fabio/ ///
////////////////////////////////////////////////////////////////////////
#include "exor.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// EXTERNAL VARIABLES ////
////////////////////////////////////////////////////////////////////////
// information about the options, the function, and the cover
extern cinfo g_CoverInfo;
////////////////////////////////////////////////////////////////////////
/// EXTERNAL FUNCTIONS ///
////////////////////////////////////////////////////////////////////////
// Cube Cover Iterator
// starts an iterator that traverses all the cubes in the ring
extern Cube* IterCubeSetStart();
// returns the next cube in the ring
extern Cube* IterCubeSetNext();
// retrieves the variable from the cube
extern varvalue GetVar( Cube* pC, int Var );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//////////// Cover Service Procedures /////////////////
///////////////////////////////////////////////////////////////////
int CountLiterals()
// nCubesAlloc is the number of allocated cubes
{
Cube* p;
int Value, v;
int LitCounter = 0;
int LitCounterControl = 0;
for ( p = IterCubeSetStart( ); p; p = IterCubeSetNext() )
{
LitCounterControl += p->a;
assert( p->fMark == 0 );
// write the input variables
for ( v = 0; v < g_CoverInfo.nVarsIn; v++ )
{
Value = GetVar( p, v );
if ( Value == VAR_NEG )
LitCounter++;
else if ( Value == VAR_POS )
LitCounter++;
else if ( Value != VAR_ABS )
{
assert(0);
}
}
}
if ( LitCounterControl != LitCounter )
printf( "Warning! The recorded number of literals (%d) differs from the actual number (%d)\n", LitCounterControl, LitCounter );
return LitCounter;
}
void WriteTableIntoFile( FILE * pFile )
// nCubesAlloc is the number of allocated cubes
{
int v, w;
Cube * p;
int cOutputs;
int nOutput;
int WordSize;
for ( p = IterCubeSetStart( ); p; p = IterCubeSetNext() )
{
assert( p->fMark == 0 );
// write the input variables
for ( v = 0; v < g_CoverInfo.nVarsIn; v++ )
{
int Value = GetVar( p, v );
if ( Value == VAR_NEG )
fprintf( pFile, "0" );
else if ( Value == VAR_POS )
fprintf( pFile, "1" );
else if ( Value == VAR_ABS )
fprintf( pFile, "-" );
else
assert(0);
}
fprintf( pFile, " " );
// write the output variables
cOutputs = 0;
nOutput = g_CoverInfo.nVarsOut;
WordSize = 8*sizeof( unsigned );
for ( w = 0; w < g_CoverInfo.nWordsOut; w++ )
for ( v = 0; v < WordSize; v++ )
{
if ( p->pCubeDataOut[w] & (1<<v) )
fprintf( pFile, "1" );
else
fprintf( pFile, "0" );
if ( ++cOutputs == nOutput )
break;
}
fprintf( pFile, "\n" );
}
}
int WriteResultIntoFile( char * pFileName )
// write the ESOP cover into the PLA file <NewFileName>
{
FILE * pFile;
time_t ltime;
char * TimeStr;
pFile = fopen( pFileName, "w" );
if ( pFile == NULL )
{
fprintf( pFile, "\n\nCannot open the output file\n" );
return 1;
}
// get current time
time( &ltime );
TimeStr = asctime( localtime( &ltime ) );
// get the number of literals
g_CoverInfo.nLiteralsAfter = CountLiterals();
fprintf( pFile, "# EXORCISM-4 output for command line arguments: " );
fprintf( pFile, "\"-Q %d -V %d\"\n", g_CoverInfo.Quality, g_CoverInfo.Verbosity );
fprintf( pFile, "# Minimization performed %s", TimeStr );
fprintf( pFile, "# Initial statistics: " );
fprintf( pFile, "Cubes = %d Literals = %d\n", g_CoverInfo.nCubesBefore, g_CoverInfo.nLiteralsBefore );
fprintf( pFile, "# Final statistics: " );
fprintf( pFile, "Cubes = %d Literals = %d\n", g_CoverInfo.nCubesInUse, g_CoverInfo.nLiteralsAfter );
fprintf( pFile, "# File reading and reordering time = %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeRead) );
fprintf( pFile, "# Starting cover generation time = %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeStart) );
fprintf( pFile, "# Pure ESOP minimization time = %.2f sec\n", TICKS_TO_SECONDS(g_CoverInfo.TimeMin) );
fprintf( pFile, ".i %d\n", g_CoverInfo.nVarsIn );
fprintf( pFile, ".o %d\n", g_CoverInfo.nVarsOut );
fprintf( pFile, ".p %d\n", g_CoverInfo.nCubesInUse );
fprintf( pFile, ".type esop\n" );
WriteTableIntoFile( pFile );
fprintf( pFile, ".e\n" );
fclose( pFile );
return 0;
}
///////////////////////////////////////////////////////////////////
//////////// End of File /////////////////
///////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

View File

@ -0,0 +1,6 @@
SRC += src/base/exor/exor.c \
src/base/exor/exorBits.c \
src/base/exor/exorCubes.c \
src/base/exor/exorLink.c \
src/base/exor/exorList.c \
src/base/exor/exorUtil.c

View File

@ -903,10 +903,10 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Abc_Ntk_t * pNtk;
char * pFileName;
int c, fZeros = 0, fBoth = 0, fCheck = 1;
int c, fZeros = 0, fBoth = 0, fSkipPrepro = 0, fCheck = 1;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "zbch" ) ) != EOF )
while ( ( c = Extra_UtilGetopt( argc, argv, "zbxch" ) ) != EOF )
{
switch ( c )
{
@ -916,6 +916,9 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
case 'b':
fBoth ^= 1;
break;
case 'x':
fSkipPrepro ^= 1;
break;
case 'c':
fCheck ^= 1;
break;
@ -930,10 +933,10 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
// get the input file name
pFileName = argv[globalUtilOptind];
// read the file using the corresponding file reader
if ( fZeros || fBoth )
if ( fZeros || fBoth || fSkipPrepro )
{
Abc_Ntk_t * pTemp;
pNtk = Io_ReadPla( pFileName, fZeros, fBoth, fCheck );
pNtk = Io_ReadPla( pFileName, fZeros, fBoth, fSkipPrepro, fCheck );
if ( pNtk == NULL )
{
printf( "Reading PLA file has failed.\n" );
@ -952,10 +955,11 @@ int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
fprintf( pAbc->Err, "usage: read_pla [-zbch] <file>\n" );
fprintf( pAbc->Err, "usage: read_pla [-zbxch] <file>\n" );
fprintf( pAbc->Err, "\t reads the network in PLA\n" );
fprintf( pAbc->Err, "\t-z : toggle reading on-set and off-set [default = %s]\n", fZeros? "off-set":"on-set" );
fprintf( pAbc->Err, "\t-b : toggle reading both on-set and off-set as on-set [default = %s]\n", fBoth? "off-set":"on-set" );
fprintf( pAbc->Err, "\t-x : toggle reading Exclusive SOP rather than SOP [default = %s]\n", fSkipPrepro? "yes":"no" );
fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" );
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );

View File

@ -93,7 +93,7 @@ extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck );
/*=== abcReadEqn.c ============================================================*/
extern Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck );
/*=== abcReadPla.c ============================================================*/
extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fBoth, int fCheck );
extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fBoth, int fSkipPrepro, int fCheck );
/*=== abcReadVerilog.c ========================================================*/
extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck );
/*=== abcWriteAiger.c =========================================================*/

View File

@ -28,7 +28,7 @@ ABC_NAMESPACE_IMPL_START
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth );
static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth, int fSkipPrepro );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
@ -326,7 +326,7 @@ void Io_ReadPlaCubePreprocess( Vec_Str_t * vSop, int iCover, int fVerbose )
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fBoth, int fCheck )
Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fBoth, int fSkipPrepro, int fCheck )
{
Extra_FileReader_t * p;
Abc_Ntk_t * pNtk;
@ -338,7 +338,7 @@ Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fBoth, int fCheck )
return NULL;
// read the network
pNtk = Io_ReadPlaNetwork( p, fZeros, fBoth );
pNtk = Io_ReadPlaNetwork( p, fZeros, fBoth, fSkipPrepro );
Extra_FileReaderFree( p );
if ( pNtk == NULL )
return NULL;
@ -363,7 +363,7 @@ Abc_Ntk_t * Io_ReadPla( char * pFileName, int fZeros, int fBoth, int fCheck )
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth )
Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth, int fSkipPrepro )
{
ProgressBar * pProgress;
Vec_Ptr_t * vTokens;
@ -567,7 +567,8 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p, int fZeros, int fBoth )
continue;
}
Vec_StrPush( ppSops[i], 0 );
Io_ReadPlaCubePreprocess( ppSops[i], i, 0 );
if ( !fSkipPrepro )
Io_ReadPlaCubePreprocess( ppSops[i], i, 0 );
pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, ppSops[i]->pArray );
Vec_StrFree( ppSops[i] );
}

View File

@ -144,7 +144,7 @@ Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck
else if ( FileType == IO_FILE_EQN )
pNtk = Io_ReadEqn( pFileName, fCheck );
else if ( FileType == IO_FILE_PLA )
pNtk = Io_ReadPla( pFileName, 0, 0, fCheck );
pNtk = Io_ReadPla( pFileName, 0, 0, 0, fCheck );
else if ( FileType == IO_FILE_VERILOG )
pNtk = Io_ReadVerilog( pFileName, fCheck );
else