Compare commits

..

No commits in common. "yosys-experimental" and "v0.68" have entirely different histories.

68 changed files with 18080 additions and 21992 deletions

View File

@ -35,7 +35,7 @@ OS := $(shell uname -s)
MODULES := \ MODULES := \
$(wildcard src/ext*) \ $(wildcard src/ext*) \
src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \ src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \
src/base/ver src/base/wlc src/base/wln src/base/sn src/base/acb src/base/pla src/base/test \ src/base/ver src/base/wlc src/base/wln src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \
src/map/mapper src/map/mio src/map/super src/map/if src/map/if/acd \ src/map/mapper src/map/mio src/map/super src/map/if src/map/if/acd \
src/map/amap src/map/cov src/map/scl src/map/mpm src/map/emap \ src/map/amap src/map/cov src/map/scl src/map/mpm src/map/emap \
src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \ src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \

View File

@ -918,6 +918,138 @@ SOURCE=.\src\base\pla\plaSimple.c
SOURCE=.\src\base\pla\plaWrite.c SOURCE=.\src\base\pla\plaWrite.c
# End Source File # End Source File
# End Group # End Group
# Begin Group "bac"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\base\bac\bac.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bac.h
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacBac.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacBlast.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacCom.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacLib.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacNtk.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacOper.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacPrs.h
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacPrsBuild.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacPrsTrans.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacPtr.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacPtrAbc.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacReadBlif.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacReadSmt.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacReadVer.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacWriteBlif.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacWriteSmt.c
# End Source File
# Begin Source File
SOURCE=.\src\base\bac\bacWriteVer.c
# End Source File
# End Group
# Begin Group "cba"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\base\cba\cba.c
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cba.h
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaBlast.c
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaCba.c
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaCom.c
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaNtk.c
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaPrs.h
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaReadBlif.c
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaReadVer.c
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaTypes.h
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaWriteBlif.c
# End Source File
# Begin Source File
SOURCE=.\src\base\cba\cbaWriteVer.c
# End Source File
# End Group
# Begin Group "exor" # Begin Group "exor"
# PROP Default_Filter "" # PROP Default_Filter ""
@ -971,6 +1103,10 @@ SOURCE=.\src\base\acb\acbAig.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\src\base\acb\acbCom.c
# End Source File
# Begin Source File
SOURCE=.\src\base\acb\acbFunc.c SOURCE=.\src\base\acb\acbFunc.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@ -1004,14 +1140,6 @@ SOURCE=.\src\base\acb\acbUtil.c
# End Group # End Group
# Begin Group "wln" # Begin Group "wln"
SOURCE=.\src\base\acb\acbXec.c
# End Source File
# Begin Source File
SOURCE=.\src\base\acb\acbXec.h
# End Source File
# Begin Source File
# PROP Default_Filter "" # PROP Default_Filter ""
# Begin Source File # Begin Source File
@ -1070,74 +1198,6 @@ SOURCE=.\src\base\wln\wlnWlc.c
SOURCE=.\src\base\wln\wlnWriteVer.c SOURCE=.\src\base\wln\wlnWriteVer.c
# End Source File # End Source File
# End Group # End Group
# Begin Group "sn"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\base\sn\sn.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snTech.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMapDsp.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMapMem.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMapAdd.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMapTech.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snCheck.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snBoundary.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMapLut.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snPth.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snBlast.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMiniAig.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMiniLut.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMiniGate.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snMux.h
# End Source File
# Begin Source File
SOURCE=.\src\base\sn\snCom.c
# End Source File
# End Group
# End Group # End Group
# Begin Group "bdd" # Begin Group "bdd"

View File

@ -2211,106 +2211,4 @@ Gia_Man_t* Gia_ManDecGraphFromFile(char* pFileName) {
return pNew; return pNew;
} }
extern "C" int Gia_ManVerifyTruthFile(Gia_Man_t* p, char* pFileName, int fVerbose) {
const int nIns = Gia_ManCiNum(p);
const int nOuts = Gia_ManCoNum(p);
char* pBuffer;
char* table;
uint64_t nBits;
int iOut = 0;
int result = -1;
if (Gia_ManRegNum(p) != 0) {
Abc_Print(-1, "Truth-table verification requires a combinational network.\n");
return -1;
}
if (nIns >= 63) {
Abc_Print(-1, "A .truth file cannot represent a network with %d inputs.\n", nIns);
return -1;
}
nBits = (uint64_t)1 << nIns;
pBuffer = Extra_FileReadContents(pFileName);
if (pBuffer == NULL) {
Abc_Print(-1, "Cannot read truth-table file \"%s\".\n", pFileName);
return -1;
}
Abc_CexFreeP(&p->pCexComb);
Gia_ObjComputeTruthTableStart(p, nIns);
table = strtok(pBuffer, " \r\n\t|");
while (table != NULL) {
const uint64_t tableSize = strlen(table);
DecGraph::TruthTable fileTruth;
DecGraph::TruthTable giaTruth;
Gia_Obj_t* pObj;
word* pTruth;
uint64_t i;
if (iOut == nOuts) {
Abc_Print(-1, "Truth-table file \"%s\" has more than %d outputs.\n", pFileName, nOuts);
goto finish;
}
if (tableSize != nBits) {
Abc_Print(-1, "Output %d in truth-table file \"%s\" has %llu bits; expected %llu for %d inputs.\n",
iOut, pFileName, (unsigned long long)tableSize, (unsigned long long)nBits, nIns);
goto finish;
}
for (i = 0; i < tableSize; ++i) {
if (table[i] != '0' && table[i] != '1') {
Abc_Print(-1, "Unexpected character '%c' in output %d of truth-table file \"%s\".\n",
table[i], iOut, pFileName);
goto finish;
}
}
fileTruth.readBinaryReverse(table);
giaTruth.create(nBits);
pObj = Gia_ManCo(p, iOut);
pTruth = Gia_ObjComputeTruthTable(p, Gia_ObjFanin0(pObj));
if (nIns >= 6) {
for (i = 0; i < giaTruth.nWords(); ++i)
giaTruth.data()[i] = Gia_ObjFaninC0(pObj) ? ~DecGraph::reverseBits(pTruth[i]) : DecGraph::reverseBits(pTruth[i]);
} else {
word value = (Gia_ObjFaninC0(pObj) ? ~pTruth[0] : pTruth[0]) & DecGraph::ones_mask[nIns];
giaTruth.data()[0] = DecGraph::reverseBits(value);
}
if (fileTruth != giaTruth) {
uint64_t iMint = 0;
p->pCexComb = Abc_CexAlloc(0, nIns, 1);
p->pCexComb->iPo = iOut;
for (i = 0; i < fileTruth.nWords(); ++i) {
word diff = fileTruth.data()[i] ^ giaTruth.data()[i];
if (diff == 0)
continue;
for (int b = 0; b < 64; ++b)
if (diff & ((word)1 << (63 - b))) {
iMint = 64 * i + b;
break;
}
break;
}
for (int v = 0; v < nIns; ++v)
if ((iMint >> v) & 1)
Abc_InfoSetBit(p->pCexComb->pData, v);
if (fVerbose)
Abc_Print(1, "Truth tables differ for output %d at minterm %llu.\n", iOut, (unsigned long long)iMint);
result = 0;
goto finish;
}
++iOut;
table = strtok(NULL, " \r\n\t|");
}
if (iOut != nOuts) {
Abc_Print(-1, "Truth-table file \"%s\" has %d outputs; expected %d.\n", pFileName, iOut, nOuts);
goto finish;
}
result = 1;
finish:
Gia_ObjComputeTruthTableStop(p);
ABC_FREE(pBuffer);
return result;
}
ABC_NAMESPACE_IMPL_END ABC_NAMESPACE_IMPL_END

View File

@ -351,20 +351,6 @@ static int Mini_AigAndMulti( Mini_Aig_t * p, int * pLits, int nLits )
} }
return pLits[0]; return pLits[0];
} }
static int Mini_AigXorMulti( Mini_Aig_t * p, int * pLits, int nLits )
{
int i;
assert( nLits > 0 );
while ( nLits > 1 )
{
for ( i = 0; i < nLits/2; i++ )
pLits[i] = Mini_AigXor(p, pLits[2*i], pLits[2*i+1]);
if ( nLits & 1 )
pLits[i++] = pLits[nLits-1];
nLits = i;
}
return pLits[0];
}
static int Mini_AigMuxMulti( Mini_Aig_t * p, int * pCtrl, int nCtrl, int * pData, int nData ) static int Mini_AigMuxMulti( Mini_Aig_t * p, int * pCtrl, int nCtrl, int * pData, int nData )
{ {
int i, c; int i, c;
@ -861,3 +847,4 @@ ABC_NAMESPACE_HEADER_END
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
/// END OF FILE /// /// END OF FILE ///
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////

View File

@ -64,6 +64,7 @@
#include "map/mio/mio.h" #include "map/mio/mio.h"
#include "opt/fret/fretime.h" #include "opt/fret/fretime.h"
#include "opt/nwk/nwkMerge.h" #include "opt/nwk/nwkMerge.h"
#include "base/acb/acbPar.h"
#include "base/wln/wln.h" #include "base/wln/wln.h"
#include "misc/extra/extra.h" #include "misc/extra/extra.h"
#include "opt/eslim/eSLIM.h" #include "opt/eslim/eSLIM.h"
@ -131,6 +132,7 @@ static int Abc_CommandLutmin ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandMfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMfs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMfs2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMfs2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMfs3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMfs3 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMfse ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandLogicPush ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLogicPush ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTrace ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandGlitch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGlitch ( Abc_Frame_t * pAbc, int argc, char ** argv );
@ -700,11 +702,6 @@ extern int Cec_GiaReplayTest( Gia_Man_t * p, Wlc_Ntk_t * pWlc, char * pFileName,
/// FUNCTION DEFINITIONS /// /// FUNCTION DEFINITIONS ///
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C"
#endif
int Gia_ManVerifyTruthFile( Gia_Man_t * p, char * pFileName, int fVerbose );
/**Function************************************************************* /**Function*************************************************************
Synopsis [] Synopsis []
@ -989,6 +986,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Synthesis", "mfs", Abc_CommandMfs, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mfs", Abc_CommandMfs, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "mfs2", Abc_CommandMfs2, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mfs2", Abc_CommandMfs2, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "mfs3", Abc_CommandMfs3, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mfs3", Abc_CommandMfs3, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "mfse", Abc_CommandMfse, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "logicpush", Abc_CommandLogicPush, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "logicpush", Abc_CommandLogicPush, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "trace", Abc_CommandTrace, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "trace", Abc_CommandTrace, 0 );
Cmd_CommandAdd( pAbc, "Synthesis", "glitch", Abc_CommandGlitch, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "glitch", Abc_CommandGlitch, 0 );
@ -6282,6 +6280,155 @@ usage:
return 1; return 1;
} }
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern Abc_Ntk_t * Abc_NtkOptMfse( Abc_Ntk_t * pNtk, Acb_Par_t * pPars );
Abc_Ntk_t * pNtkNew, * pNtk = Abc_FrameReadNtk(pAbc);
Acb_Par_t Pars, * pPars = &Pars; int c;
Acb_ParSetDefault( pPars );
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "IOWFLCadvwh" ) ) != EOF )
{
switch ( c )
{
case 'I':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" );
goto usage;
}
pPars->nTfiLevMax = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( pPars->nTfiLevMax < 0 )
goto usage;
break;
case 'O':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" );
goto usage;
}
pPars->nTfoLevMax = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( pPars->nTfoLevMax < 0 )
goto usage;
break;
case 'W':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" );
goto usage;
}
pPars->nWinNodeMax = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( pPars->nWinNodeMax < 0 )
goto usage;
break;
case 'F':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" );
goto usage;
}
pPars->nFanoutMax = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( pPars->nFanoutMax < 0 )
goto usage;
break;
case 'L':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" );
goto usage;
}
pPars->nGrowthLevel = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( pPars->nGrowthLevel < -ABC_INFINITY || pPars->nGrowthLevel > ABC_INFINITY )
goto usage;
break;
case 'C':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
pPars->nBTLimit = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( pPars->nBTLimit < 0 )
goto usage;
break;
case 'a':
pPars->fArea ^= 1;
break;
case 'd':
pPars->fUseAshen ^= 1;
break;
case 'v':
pPars->fVerbose ^= 1;
break;
case 'w':
pPars->fVeryVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( pNtk == NULL )
{
Abc_Print( -1, "Empty network.\n" );
return 1;
}
if ( !Abc_NtkIsLogic(pNtk) )
{
Abc_Print( -1, "This command can only be applied to a logic network.\n" );
return 1;
}
pPars->nLutSize = Abc_NtkGetFaninMax( pNtk );
if ( pPars->nLutSize > 6 )
{
Abc_Print( -1, "Command is only applicable to LUT size no more than 6.\n" );
return 1;
}
Abc_NtkToSop( pNtk, -1, ABC_INFINITY );
pNtkNew = Abc_NtkOptMfse( pNtk, pPars );
if ( pNtkNew == NULL )
{
Abc_Print( -1, "Command \"mfse\" has failed.\n" );
return 1;
}
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew );
return 0;
usage:
Abc_Print( -2, "usage: mfse [-IOWFLC <num>] [-advwh]\n" );
Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" );
Abc_Print( -2, "\t-I <num> : the number of levels in the TFI cone (2 <= num) [default = %d]\n", pPars->nTfiLevMax );
Abc_Print( -2, "\t-O <num> : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax );
Abc_Print( -2, "\t-W <num> : the max number of nodes in the window (1 <= num) [default = %d]\n", pPars->nWinNodeMax );
Abc_Print( -2, "\t-F <num> : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax );
Abc_Print( -2, "\t-L <num> : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel );
Abc_Print( -2, "\t-C <num> : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit );
Abc_Print( -2, "\t-a : toggle minimizing area [default = %s]\n", pPars->fArea? "area": "delay" );
Abc_Print( -2, "\t-d : toggle using Ashenhurst decomposition [default = %s]\n", pPars->fUseAshen? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" );
Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function************************************************************* /**Function*************************************************************
Synopsis [] Synopsis []
@ -7813,17 +7960,14 @@ usage:
***********************************************************************/ ***********************************************************************/
int Abc_CommandRunTest( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandRunTest( Abc_Frame_t * pAbc, int argc, char ** argv )
{ {
extern void Acb_NtkRunTest( char * pFileNames[4], int fFancy, int fVerbose, int fUseCadical ); extern void Acb_NtkRunTest( char * pFileNames[4], int fFancy, int fVerbose );
char * pFileNames[4] = {NULL}; char * pFileNames[4] = {NULL};
int c, fFancy = 0, fVerbose = 0, fUseCadical = 0; int c, fFancy = 0, fVerbose = 0;
Extra_UtilGetoptReset(); Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "cfvh" ) ) != EOF ) while ( ( c = Extra_UtilGetopt( argc, argv, "fvh" ) ) != EOF )
{ {
switch ( c ) switch ( c )
{ {
case 'c':
fUseCadical ^= 1;
break;
case 'f': case 'f':
fFancy ^= 1; fFancy ^= 1;
break; break;
@ -7843,13 +7987,12 @@ int Abc_CommandRunTest( Abc_Frame_t * pAbc, int argc, char ** argv )
} }
for ( c = 0; c < argc - globalUtilOptind; c++ ) for ( c = 0; c < argc - globalUtilOptind; c++ )
pFileNames[c] = argv[globalUtilOptind+c]; pFileNames[c] = argv[globalUtilOptind+c];
Acb_NtkRunTest( pFileNames, fFancy, fVerbose, fUseCadical ); Acb_NtkRunTest( pFileNames, fFancy, fVerbose );
return 0; return 0;
usage: usage:
Abc_Print( -2, "usage: xec [-cfvh] <file1> <file2>\n" ); Abc_Print( -2, "usage: xec [-fvh] <file1> <file2>\n" );
Abc_Print( -2, "\t combinational equivalence checking with x-values\n" ); Abc_Print( -2, "\t combinational equivalence checking with x-values\n" );
Abc_Print( -2, "\t-c : toggle using CaDiCaL SAT-only solving [default = %s]\n", fUseCadical? "yes": "no" );
Abc_Print( -2, "\t-f : toggle using experimental feature [default = %s]\n", fFancy? "yes": "no" ); Abc_Print( -2, "\t-f : toggle using experimental feature [default = %s]\n", fFancy? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t-h : print the command usage\n");
@ -43740,29 +43883,6 @@ static Gia_Man_t * Abc_ReadAigerOrVerilogFile( char * pFileName, char * pFileNam
return pGia; return pGia;
} }
/**Function*************************************************************
Synopsis [Returns 1 if all outputs of the swept miter are constant 0.]
Description [The equivalence check below concludes from the swept miter
having no AND nodes. An AND-free GIA can still have outputs that are
constant 1 or CI literals, which are satisfiable, so the outputs are
checked here as well.]
SideEffects []
SeeAlso []
***********************************************************************/
static int Abc_CecSweptMiterIsConst0( Gia_Man_t * p )
{
int i;
for ( i = 0; i < Gia_ManPoNum(p); i++ )
if ( !Gia_ManPoIsConst0(p, i) )
return 0;
return 1;
}
/**Function************************************************************* /**Function*************************************************************
Synopsis [] Synopsis []
@ -44060,29 +44180,6 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv )
} }
FileName = pAbc->pGia->pSpec; FileName = pAbc->pGia->pSpec;
} }
if ( fUseSim && nArgcNew == 1 && !strcmp( Extra_FileNameExtension(FileName), "truth" ) )
{
abctime clk = Abc_Clock();
int Status = Gia_ManVerifyTruthFile( pGias[0], FileName, pPars->fVerbose );
if ( Status == 1 )
Abc_Print( 1, "Network and truth table are equivalent. " );
else if ( Status == 0 )
Abc_Print( 1, "Network and truth table are NOT equivalent. " );
else
{
Vec_PtrFree( vDefines );
Vec_PtrFree( vBoxes );
Vec_PtrFree( vInsts );
return 1;
}
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
pAbc->Status = Status;
Abc_FrameReplaceCex( pAbc, &pGias[0]->pCexComb );
Vec_PtrFree( vDefines );
Vec_PtrFree( vBoxes );
Vec_PtrFree( vInsts );
return 0;
}
pGias[1] = Abc_ReadAigerOrVerilogFile( FileName, pFileName2, pTopModule, vDefines, vBoxes, vInsts, &Abc_ReadAigerOrVerilogFileStatus ); pGias[1] = Abc_ReadAigerOrVerilogFile( FileName, pFileName2, pTopModule, vDefines, vBoxes, vInsts, &Abc_ReadAigerOrVerilogFileStatus );
if ( pGias[1] == NULL ) if ( pGias[1] == NULL )
{ {
@ -44191,12 +44288,10 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv )
abctime clk = Abc_Clock(); abctime clk = Abc_Clock();
extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose );
Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose ); Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose );
if ( Gia_ManAndNum(pNew) != 0 ) if ( Gia_ManAndNum(pNew) == 0 )
Abc_Print( 1, "Networks are UNDECIDED. " );
else if ( Abc_CecSweptMiterIsConst0(pNew) )
Abc_Print( 1, "Networks are equivalent. " ); Abc_Print( 1, "Networks are equivalent. " );
else else
Abc_Print( 1, "Networks are NOT equivalent. " ); Abc_Print( 1, "Networks are UNDECIDED. " );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
Gia_ManStop( pNew ); Gia_ManStop( pNew );
} }
@ -44205,12 +44300,10 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv )
abctime clk = Abc_Clock(); abctime clk = Abc_Clock();
extern Gia_Man_t * Cec5_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); extern Gia_Man_t * Cec5_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose );
Gia_Man_t * pNew = Cec5_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose ); Gia_Man_t * pNew = Cec5_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose );
if ( Gia_ManAndNum(pNew) != 0 ) if ( Gia_ManAndNum(pNew) == 0 )
Abc_Print( 1, "Networks are UNDECIDED. " );
else if ( Abc_CecSweptMiterIsConst0(pNew) )
Abc_Print( 1, "Networks are equivalent. " ); Abc_Print( 1, "Networks are equivalent. " );
else else
Abc_Print( 1, "Networks are NOT equivalent. " ); Abc_Print( 1, "Networks are UNDECIDED. " );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
Gia_ManStop( pNew ); Gia_ManStop( pNew );
} }
@ -44248,7 +44341,7 @@ usage:
Abc_Print( -2, "\t-s : toggle silent operation [default = %s]\n", pPars->fSilent ? "yes":"no"); Abc_Print( -2, "\t-s : toggle silent operation [default = %s]\n", pPars->fSilent ? "yes":"no");
Abc_Print( -2, "\t-x : toggle using new solver [default = %s]\n", fUseNewX? "yes":"no"); Abc_Print( -2, "\t-x : toggle using new solver [default = %s]\n", fUseNewX? "yes":"no");
Abc_Print( -2, "\t-y : toggle using new solver [default = %s]\n", fUseNewY? "yes":"no"); Abc_Print( -2, "\t-y : toggle using new solver [default = %s]\n", fUseNewY? "yes":"no");
Abc_Print( -2, "\t-t : toggle using simulation; accepts one .truth file for the current network [default = %s]\n", fUseSim? "yes":"no"); Abc_Print( -2, "\t-t : toggle using simulation [default = %s]\n", fUseSim? "yes":"no");
Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes":"no"); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes":"no");
Abc_Print( -2, "\t-w : toggle printing SAT solver statistics [default = %s]\n", pPars->fVeryVerbose? "yes":"no"); Abc_Print( -2, "\t-w : toggle printing SAT solver statistics [default = %s]\n", pPars->fVeryVerbose? "yes":"no");
Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t-h : print the command usage\n");
@ -44411,12 +44504,10 @@ int Abc_CommandAbc9ICec( Abc_Frame_t * pAbc, int argc, char ** argv )
abctime clk = Abc_Clock(); abctime clk = Abc_Clock();
extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose );
Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose ); Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose );
if ( Gia_ManAndNum(pNew) != 0 ) if ( Gia_ManAndNum(pNew) == 0 )
Abc_Print( 1, "Networks are UNDECIDED. " );
else if ( Abc_CecSweptMiterIsConst0(pNew) )
Abc_Print( 1, "Networks are equivalent. " ); Abc_Print( 1, "Networks are equivalent. " );
else else
Abc_Print( 1, "Networks are NOT equivalent. " ); Abc_Print( 1, "Networks are UNDECIDED. " );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
Gia_ManStop( pNew ); Gia_ManStop( pNew );
} }

View File

@ -670,29 +670,13 @@ int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd )
extern int Abc_NodeCompareCiCo( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); extern int Abc_NodeCompareCiCo( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew );
if ( !Abc_NodeCompareCiCo(pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0)) ) if ( !Abc_NodeCompareCiCo(pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0)) )
{ {
// Abc_NtkCompareSignals() sorts the PIs/POs/boxes of both networks by name as a
// side effect, which is what makes the comparison meaningful when the two do use
// the same names. When they do not, the comparison fails, the store is reset and
// this network is kept -- so the sort has to be undone here. Otherwise the stored
// network is a permutation of the one the caller read in, and everything after it
// is off by that permutation with nothing to indicate it.
Vec_Ptr_t * vPis = Vec_PtrDup( pNtk->vPis );
Vec_Ptr_t * vPos = Vec_PtrDup( pNtk->vPos );
Vec_Ptr_t * vBoxes = Vec_PtrDup( pNtk->vBoxes );
// reorder PIs of pNtk2 according to pNtk1 // reorder PIs of pNtk2 according to pNtk1
if ( !Abc_NtkCompareSignals( pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0), 1, 1 ) ) if ( !Abc_NtkCompareSignals( pNtk, (Abc_Ntk_t *)Vec_PtrEntry(vStore, 0), 1, 1 ) )
{ {
Vec_PtrFree( pNtk->vPis ); pNtk->vPis = vPis; vPis = NULL;
Vec_PtrFree( pNtk->vPos ); pNtk->vPos = vPos; vPos = NULL;
Vec_PtrFree( pNtk->vBoxes ); pNtk->vBoxes = vBoxes; vBoxes = NULL;
Abc_NtkOrderCisCos( pNtk );
printf( "Trying to store the network with different primary inputs.\n" ); printf( "Trying to store the network with different primary inputs.\n" );
printf( "The previously stored networks are deleted and this one is added.\n" ); printf( "The previously stored networks are deleted and this one is added.\n" );
Abc_NtkFraigStoreClean(); Abc_NtkFraigStoreClean();
} }
if ( vPis ) Vec_PtrFree( vPis );
if ( vPos ) Vec_PtrFree( vPos );
if ( vBoxes ) Vec_PtrFree( vBoxes );
} }
} }
Vec_PtrPush( vStore, pNtk ); Vec_PtrPush( vStore, pNtk );

View File

@ -925,79 +925,6 @@ void Abc_NtkDelayTraceCritPathCollect_rec( Vec_Int_t * vSlacks, Abc_Obj_t * pNod
Vec_PtrPush( vPath, pNode ); Vec_PtrPush( vPath, pNode );
} }
/**Function*************************************************************
Synopsis [Checks if the library has non-zero fanout delays.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static int Abc_LibraryHasFanoutDelay( Mio_Library_t * pLib )
{
Mio_Gate_t * pGate;
Mio_Pin_t * pPin;
Mio_LibraryForEachGate( pLib, pGate )
Mio_GateForEachPin( pGate, pPin )
if ( Mio_PinReadDelayFanoutRise(pPin) != 0.0 || Mio_PinReadDelayFanoutFall(pPin) != 0.0 )
return 1;
return 0;
}
static float Abc_LibraryReadOutputLoad( Mio_Library_t * pLib )
{
// use the inverter input load as the library-derived default CO load
Mio_Gate_t * pGate = Mio_LibraryReadInv( pLib );
Mio_Pin_t * pPin;
if ( pGate == NULL )
pGate = Mio_LibraryReadBuf( pLib );
pPin = pGate ? Mio_GateReadPins(pGate) : NULL;
return pPin ? (float)Mio_PinReadInputLoad(pPin) : 0.0;
}
/**Function*************************************************************
Synopsis [Computes the load driven by the node output.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static float Abc_NodeDelayLoad( Abc_Obj_t * pNode, float OutputLoad )
{
Abc_Obj_t * pFanout;
Mio_Pin_t * pPin;
float Load = 0.0;
int i, k, iFanin;
Abc_ObjForEachFanout( pNode, pFanout, i )
{
if ( Abc_ObjIsCo(pFanout) )
{
Load += OutputLoad;
continue;
}
if ( !Abc_ObjIsNode(pFanout) || pFanout->pData == NULL )
{
Load += OutputLoad;
continue;
}
iFanin = Abc_NodeFindFanin( pFanout, pNode );
assert( iFanin >= 0 );
pPin = Mio_GateReadPins( (Mio_Gate_t *)pFanout->pData );
for ( k = 0; k < iFanin; k++ )
pPin = Mio_PinReadNext( pPin );
assert( pPin != NULL );
Load += (float)Mio_PinReadInputLoad( pPin );
}
return Load;
}
/**Function************************************************************* /**Function*************************************************************
Synopsis [] Synopsis []
@ -1009,11 +936,11 @@ static float Abc_NodeDelayLoad( Abc_Obj_t * pNode, float OutputLoad )
SeeAlso [] SeeAlso []
***********************************************************************/ ***********************************************************************/
static void Abc_NodeDelayTraceArrivalInt( Abc_Obj_t * pNode, Vec_Int_t * vSlacks, int fUseFanoutDelay, float OutputLoad ) void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
{ {
Abc_Obj_t * pFanin; Abc_Obj_t * pFanin;
Abc_Time_t * pTimeIn, * pTimeOut; Abc_Time_t * pTimeIn, * pTimeOut;
float tDelayBlockRise, tDelayBlockFall, Load; float tDelayBlockRise, tDelayBlockFall;
Mio_PinPhase_t PinPhase; Mio_PinPhase_t PinPhase;
Mio_Pin_t * pPin; Mio_Pin_t * pPin;
int i; int i;
@ -1028,7 +955,6 @@ static void Abc_NodeDelayTraceArrivalInt( Abc_Obj_t * pNode, Vec_Int_t * vSlacks
*pTimeOut = *pTimeIn; *pTimeOut = *pTimeIn;
return; return;
} }
Load = fUseFanoutDelay ? Abc_NodeDelayLoad(pNode, OutputLoad) : 0.0;
// go through the pins of the gate // go through the pins of the gate
pPin = Mio_GateReadPins((Mio_Gate_t *)pNode->pData); pPin = Mio_GateReadPins((Mio_Gate_t *)pNode->pData);
Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_ObjForEachFanin( pNode, pFanin, i )
@ -1038,11 +964,6 @@ static void Abc_NodeDelayTraceArrivalInt( Abc_Obj_t * pNode, Vec_Int_t * vSlacks
PinPhase = Mio_PinReadPhase(pPin); PinPhase = Mio_PinReadPhase(pPin);
tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );
if ( fUseFanoutDelay )
{
tDelayBlockRise += (float)Mio_PinReadDelayFanoutRise( pPin ) * Load;
tDelayBlockFall += (float)Mio_PinReadDelayFanoutFall( pPin ) * Load;
}
// compute the arrival times of the positive phase // compute the arrival times of the positive phase
if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present
{ {
@ -1074,11 +995,6 @@ static void Abc_NodeDelayTraceArrivalInt( Abc_Obj_t * pNode, Vec_Int_t * vSlacks
PinPhase = Mio_PinReadPhase(pPin); PinPhase = Mio_PinReadPhase(pPin);
tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin );
tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin );
if ( fUseFanoutDelay )
{
tDelayBlockRise += (float)Mio_PinReadDelayFanoutRise( pPin ) * Load;
tDelayBlockFall += (float)Mio_PinReadDelayFanoutFall( pPin ) * Load;
}
// compute the arrival times of the positive phase // compute the arrival times of the positive phase
Slack = ABC_INFINITY; Slack = ABC_INFINITY;
if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present
@ -1097,13 +1013,6 @@ static void Abc_NodeDelayTraceArrivalInt( Abc_Obj_t * pNode, Vec_Int_t * vSlacks
} }
} }
void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode, Vec_Int_t * vSlacks )
{
Mio_Library_t * pLib = (Mio_Library_t *)pNode->pNtk->pManFunc;
int fUseFanoutDelay = Abc_LibraryHasFanoutDelay( pLib );
Abc_NodeDelayTraceArrivalInt( pNode, vSlacks, fUseFanoutDelay, Abc_LibraryReadOutputLoad(pLib) );
}
/**Function************************************************************* /**Function*************************************************************
@ -1125,8 +1034,8 @@ float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, in
Abc_Obj_t * pNode, * pDriver; Abc_Obj_t * pNode, * pDriver;
Vec_Ptr_t * vNodes; Vec_Ptr_t * vNodes;
Abc_Time_t * pTime; Abc_Time_t * pTime;
float tArrivalMax, OutputLoad; float tArrivalMax;
int i, fUseFanoutDelay; int i;
assert( Abc_NtkIsMappedLogic(pNtk) ); assert( Abc_NtkIsMappedLogic(pNtk) );
assert( pOut == NULL || Abc_ObjIsCo(pOut) ); assert( pOut == NULL || Abc_ObjIsCo(pOut) );
@ -1136,14 +1045,11 @@ float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, in
if ( pOut || pIn || fPrint ) if ( pOut || pIn || fPrint )
vSlacks = Abc_NtkDelayTraceSlackStart( pNtk ); vSlacks = Abc_NtkDelayTraceSlackStart( pNtk );
fUseFanoutDelay = Abc_LibraryHasFanoutDelay( (Mio_Library_t *)pNtk->pManFunc );
OutputLoad = Abc_LibraryReadOutputLoad( (Mio_Library_t *)pNtk->pManFunc );
// compute the timing // compute the timing
Abc_NtkTimePrepare( pNtk ); Abc_NtkTimePrepare( pNtk );
vNodes = Abc_NtkDfs( pNtk, 1 ); vNodes = Abc_NtkDfs( pNtk, 1 );
Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
Abc_NodeDelayTraceArrivalInt( pNode, vSlacks, fUseFanoutDelay, OutputLoad ); Abc_NodeDelayTraceArrival( pNode, vSlacks );
Vec_PtrFree( vNodes ); Vec_PtrFree( vNodes );
// get the latest arrival times // get the latest arrival times
@ -1531,3 +1437,4 @@ void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels )
ABC_NAMESPACE_IMPL_END ABC_NAMESPACE_IMPL_END

735
src/base/acb/acbCom.c Normal file
View File

@ -0,0 +1,735 @@
/**CFile****************************************************************
FileName [acbCom.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Command handlers.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: acbCom.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "acb.h"
#include "proof/cec/cec.h"
#include "base/main/mainInt.h"
ABC_NAMESPACE_IMPL_START
#if 0
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Acb_CommandRead ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Acb_CommandWrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Acb_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Acb_CommandPut ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Acb_CommandGet ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Acb_CommandClp ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Acb_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Acb_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Acb_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
static inline Acb_Man_t * Acb_AbcGetMan( Abc_Frame_t * pAbc ) { return (Acb_Man_t *)pAbc->pAbcCba; }
static inline void Acb_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcCba ) Acb_ManFree(Acb_AbcGetMan(pAbc)); }
static inline void Acb_AbcUpdateMan( Abc_Frame_t * pAbc, Acb_Man_t * p ) { Acb_AbcFreeMan(pAbc); pAbc->pAbcCba = p; }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Acb_Init( Abc_Frame_t * pAbc )
{
Cmd_CommandAdd( pAbc, "New word level", "@read", Acb_CommandRead, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@write", Acb_CommandWrite, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@ps", Acb_CommandPs, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@put", Acb_CommandPut, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@get", Acb_CommandGet, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@clp", Acb_CommandClp, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@blast", Acb_CommandBlast, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@cec", Acb_CommandCec, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@test", Acb_CommandTest, 0 );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Acb_End( Abc_Frame_t * pAbc )
{
Acb_AbcFreeMan( pAbc );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pFile;
Acb_Man_t * p = NULL;
char * pFileName = NULL;
int c, fTest = 0, fDfs = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "tdvh" ) ) != EOF )
{
switch ( c )
{
case 't':
fTest ^= 1;
break;
case 'd':
fDfs ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( argc != globalUtilOptind + 1 )
{
printf( "Acb_CommandRead(): Input file name should be given on the command line.\n" );
return 0;
}
// get the file name
pFileName = argv[globalUtilOptind];
if ( (pFile = fopen( pFileName, "r" )) == NULL )
{
Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName );
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", ".smt", ".acb", NULL )) )
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
Abc_Print( 1, "\n" );
return 0;
}
fclose( pFile );
if ( fTest )
{
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
Prs_ManReadBlifTest( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
Prs_ManReadVerilogTest( pFileName );
else
{
printf( "Unrecognized input file extension.\n" );
return 0;
}
return 0;
}
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
p = Acb_ManReadBlif( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
p = Acb_ManReadVerilog( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "acb" ) )
p = Acb_ManReadCba( pFileName );
else
{
printf( "Unrecognized input file extension.\n" );
return 0;
}
if ( fDfs )
{
Acb_Man_t * pTemp;
p = Acb_ManDup( pTemp = p, Acb_NtkCollectDfs );
Acb_ManFree( pTemp );
}
Acb_AbcUpdateMan( pAbc, p );
return 0;
usage:
Abc_Print( -2, "usage: @read [-tdvh] <file_name>\n" );
Abc_Print( -2, "\t reads hierarchical design\n" );
Abc_Print( -2, "\t-t : toggle testing the parser [default = %s]\n", fTest? "yes": "no" );
Abc_Print( -2, "\t-d : toggle computing DFS ordering [default = %s]\n", fDfs? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandWrite( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
char * pFileName = NULL;
int fInclineCats = 0;
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF )
{
switch ( c )
{
case 'c':
fInclineCats ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Acb_CommandWrite(): There is no current design.\n" );
return 0;
}
if ( argc == globalUtilOptind + 1 )
pFileName = argv[globalUtilOptind];
else if ( argc == globalUtilOptind && p )
{
pFileName = Extra_FileNameGenericAppend( Acb_ManSpec(p) ? Acb_ManSpec(p) : Acb_ManName(p), "_out.v" );
printf( "Generated output file name \"%s\".\n", pFileName );
}
else
{
printf( "Output file name should be given on the command line.\n" );
return 0;
}
// perform writing
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
Acb_ManWriteBlif( pFileName, p );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
Acb_ManWriteVerilog( pFileName, p, fInclineCats );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "acb" ) )
Acb_ManWriteCba( pFileName, p );
else
{
printf( "Unrecognized output file extension.\n" );
return 0;
}
return 0;
usage:
Abc_Print( -2, "usage: @write [-cvh]\n" );
Abc_Print( -2, "\t writes the design into a file in BLIF or Verilog\n" );
Abc_Print( -2, "\t-c : toggle inlining input concatenations [default = %s]\n", fInclineCats? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
int nModules = 0;
int fShowMulti = 0;
int fShowAdder = 0;
int fDistrib = 0;
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "Mmadvh" ) ) != EOF )
{
switch ( c )
{
case 'M':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
goto usage;
}
nModules = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nModules < 0 )
goto usage;
break;
case 'm':
fShowMulti ^= 1;
break;
case 'a':
fShowAdder ^= 1;
break;
case 'd':
fDistrib ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Acb_CommandPs(): There is no current design.\n" );
return 0;
}
if ( nModules )
{
Acb_ManPrintStats( p, nModules, fVerbose );
return 0;
}
Acb_NtkPrintStatsFull( Acb_ManRoot(p), fDistrib, fVerbose );
if ( fShowMulti )
Acb_NtkPrintNodes( Acb_ManRoot(p), ABC_OPER_ARI_MUL );
if ( fShowAdder )
Acb_NtkPrintNodes( Acb_ManRoot(p), ABC_OPER_ARI_ADD );
return 0;
usage:
Abc_Print( -2, "usage: @ps [-M num] [-madvh]\n" );
Abc_Print( -2, "\t prints statistics\n" );
Abc_Print( -2, "\t-M num : the number of first modules to report [default = %d]\n", nModules );
Abc_Print( -2, "\t-m : toggle printing multipliers [default = %s]\n", fShowMulti? "yes": "no" );
Abc_Print( -2, "\t-a : toggle printing adders [default = %s]\n", fShowAdder? "yes": "no" );
Abc_Print( -2, "\t-d : toggle printing distrubition [default = %s]\n", fDistrib? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandPut( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
Gia_Man_t * pGia = NULL;
int c, fBarBufs = 1, fSeq = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "bsvh" ) ) != EOF )
{
switch ( c )
{
case 'b':
fBarBufs ^= 1;
break;
case 's':
fSeq ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Acb_CommandPut(): There is no current design.\n" );
return 0;
}
pGia = Acb_ManBlast( p, fBarBufs, fSeq, fVerbose );
if ( pGia == NULL )
{
Abc_Print( 1, "Acb_CommandPut(): Conversion to AIG has failed.\n" );
return 0;
}
Abc_FrameUpdateGia( pAbc, pGia );
return 0;
usage:
Abc_Print( -2, "usage: @put [-bsvh]\n" );
Abc_Print( -2, "\t extracts AIG from the hierarchical design\n" );
Abc_Print( -2, "\t-b : toggle using barrier buffers [default = %s]\n", fBarBufs? "yes": "no" );
Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandGet( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Acb_Man_t * pNew = NULL, * p = Acb_AbcGetMan(pAbc);
int c, fMapped = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF )
{
switch ( c )
{
case 'm':
fMapped ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Acb_CommandGet(): There is no current design.\n" );
return 0;
}
if ( fMapped )
{
if ( pAbc->pNtkCur == NULL )
{
Abc_Print( 1, "Acb_CommandGet(): There is no current mapped design.\n" );
return 0;
}
pNew = Acb_ManInsertAbc( p, pAbc->pNtkCur );
}
else
{
if ( pAbc->pGia == NULL )
{
Abc_Print( 1, "Acb_CommandGet(): There is no current AIG.\n" );
return 0;
}
pNew = Acb_ManInsertGia( p, pAbc->pGia );
}
Acb_AbcUpdateMan( pAbc, pNew );
return 0;
usage:
Abc_Print( -2, "usage: @get [-mvh]\n" );
Abc_Print( -2, "\t extracts AIG or mapped network into the hierarchical design\n" );
Abc_Print( -2, "\t-m : toggle using mapped network from main-space [default = %s]\n", fMapped? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandClp( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Acb_Man_t * pNew = NULL, * p = Acb_AbcGetMan(pAbc);
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Acb_CommandGet(): There is no current design.\n" );
return 0;
}
pNew = Acb_ManCollapse( p );
Acb_AbcUpdateMan( pAbc, pNew );
return 0;
usage:
Abc_Print( -2, "usage: @clp [-vh]\n" );
Abc_Print( -2, "\t collapses the current hierarchical design\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Gia_Man_t * pNew = NULL;
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
int c, fSeq = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
{
switch ( c )
{
case 's':
fSeq ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Acb_CommandBlast(): There is no current design.\n" );
return 0;
}
pNew = Acb_ManBlast( p, 0, fSeq, fVerbose );
if ( pNew == NULL )
{
Abc_Print( 1, "Acb_CommandBlast(): Bit-blasting has failed.\n" );
return 0;
}
Abc_FrameUpdateGia( pAbc, pNew );
return 0;
usage:
Abc_Print( -2, "usage: @blast [-svh]\n" );
Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" );
Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Acb_Man_t * p = Acb_AbcGetMan(pAbc), * pTemp;
Gia_Man_t * pFirst, * pSecond, * pMiter;
Cec_ParCec_t ParsCec, * pPars = &ParsCec;
char * pFileName, * pStr, ** pArgvNew;
int c, nArgcNew, fDumpMiter = 0;
FILE * pFile;
Cec_ManCecSetDefaultParams( pPars );
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
pPars->fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Acb_CommandCec(): There is no current design.\n" );
return 0;
}
pArgvNew = argv + globalUtilOptind;
nArgcNew = argc - globalUtilOptind;
if ( nArgcNew != 1 )
{
if ( p->pSpec == NULL )
{
Abc_Print( -1, "File name is not given on the command line.\n" );
return 1;
}
pFileName = p->pSpec;
}
else
pFileName = pArgvNew[0];
// fix the wrong symbol
for ( pStr = pFileName; *pStr; pStr++ )
if ( *pStr == '>' )
*pStr = '\\';
if ( (pFile = fopen( pFileName, "r" )) == NULL )
{
Abc_Print( -1, "Cannot open input file \"%s\". ", pFileName );
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", NULL, NULL, NULL )) )
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
Abc_Print( 1, "\n" );
return 1;
}
fclose( pFile );
// extract AIG from the current design
pFirst = Acb_ManBlast( p, 0, 0, 0 );
if ( pFirst == NULL )
{
Abc_Print( -1, "Extracting AIG from the current design has failed.\n" );
return 0;
}
// extract AIG from the second design
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
pTemp = Acb_ManReadBlif( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
pTemp = Acb_ManReadVerilog( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "acb" ) )
pTemp = Acb_ManReadCba( pFileName );
else assert( 0 );
pSecond = Acb_ManBlast( pTemp, 0, 0, 0 );
Acb_ManFree( pTemp );
if ( pSecond == NULL )
{
Gia_ManStop( pFirst );
Abc_Print( -1, "Extracting AIG from the original design has failed.\n" );
return 0;
}
// compute the miter
pMiter = Gia_ManMiter( pFirst, pSecond, 0, 1, 0, 0, pPars->fVerbose );
if ( pMiter )
{
if ( fDumpMiter )
{
Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" );
Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 );
}
pAbc->Status = Cec_ManVerify( pMiter, pPars );
//Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb );
Gia_ManStop( pMiter );
}
Gia_ManStop( pFirst );
Gia_ManStop( pSecond );
return 0;
usage:
Abc_Print( -2, "usage: @cec [-vh]\n" );
Abc_Print( -2, "\t combinational equivalence checking\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Acb_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Acb_Man_t * p = Acb_AbcGetMan(pAbc);
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Acb_CommandTest(): There is no current design.\n" );
return 0;
}
return 0;
usage:
Abc_Print( -2, "usage: @test [-vh]\n" );
Abc_Print( -2, "\t experiments with word-level networks\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

File diff suppressed because it is too large Load Diff

View File

@ -1,368 +0,0 @@
/**CFile****************************************************************
FileName [acbXec.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Reusable XEC proof helpers.]
***********************************************************************/
#include "acbXec.h"
#include "aig/gia/giaAig.h"
#include "base/abc/abc.h"
#include "opt/dar/dar.h"
#include "sat/cadical/cadicalSolver.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
typedef enum Acb_SatStatus_t_
{
ACB_SAT_UNSAT = -1,
ACB_SAT_UNDEC = 0,
ACB_SAT_SAT = 1
} Acb_SatStatus_t;
int Acb_CnfCoDriverLit( Cnf_Dat_t * pCnf, int iCo, int * pLit )
{
Aig_Obj_t * pCo = Aig_ManCo( pCnf->pMan, iCo );
Aig_Obj_t * pFan = Aig_ObjFanin0( pCo );
int fCompl = Aig_ObjFaninC0( pCo );
int Var;
if ( Aig_ObjIsConst1(pFan) )
return fCompl ? -1 : 0;
Var = pCnf->pVarNums[pFan->Id];
if ( Var < 0 )
return -2;
*pLit = Abc_Var2Lit( Var, fCompl );
return 1;
}
static int Acb_GiaPoIsConst0( Gia_Man_t * p, int iPo )
{
Gia_Obj_t * pObj;
if ( iPo < 0 || iPo >= Gia_ManCoNum(p) )
return 0;
pObj = Gia_ManCo( p, iPo );
return Gia_ObjFanin0(pObj) == Gia_ManConst0(p) && !Gia_ObjFaninC0(pObj);
}
int Acb_GiaAllPosConst0( Gia_Man_t * p )
{
int i;
for ( i = 0; i < Gia_ManCoNum(p); i++ )
if ( !Acb_GiaPoIsConst0(p, i) )
return 0;
return 1;
}
static word Acb_XecGiaVarWord( int iVar, ABC_UINT64_T iWord )
{
static word Truth6[6] = {
ABC_CONST(0xAAAAAAAAAAAAAAAA),
ABC_CONST(0xCCCCCCCCCCCCCCCC),
ABC_CONST(0xF0F0F0F0F0F0F0F0),
ABC_CONST(0xFF00FF00FF00FF00),
ABC_CONST(0xFFFF0000FFFF0000),
ABC_CONST(0xFFFFFFFF00000000)
};
if ( iVar < 6 )
return Truth6[iVar];
return ((iWord >> (iVar - 6)) & 1) ? ~(word)0 : 0;
}
static inline word Acb_XecGiaLitWord( Vec_Wrd_t * vSims, int nWords, int Lit, int w )
{
word Res = Vec_WrdEntry( vSims, Abc_Lit2Var(Lit) * nWords + w );
return Abc_LitIsCompl(Lit) ? ~Res : Res;
}
int * Acb_NtkSolveCadicalLimit( Gia_Man_t * p, int fUseHeavyOpt, int fVerbose, int * pStatus, int nSatTimeLimit, const char * pLabel, int fUseXecOutputClauses )
{
Aig_Man_t * pMan = NULL;
Cnf_Dat_t * pCnf = NULL;
cadical_solver * pSat = NULL;
Vec_Int_t * vPoLits = NULL;
Gia_Man_t * pGiaOpt = NULL, * pGiaTemp = NULL;
Gia_Man_t * pGia = p;
Aig_Obj_t * pObj;
int i, Ret, Lit, Status = ACB_SAT_UNDEC, * pBeg, * pEnd, * pModel = NULL;
int fRunSolve = 0, fSolvedSat = 0;
abctime clk = Abc_Clock();
(void)fUseXecOutputClauses;
if ( pStatus )
*pStatus = ACB_XEC_UNDEC;
if ( p == NULL )
return NULL;
if ( Gia_ManCoNum(p) == 0 || Acb_GiaAllPosConst0(p) )
{
if ( pStatus )
*pStatus = ACB_XEC_EQ;
if ( pLabel )
{
printf( "The networks are equivalent by %s. ", pLabel );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
return NULL;
}
if ( fUseHeavyOpt && Gia_ManAndNum(p) > 0 )
{
pGiaTemp = Gia_ManCompress2( p, 1, 0 );
if ( pGiaTemp )
{
pGiaOpt = pGiaTemp;
pGiaTemp = NULL;
pGia = pGiaOpt;
assert( Gia_ManCiNum(pGia) == Gia_ManCiNum(p) );
}
}
pMan = Gia_ManToAig( pGia, 0 );
pCnf = pMan ? Cnf_Derive( pMan, Aig_ManCoNum(pMan) ) : NULL;
pSat = pCnf ? cadical_solver_new() : NULL;
if ( pCnf && pSat )
{
fRunSolve = 1;
cadical_solver_setnvars( pSat, pCnf->nVars );
Cnf_CnfForClause( pCnf, pBeg, pEnd, i )
{
if ( !cadical_solver_addclause( pSat, pBeg, pEnd ) )
{
Status = ACB_SAT_UNSAT;
fRunSolve = 0;
break;
}
}
if ( fRunSolve )
{
vPoLits = Vec_IntAlloc( Gia_ManCoNum(pGia) );
for ( i = 0; i < Gia_ManCoNum(pGia); i++ )
{
Ret = Acb_CnfCoDriverLit( pCnf, i, &Lit );
if ( Ret == -2 )
{
Status = ACB_SAT_UNDEC;
fRunSolve = 0;
break;
}
if ( Ret == -1 )
continue;
if ( Ret == 0 )
{
Status = ACB_SAT_SAT;
fRunSolve = 0;
break;
}
Vec_IntPush( vPoLits, Lit );
}
}
if ( fRunSolve && Vec_IntSize(vPoLits) == 0 )
{
Status = ACB_SAT_UNSAT;
fRunSolve = 0;
}
if ( fRunSolve && !cadical_solver_addclause( pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits) ) )
{
Status = ACB_SAT_UNSAT;
fRunSolve = 0;
}
if ( fRunSolve && fVerbose )
{
printf( "CaDiCaL CNF: Var = %d. Cla = %d. PO = %d.\n",
pCnf->nVars, pCnf->nClauses + 1, Gia_ManCoNum(pGia) );
if ( nSatTimeLimit > 0 )
printf( "CaDiCaL SAT runtime limit: %d sec.\n", nSatTimeLimit );
}
if ( fRunSolve )
{
Status = cadical_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 );
fSolvedSat = Status == ACB_SAT_SAT;
}
if ( fVerbose )
printf( "CaDiCaL stats: conflicts = %d. learned = %d.\n",
cadical_solver_nconflicts(pSat), cadical_solver_nlearned(pSat) );
}
if ( Status == ACB_SAT_UNSAT )
{
if ( pStatus )
*pStatus = ACB_XEC_EQ;
if ( pLabel )
{
printf( "The networks are equivalent by %s. ", pLabel );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
}
else if ( Status == ACB_SAT_SAT )
{
if ( pStatus )
*pStatus = ACB_XEC_NEQ;
if ( fSolvedSat )
pModel = ABC_CALLOC( int, Gia_ManCiNum(pGia) );
if ( pModel && pSat && pCnf && pMan )
Aig_ManForEachCi( pMan, pObj, i )
{
int Var = pCnf->pVarNums[pObj->Id];
pModel[i] = Var >= 0 ? cadical_solver_get_var_value( pSat, Var ) : 0;
}
if ( pLabel )
{
printf( "The networks are NOT equivalent by %s. ", pLabel );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
}
else
{
if ( pStatus )
*pStatus = ACB_XEC_UNDEC;
if ( fVerbose && pLabel )
{
printf( "The networks are UNDECIDED by %s. ", pLabel );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
}
if ( pSat )
cadical_solver_delete( pSat );
if ( pCnf )
Cnf_DataFree( pCnf );
if ( pMan )
Aig_ManStop( pMan );
if ( pGiaOpt )
Gia_ManStop( pGiaOpt );
Vec_IntFreeP( &vPoLits );
return pModel;
}
int Acb_XecGiaSolveSmallConeExhaustive( Gia_Man_t * p, int fVerbose, int nTotalLimit )
{
Vec_Wrd_t * vSims = NULL;
Gia_Obj_t * pObj;
ABC_UINT64_T nWordsTotal, nWordBudget, iWordBase, nWordsDone = 0;
int i, w, nWords, nWordsChunk, nObjs, nCis, nHiVars, Status = ACB_XEC_EQ, fDone = 0;
abctime clk = Abc_Clock();
abctime clkLimit = nTotalLimit > 0 ? clk + nTotalLimit * CLOCKS_PER_SEC : 0;
if ( Gia_ManCoNum(p) != 1 || Gia_ManAndNum(p) > 5000 )
return ACB_XEC_UNDEC;
nCis = Gia_ManCiNum(p);
nHiVars = Abc_MaxInt( 0, nCis - 6 );
if ( nHiVars >= 63 )
{
if ( fVerbose )
printf( "Skipping small-cone exhaustive word proof: CI = %d needs more than 2^63 simulation words.\n", nCis );
return ACB_XEC_UNDEC;
}
nWordsChunk = nCis >= 31 ? 4096 : (nCis >= 28 ? 8192 : 16384);
nWordsTotal = nHiVars ? ((ABC_UINT64_T)1 << nHiVars) : 1;
nWordBudget = nTotalLimit > 0 ? (ABC_UINT64_T)200000 * nTotalLimit : (ABC_UINT64_T)60000000;
if ( nWordBudget < (ABC_UINT64_T)8000000 )
nWordBudget = (ABC_UINT64_T)8000000;
if ( nWordsTotal > nWordBudget )
{
if ( fVerbose )
printf( "Skipping small-cone exhaustive word proof: CI = %d needs %llu words, budget = %llu words.\n",
nCis, (unsigned long long)nWordsTotal, (unsigned long long)nWordBudget );
return ACB_XEC_UNDEC;
}
nObjs = Gia_ManObjNum(p);
vSims = Vec_WrdStart( nObjs * nWordsChunk );
if ( fVerbose )
printf( "Trying small-cone exhaustive word proof: CI = %d. AND = %d. chunks = %llu x %d words. limit = %d sec.\n",
nCis, Gia_ManAndNum(p), (unsigned long long)((nWordsTotal + nWordsChunk - 1) / nWordsChunk), nWordsChunk, nTotalLimit );
for ( iWordBase = 0; iWordBase < nWordsTotal && !fDone; iWordBase += nWordsChunk )
{
ABC_UINT64_T nWordsLeft = nWordsTotal - iWordBase;
nWords = nWordsLeft < (ABC_UINT64_T)nWordsChunk ? (int)nWordsLeft : nWordsChunk;
if ( clkLimit && Abc_Clock() >= clkLimit )
{
Status = ACB_XEC_UNDEC;
break;
}
/* Only the active words [0..nWords) are consumed in this chunk; other words may retain previous data. */
for ( w = 0; w < nWords; w++ )
Vec_WrdWriteEntry( vSims, w, 0 );
Gia_ManForEachCi( p, pObj, i )
for ( w = 0; w < nWords; w++ )
Vec_WrdWriteEntry( vSims, Gia_ObjId(p, pObj) * nWordsChunk + w, Acb_XecGiaVarWord(i, iWordBase + w) );
Gia_ManForEachAnd( p, pObj, i )
for ( w = 0; w < nWords; w++ )
Vec_WrdWriteEntry( vSims, Gia_ObjId(p, pObj) * nWordsChunk + w,
Acb_XecGiaLitWord(vSims, nWordsChunk, Gia_ObjFaninLit0p(p, pObj), w) &
Acb_XecGiaLitWord(vSims, nWordsChunk, Gia_ObjFaninLit1p(p, pObj), w) );
pObj = Gia_ManCo( p, 0 );
for ( w = 0; w < nWords; w++ )
{
word Res = Acb_XecGiaLitWord(vSims, nWordsChunk, Gia_ObjFaninLit0p(p, pObj), w);
if ( iWordBase + w + 1 == nWordsTotal && nCis < 6 )
Res &= (((word)1) << (1 << nCis)) - 1;
if ( Res )
{
Status = ACB_XEC_UNDEC;
fDone = 1;
break;
}
}
nWordsDone += nWords;
}
if ( fVerbose )
{
printf( "Small-cone exhaustive word proof: %s. checked words = %llu/%llu. ",
Status == ACB_XEC_EQ ? "UNSAT" : "UNDECIDED",
(unsigned long long)nWordsDone, (unsigned long long)nWordsTotal );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
Vec_WrdFree( vSims );
return Status;
}
Gia_Man_t * Acb_XecGiaSmallConeXorRewrite( Gia_Man_t * p, int fVerbose )
{
Aig_Man_t * pAig = NULL, * pAigTemp = NULL;
Gia_Man_t * pGia = NULL, * pTemp = NULL;
int nAndStart = Gia_ManAndNum(p);
abctime clk = Abc_Clock();
if ( Gia_ManCoNum(p) != 1 || Gia_ManCiNum(p) > 64 || nAndStart > 8000 )
return NULL;
if ( fVerbose )
printf( "Small-cone XOR structural rewrite: CI = %d. AND = %d.\n",
Gia_ManCiNum(p), nAndStart );
pAig = Gia_ManToAig( p, 0 );
if ( pAig == NULL )
return NULL;
pAig = Dar_ManBalanceXor( pAigTemp = pAig, 1, 1, 0 );
Aig_ManStop( pAigTemp );
if ( pAig == NULL )
return NULL;
pAig = Dar_ManRwsat( pAigTemp = pAig, 1, 0 );
Aig_ManStop( pAigTemp );
if ( pAig == NULL )
return NULL;
pGia = Gia_ManFromAig( pAig );
Aig_ManStop( pAig );
if ( pGia == NULL )
return NULL;
pTemp = Gia_ManCompress2( pGia, 1, 0 );
if ( pTemp )
{
Gia_ManStop( pGia );
pGia = pTemp;
}
if ( fVerbose )
{
printf( "Small-cone XOR structural rewrite: AND = %d -> %d. Lev = %d -> %d. ",
nAndStart, Gia_ManAndNum(pGia), Gia_ManLevelNum(p), Gia_ManLevelNum(pGia) );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}
if ( Gia_ManCoNum(pGia) != Gia_ManCoNum(p) ||
(!Acb_GiaAllPosConst0(pGia) && Gia_ManAndNum(pGia) >= nAndStart) )
{
Gia_ManStop( pGia );
return NULL;
}
return pGia;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

View File

@ -1,70 +0,0 @@
/**CFile****************************************************************
FileName [acbXec.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Shared XEC proof helper API.]
***********************************************************************/
#ifndef ABC__base__acb__acbXec_h
#define ABC__base__acb__acbXec_h
#include "acb.h"
#include "sat/cnf/cnf.h"
ABC_NAMESPACE_HEADER_START
/*
* XEC/network-level proof status:
* ACB_XEC_EQ : networks/output are proven equivalent/UNSAT miter
* ACB_XEC_NEQ : networks/output are proven different/SAT miter
* ACB_XEC_UNDEC : proof was inconclusive
* ACB_XEC_ONE_HARD : local sweep proved all but one output
* ACB_XEC_MANY_HARD : local sweep left multiple hard outputs
*
*/
typedef enum Acb_XecStatus_t_
{
ACB_XEC_MANY_HARD = -3,
ACB_XEC_ONE_HARD = -2,
ACB_XEC_UNDEC = -1,
ACB_XEC_NEQ = 0,
ACB_XEC_EQ = 1
} Acb_XecStatus_t;
static inline void Acb_NtkPrintUnsupportedObj( Acb_Ntk_t * p, int iObj, const char * pWhere, int ExpectedFans, int ActualFans )
{
printf( "%s unsupported ACB object: obj = %d", pWhere ? pWhere : "XEC" , iObj );
if ( p && iObj >= 0 && iObj < Acb_NtkObjNumMax(p) )
printf( ", type = %d", Acb_ObjType(p, iObj) );
if ( ExpectedFans >= 0 || ActualFans >= 0 )
printf( ", fanins = %d, expected = %d", ActualFans, ExpectedFans );
printf( ".\n" );
}
static inline void Acb_XecMergeTargetStatus( int StatusTarget, int fHasModel, int * pStatus, int * pCheckModel )
{
if ( fHasModel && pCheckModel )
*pCheckModel = 1;
if ( pStatus == NULL )
return;
if ( StatusTarget == ACB_XEC_EQ )
*pStatus = ACB_XEC_EQ;
else if ( StatusTarget == ACB_XEC_NEQ )
*pStatus = ACB_XEC_NEQ;
}
extern int * Acb_NtkSolveCadicalLimit( Gia_Man_t * p, int fUseHeavyOpt, int fVerbose, int * pStatus, int nSatTimeLimit, const char * pLabel, int fUseXecOutputClauses );
extern int Acb_CnfCoDriverLit( Cnf_Dat_t * pCnf, int iCo, int * pLit );
extern int Acb_GiaAllPosConst0( Gia_Man_t * p );
extern int Acb_XecGiaSolveSmallConeExhaustive( Gia_Man_t * p, int fVerbose, int nTotalLimit );
extern Gia_Man_t *Acb_XecGiaSmallConeXorRewrite( Gia_Man_t * p, int fVerbose );
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,9 +1,9 @@
SRC += src/base/acb/acbAbc.c \ SRC += src/base/acb/acbAbc.c \
src/base/acb/acbAig.c \ src/base/acb/acbAig.c \
src/base/acb/acbCom.c \
src/base/acb/acbFunc.c \ src/base/acb/acbFunc.c \
src/base/acb/acbMfs.c \ src/base/acb/acbMfs.c \
src/base/acb/acbPush.c \ src/base/acb/acbPush.c \
src/base/acb/acbSets.c \ src/base/acb/acbSets.c \
src/base/acb/acbTest.c \ src/base/acb/acbTest.c \
src/base/acb/acbUtil.c \ src/base/acb/acbUtil.c
src/base/acb/acbXec.c

52
src/base/bac/bac.c Normal file
View File

@ -0,0 +1,52 @@
/**CFile****************************************************************
FileName [bac.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Verilog parser.]
Synopsis [Parses several flavors of word-level Verilog.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bac.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

1017
src/base/bac/bac.h Normal file

File diff suppressed because it is too large Load Diff

298
src/base/bac/bacBac.c Normal file
View File

@ -0,0 +1,298 @@
/**CFile****************************************************************
FileName [bacBac.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Verilog parser.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacBac.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Read CBA.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int BacManReadBacLine( Vec_Str_t * vOut, int * pPos, char * pBuffer, char * pLimit )
{
char c;
while ( (c = Vec_StrEntry(vOut, (*pPos)++)) != '\n' && pBuffer < pLimit )
*pBuffer++ = c;
*pBuffer = 0;
return pBuffer < pLimit;
}
int BacManReadBacNameAndNums( char * pBuffer, int * Num1, int * Num2, int * Num3, int * Num4 )
{
*Num1 = *Num2 = *Num3 = *Num4 = -1;
// read name
while ( *pBuffer && *pBuffer != ' ' )
pBuffer++;
if ( !*pBuffer )
return 0;
assert( *pBuffer == ' ' );
*pBuffer = 0;
// read Num1
*Num1 = atoi(++pBuffer);
while ( *pBuffer && *pBuffer != ' ' )
pBuffer++;
if ( !*pBuffer )
return 0;
// read Num2
assert( *pBuffer == ' ' );
*Num2 = atoi(++pBuffer);
while ( *pBuffer && *pBuffer != ' ' )
pBuffer++;
if ( !*pBuffer )
return 1;
// read Num3
assert( *pBuffer == ' ' );
*Num3 = atoi(++pBuffer);
while ( *pBuffer && *pBuffer != ' ' )
pBuffer++;
if ( !*pBuffer )
return 1;
// read Num4
assert( *pBuffer == ' ' );
*Num4 = atoi(++pBuffer);
return 1;
}
void Bac_ManReadBacVecStr( Vec_Str_t * vOut, int * pPos, Vec_Str_t * p, int nSize )
{
memcpy( Vec_StrArray(p), Vec_StrArray(vOut) + *pPos, (size_t)nSize );
*pPos += nSize;
p->nSize = nSize;
assert( Vec_StrSize(p) == Vec_StrCap(p) );
}
void Bac_ManReadBacVecInt( Vec_Str_t * vOut, int * pPos, Vec_Int_t * p, int nSize )
{
memcpy( Vec_IntArray(p), Vec_StrArray(vOut) + *pPos, (size_t)nSize );
*pPos += nSize;
p->nSize = nSize / 4;
assert( Vec_IntSize(p) == Vec_IntCap(p) );
}
void Bac_ManReadBacNtk( Vec_Str_t * vOut, int * pPos, Bac_Ntk_t * pNtk )
{
int i, Type;
//char * pName; int iObj, NameId;
Bac_ManReadBacVecStr( vOut, pPos, &pNtk->vType, Bac_NtkObjNumAlloc(pNtk) );
Bac_ManReadBacVecInt( vOut, pPos, &pNtk->vFanin, 4 * Bac_NtkObjNumAlloc(pNtk) );
Bac_ManReadBacVecInt( vOut, pPos, &pNtk->vInfo, 12 * Bac_NtkInfoNumAlloc(pNtk) );
Bac_NtkForEachObjType( pNtk, Type, i )
{
if ( Type == BAC_OBJ_PI )
Vec_IntPush( &pNtk->vInputs, i );
if ( Type == BAC_OBJ_PO )
Vec_IntPush( &pNtk->vOutputs, i );
}
assert( Bac_NtkPiNum(pNtk) == Bac_NtkPiNumAlloc(pNtk) );
assert( Bac_NtkPoNum(pNtk) == Bac_NtkPoNumAlloc(pNtk) );
assert( Bac_NtkObjNum(pNtk) == Bac_NtkObjNumAlloc(pNtk) );
assert( Bac_NtkInfoNum(pNtk) == Bac_NtkInfoNumAlloc(pNtk) );
/*
// read input/output/box names
Bac_NtkForEachPiMain( pNtk, iObj, i )
{
pName = Vec_StrEntryP( vOut, Pos );
NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL );
Pos += strlen(pName) + 1;
}
Bac_NtkForEachPoMain( pNtk, iObj, i )
{
pName = Vec_StrEntryP( vOut, Pos );
NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL );
Pos += strlen(pName) + 1;
}
Bac_NtkForEachBox( pNtk, iObj )
{
pName = Vec_StrEntryP( vOut, Pos );
NameId = Abc_NamStrFindOrAdd( p->pStrs, pName, NULL );
Pos += strlen(pName) + 1;
}
*/
}
Bac_Man_t * Bac_ManReadBacInt( Vec_Str_t * vOut )
{
Bac_Man_t * p;
Bac_Ntk_t * pNtk;
char Buffer[1000] = "#";
int i, NameId, Pos = 0, nNtks, Num1, Num2, Num3, Num4;
while ( Buffer[0] == '#' )
if ( !BacManReadBacLine(vOut, &Pos, Buffer, Buffer+1000) )
return NULL;
if ( !BacManReadBacNameAndNums(Buffer, &nNtks, &Num2, &Num3, &Num4) )
return NULL;
// start manager
assert( nNtks > 0 );
p = Bac_ManAlloc( Buffer, nNtks );
// start networks
Bac_ManForEachNtk( p, pNtk, i )
{
if ( !BacManReadBacLine(vOut, &Pos, Buffer, Buffer+1000) )
{
Bac_ManFree( p );
return NULL;
}
if ( !BacManReadBacNameAndNums(Buffer, &Num1, &Num2, &Num3, &Num4) )
{
Bac_ManFree( p );
return NULL;
}
assert( Num1 >= 0 && Num2 >= 0 && Num3 >= 0 );
NameId = Abc_NamStrFindOrAdd( p->pStrs, Buffer, NULL );
Bac_NtkAlloc( pNtk, NameId, Num1, Num2, Num3 );
Vec_IntFill( &pNtk->vInfo, 3 * Num4, -1 );
}
// read networks
Bac_ManForEachNtk( p, pNtk, i )
Bac_ManReadBacNtk( vOut, &Pos, pNtk );
assert( Bac_ManNtkNum(p) == nNtks );
assert( Pos == Vec_StrSize(vOut) );
return p;
}
Bac_Man_t * Bac_ManReadBac( char * pFileName )
{
Bac_Man_t * p;
FILE * pFile;
Vec_Str_t * vOut;
int nFileSize;
pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
printf( "Cannot open file \"%s\" for reading.\n", pFileName );
return NULL;
}
// get the file size, in bytes
fseek( pFile, 0, SEEK_END );
nFileSize = ftell( pFile );
rewind( pFile );
// load the contents
vOut = Vec_StrAlloc( nFileSize );
vOut->nSize = vOut->nCap;
assert( nFileSize == Vec_StrSize(vOut) );
nFileSize = fread( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile );
assert( nFileSize == Vec_StrSize(vOut) );
fclose( pFile );
// read the networks
p = Bac_ManReadBacInt( vOut );
if ( p != NULL )
{
ABC_FREE( p->pSpec );
p->pSpec = Abc_UtilStrsav( pFileName );
}
Vec_StrFree( vOut );
return p;
}
/**Function*************************************************************
Synopsis [Write CBA.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_ManWriteBacNtk( Vec_Str_t * vOut, Bac_Ntk_t * pNtk )
{
//char * pName; int iObj, NameId;
Vec_StrPushBuffer( vOut, (char *)Vec_StrArray(&pNtk->vType), Bac_NtkObjNum(pNtk) );
Vec_StrPushBuffer( vOut, (char *)Vec_IntArray(&pNtk->vFanin), 4 * Bac_NtkObjNum(pNtk) );
Vec_StrPushBuffer( vOut, (char *)Vec_IntArray(&pNtk->vInfo), 12 * Bac_NtkInfoNum(pNtk) );
/*
// write input/output/box names
Bac_NtkForEachPiMain( pNtk, iObj, i )
{
pName = Bac_ObjNameStr( pNtk, iObj );
Vec_StrPrintStr( vOut, pName );
Vec_StrPush( vOut, '\0' );
}
Bac_NtkForEachPoMain( pNtk, iObj, i )
{
pName = Bac_ObjNameStr( pNtk, iObj );
Vec_StrPrintStr( vOut, pName );
Vec_StrPush( vOut, '\0' );
}
Bac_NtkForEachBox( pNtk, iObj )
{
pName = Bac_ObjNameStr( pNtk, iObj );
Vec_StrPrintStr( vOut, pName );
Vec_StrPush( vOut, '\0' );
}
*/
}
void Bac_ManWriteBacInt( Vec_Str_t * vOut, Bac_Man_t * p )
{
char Buffer[1000];
Bac_Ntk_t * pNtk; int i;
sprintf( Buffer, "# Design \"%s\" written by ABC on %s\n", Bac_ManName(p), Extra_TimeStamp() );
Vec_StrPrintStr( vOut, Buffer );
// write short info
sprintf( Buffer, "%s %d \n", Bac_ManName(p), Bac_ManNtkNum(p) );
Vec_StrPrintStr( vOut, Buffer );
Bac_ManForEachNtk( p, pNtk, i )
{
sprintf( Buffer, "%s %d %d %d %d \n", Bac_NtkName(pNtk),
Bac_NtkPiNum(pNtk), Bac_NtkPoNum(pNtk), Bac_NtkObjNum(pNtk), Bac_NtkInfoNum(pNtk) );
Vec_StrPrintStr( vOut, Buffer );
}
Bac_ManForEachNtk( p, pNtk, i )
Bac_ManWriteBacNtk( vOut, pNtk );
}
void Bac_ManWriteBac( char * pFileName, Bac_Man_t * p )
{
Vec_Str_t * vOut;
assert( p->pMioLib == NULL );
vOut = Vec_StrAlloc( 10000 );
Bac_ManWriteBacInt( vOut, p );
if ( Vec_StrSize(vOut) > 0 )
{
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
printf( "Cannot open file \"%s\" for writing.\n", pFileName );
else
{
fwrite( Vec_StrArray(vOut), 1, Vec_StrSize(vOut), pFile );
fclose( pFile );
}
}
Vec_StrFree( vOut );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

587
src/base/bac/bacBlast.c Normal file
View File

@ -0,0 +1,587 @@
/**CFile****************************************************************
FileName [bacBlast.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Bit-blasting of the netlist.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacBlast.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "base/abc/abc.h"
#include "map/mio/mio.h"
#include "bool/dec/dec.h"
#include "base/main/mainInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_ManPrepareGates( Bac_Man_t * p )
{
Dec_Graph_t ** ppGraphs; int i;
if ( p->pMioLib == NULL )
return;
ppGraphs = ABC_CALLOC( Dec_Graph_t *, Abc_NamObjNumMax(p->pMods) );
for ( i = 1; i < Abc_NamObjNumMax(p->pMods); i++ )
{
char * pGateName = Abc_NamStr( p->pMods, i );
Mio_Gate_t * pGate = Mio_LibraryReadGateByName( (Mio_Library_t *)p->pMioLib, pGateName, NULL );
if ( pGate != NULL )
ppGraphs[i] = Dec_Factor( Mio_GateReadSop(pGate) );
}
assert( p->ppGraphs == NULL );
p->ppGraphs = (void **)ppGraphs;
}
void Bac_ManUndoGates( Bac_Man_t * p )
{
int i;
if ( p->pMioLib == NULL )
return;
for ( i = 1; i < Abc_NamObjNumMax(p->pMods); i++ )
if ( p->ppGraphs[i] )
Dec_GraphFree( (Dec_Graph_t *)p->ppGraphs[i] );
ABC_FREE( p->ppGraphs );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_ManAddBarbuf( Gia_Man_t * pNew, int iRes, Bac_Man_t * p, int iLNtk, int iLObj, int iRNtk, int iRObj, Vec_Int_t * vMap )
{
int iBufLit, iIdLit;
if ( iRes == 0 || iRes == 1 )
return iRes;
assert( iRes > 0 );
if ( vMap && Abc_Lit2Var(iRes) < Vec_IntSize(vMap) && (iIdLit = Vec_IntEntry(vMap, Abc_Lit2Var(iRes))) >= 0 &&
Vec_IntEntry(&p->vBuf2LeafNtk, Abc_Lit2Var(iIdLit)) == iLNtk && Vec_IntEntry(&p->vBuf2RootNtk, Abc_Lit2Var(iIdLit)) == iRNtk )
return Abc_LitNotCond( Vec_IntEntry(pNew->vBarBufs, Abc_Lit2Var(iIdLit)), Abc_LitIsCompl(iRes) ^ Abc_LitIsCompl(iIdLit) );
assert( Bac_ManNtkIsOk(p, iLNtk) && Bac_ManNtkIsOk(p, iRNtk) );
Vec_IntPush( &p->vBuf2LeafNtk, iLNtk );
Vec_IntPush( &p->vBuf2LeafObj, iLObj );
Vec_IntPush( &p->vBuf2RootNtk, iRNtk );
Vec_IntPush( &p->vBuf2RootObj, iRObj );
iBufLit = Gia_ManAppendBuf( pNew, iRes );
if ( vMap )
{
Vec_IntSetEntryFull( vMap, Abc_Lit2Var(iRes), Abc_Var2Lit(Vec_IntSize(pNew->vBarBufs), Abc_LitIsCompl(iRes)) );
Vec_IntPush( pNew->vBarBufs, iBufLit );
}
return iBufLit;
}
int Bac_ManExtract_rec( Gia_Man_t * pNew, Bac_Ntk_t * p, int i, int fBuffers, Vec_Int_t * vMap )
{
int iRes = Bac_ObjCopy( p, i );
if ( iRes >= 0 )
return iRes;
if ( Bac_ObjIsCo(p, i) )
iRes = Bac_ManExtract_rec( pNew, p, Bac_ObjFanin(p, i), fBuffers, vMap );
else if ( Bac_ObjIsPi(p, i) )
{
Bac_Ntk_t * pHost = Bac_NtkHostNtk( p );
int iObj = Bac_BoxBi( pHost, Bac_NtkHostObj(p), Bac_ObjIndex(p, i) );
iRes = Bac_ManExtract_rec( pNew, pHost, iObj, fBuffers, vMap );
if ( fBuffers )
iRes = Bac_ManAddBarbuf( pNew, iRes, p->pDesign, Bac_NtkId(p), i, Bac_NtkId(pHost), iObj, vMap );
}
else if ( Bac_ObjIsBo(p, i) )
{
int iBox = Bac_BoxBoBox(p, i);
if ( Bac_ObjIsBoxUser(p, iBox) ) // user box
{
Bac_Ntk_t * pBox = Bac_BoxBoNtk( p, i );
int iObj = Bac_NtkPo( pBox, Bac_ObjIndex(p, i) );
iRes = Bac_ManExtract_rec( pNew, pBox, iObj, fBuffers, vMap );
if ( fBuffers )
iRes = Bac_ManAddBarbuf( pNew, iRes, p->pDesign, Bac_NtkId(p), i, Bac_NtkId(pBox), iObj, vMap );
}
else // primitive
{
int iFanin, nLits, pLits[16];
assert( Bac_ObjIsBoxPrim(p, iBox) );
Bac_BoxForEachFanin( p, iBox, iFanin, nLits )
pLits[nLits] = Bac_ManExtract_rec( pNew, p, iFanin, fBuffers, vMap );
assert( nLits <= 16 );
if ( p->pDesign->ppGraphs ) // mapped gate
{
extern int Gia_ManFactorGraph( Gia_Man_t * p, Dec_Graph_t * pFForm, Vec_Int_t * vLeaves );
Dec_Graph_t * pGraph = (Dec_Graph_t *)p->pDesign->ppGraphs[Bac_BoxNtkId(p, iBox)];
Vec_Int_t Leaves = { nLits, nLits, pLits };
assert( pGraph != NULL );
return Gia_ManFactorGraph( pNew, pGraph, &Leaves );
}
else
{
Bac_ObjType_t Type = Bac_ObjType(p, iBox);
if ( nLits == 0 )
{
if ( Type == BAC_BOX_CF )
iRes = 0;
else if ( Type == BAC_BOX_CT )
iRes = 1;
else assert( 0 );
}
else if ( nLits == 1 )
{
if ( Type == BAC_BOX_BUF )
iRes = pLits[0];
else if ( Type == BAC_BOX_INV )
iRes = Abc_LitNot( pLits[0] );
else assert( 0 );
}
else if ( nLits == 2 )
{
if ( Type == BAC_BOX_AND )
iRes = Gia_ManHashAnd( pNew, pLits[0], pLits[1] );
else if ( Type == BAC_BOX_NAND )
iRes = Abc_LitNot( Gia_ManHashAnd( pNew, pLits[0], pLits[1] ) );
else if ( Type == BAC_BOX_OR )
iRes = Gia_ManHashOr( pNew, pLits[0], pLits[1] );
else if ( Type == BAC_BOX_NOR )
iRes = Abc_LitNot( Gia_ManHashOr( pNew, pLits[0], pLits[1] ) );
else if ( Type == BAC_BOX_XOR )
iRes = Gia_ManHashXor( pNew, pLits[0], pLits[1] );
else if ( Type == BAC_BOX_XNOR )
iRes = Abc_LitNot( Gia_ManHashXor( pNew, pLits[0], pLits[1] ) );
else if ( Type == BAC_BOX_SHARP )
iRes = Gia_ManHashAnd( pNew, pLits[0], Abc_LitNot(pLits[1]) );
else if ( Type == BAC_BOX_SHARPL )
iRes = Gia_ManHashAnd( pNew, Abc_LitNot(pLits[0]), pLits[1] );
else assert( 0 );
}
else if ( nLits == 3 )
{
if ( Type == BAC_BOX_MUX )
iRes = Gia_ManHashMux( pNew, pLits[0], pLits[1], pLits[2] );
else if ( Type == BAC_BOX_MAJ )
iRes = Gia_ManHashMaj( pNew, pLits[0], pLits[1], pLits[2] );
else if ( Type == BAC_BOX_ADD )
{
int iRes0 = Gia_ManHashAnd( pNew, pLits[1], pLits[2] );
int iRes1 = Gia_ManHashOr( pNew, pLits[1], pLits[2] );
assert( Bac_BoxBoNum(p, iBox) == 2 );
if ( Bac_BoxBo(p, iBox, 0) == i ) // sum
iRes = Gia_ManHashXor( pNew, pLits[0], Gia_ManHashAnd(pNew, Abc_LitNot(iRes0), iRes1) );
else if ( Bac_BoxBo(p, iBox, 1) == i ) // cout
iRes = Gia_ManHashOr( pNew, iRes0, Gia_ManHashAnd(pNew, pLits[0], iRes1) );
else assert( 0 );
}
else assert( 0 );
}
else assert( 0 );
}
}
}
else assert( 0 );
Bac_ObjSetCopy( p, i, iRes );
return iRes;
}
Gia_Man_t * Bac_ManExtract( Bac_Man_t * p, int fBuffers, int fVerbose )
{
Bac_Ntk_t * pNtk, * pRoot = Bac_ManRoot(p);
Gia_Man_t * pNew, * pTemp;
Vec_Int_t * vMap = NULL;
int i, iObj;
Vec_IntClear( &p->vBuf2LeafNtk );
Vec_IntClear( &p->vBuf2LeafObj );
Vec_IntClear( &p->vBuf2RootNtk );
Vec_IntClear( &p->vBuf2RootObj );
Bac_ManForEachNtk( p, pNtk, i )
{
Bac_NtkDeriveIndex( pNtk );
Bac_NtkStartCopies( pNtk );
}
// start the manager
pNew = Gia_ManStart( Bac_ManNodeNum(p) );
pNew->pName = Abc_UtilStrsav(p->pName);
pNew->pSpec = Abc_UtilStrsav(p->pSpec);
// primary inputs
Bac_NtkForEachPi( pRoot, iObj, i )
Bac_ObjSetCopy( pRoot, iObj, Gia_ManAppendCi(pNew) );
// internal nodes
Gia_ManHashAlloc( pNew );
pNew->vBarBufs = Vec_IntAlloc( 10000 );
vMap = Vec_IntStartFull( 10000 );
Bac_ManPrepareGates( p );
Bac_NtkForEachPo( pRoot, iObj, i )
Bac_ManExtract_rec( pNew, pRoot, iObj, fBuffers, vMap );
Bac_ManUndoGates( p );
Vec_IntFreeP( &vMap );
Gia_ManHashStop( pNew );
// primary outputs
Bac_NtkForEachPo( pRoot, iObj, i )
Gia_ManAppendCo( pNew, Bac_ObjCopy(pRoot, iObj) );
assert( Vec_IntSize(&p->vBuf2LeafNtk) == pNew->nBufs );
// cleanup
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
//Gia_ManPrintStats( pNew, NULL );
return pNew;
}
/**Function*************************************************************
Synopsis [Mark each GIA node with the network it belongs to.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_ManMarkNodesGia( Bac_Man_t * p, Gia_Man_t * pGia )
{
Gia_Obj_t * pObj; int i, Count = 0;
assert( Vec_IntSize(&p->vBuf2LeafNtk) == Gia_ManBufNum(pGia) );
Gia_ManConst0(pGia)->Value = 1;
Gia_ManForEachPi( pGia, pObj, i )
pObj->Value = 1;
Gia_ManForEachAnd( pGia, pObj, i )
{
if ( Gia_ObjIsBuf(pObj) )
pObj->Value = Vec_IntEntry( &p->vBuf2LeafNtk, Count++ );
else
{
pObj->Value = Gia_ObjFanin0(pObj)->Value;
assert( pObj->Value == Gia_ObjFanin1(pObj)->Value );
}
}
assert( Count == Gia_ManBufNum(pGia) );
Gia_ManForEachPo( pGia, pObj, i )
{
assert( Gia_ObjFanin0(pObj)->Value == 1 );
pObj->Value = 1;
}
}
void Bac_ManRemapBarbufs( Bac_Man_t * pNew, Bac_Man_t * p )
{
Bac_Ntk_t * pNtk; int Entry, i;
//assert( Vec_IntSize(&p->vBuf2RootNtk) );
assert( !Vec_IntSize(&pNew->vBuf2RootNtk) );
Vec_IntAppend( &pNew->vBuf2RootNtk, &p->vBuf2RootNtk );
Vec_IntAppend( &pNew->vBuf2RootObj, &p->vBuf2RootObj );
Vec_IntAppend( &pNew->vBuf2LeafNtk, &p->vBuf2LeafNtk );
Vec_IntAppend( &pNew->vBuf2LeafObj, &p->vBuf2LeafObj );
Vec_IntForEachEntry( &p->vBuf2LeafObj, Entry, i )
{
pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2LeafNtk, i) );
Vec_IntWriteEntry( &pNew->vBuf2LeafObj, i, Bac_ObjCopy(pNtk, Entry) );
}
Vec_IntForEachEntry( &p->vBuf2RootObj, Entry, i )
{
pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, i) );
Vec_IntWriteEntry( &pNew->vBuf2RootObj, i, Bac_ObjCopy(pNtk, Entry) );
}
}
void Bac_NtkCreateAndConnectBuffer( Gia_Man_t * pGia, Gia_Obj_t * pObj, Bac_Ntk_t * p, int iTerm )
{
int iObj;
if ( pGia && Gia_ObjFaninId0p(pGia, pObj) > 0 )
{
iObj = Bac_ObjAlloc( p, BAC_OBJ_BI, Gia_ObjFanin0(pObj)->Value );
Bac_ObjAlloc( p, Gia_ObjFaninC0(pObj) ? BAC_BOX_INV : BAC_BOX_BUF, -1 );
}
else
{
Bac_ObjAlloc( p, pGia && Gia_ObjFaninC0(pObj) ? BAC_BOX_CT : BAC_BOX_CF, -1 );
}
iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 );
Bac_ObjSetFanin( p, iTerm, iObj );
}
void Bac_NtkInsertGia( Bac_Man_t * p, Gia_Man_t * pGia )
{
Bac_Ntk_t * pNtk, * pRoot = Bac_ManRoot( p );
int i, j, k, iBox, iTerm, Count = 0;
Gia_Obj_t * pObj;
Gia_ManConst0(pGia)->Value = ~0;
Gia_ManForEachPi( pGia, pObj, i )
pObj->Value = Bac_NtkPi( pRoot, i );
Gia_ManForEachAnd( pGia, pObj, i )
{
if ( Gia_ObjIsBuf(pObj) )
{
pNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, Count) );
iTerm = Vec_IntEntry( &p->vBuf2RootObj, Count );
assert( Bac_ObjIsCo(pNtk, iTerm) );
if ( Bac_ObjFanin(pNtk, iTerm) == -1 ) // not a feedthrough
Bac_NtkCreateAndConnectBuffer( pGia, pObj, pNtk, iTerm );
// prepare leaf
pObj->Value = Vec_IntEntry( &p->vBuf2LeafObj, Count++ );
}
else
{
int iLit0 = Gia_ObjFanin0(pObj)->Value;
int iLit1 = Gia_ObjFanin1(pObj)->Value;
Bac_ObjType_t Type;
pNtk = Bac_ManNtk( p, pObj->Value );
if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
Type = BAC_BOX_NOR;
else if ( Gia_ObjFaninC1(pObj) )
Type = BAC_BOX_SHARP;
else if ( Gia_ObjFaninC0(pObj) )
{
Type = BAC_BOX_SHARP;
ABC_SWAP( int, iLit0, iLit1 );
}
else
Type = BAC_BOX_AND;
// create box
iTerm = Bac_ObjAlloc( pNtk, BAC_OBJ_BI, iLit1 );
iTerm = Bac_ObjAlloc( pNtk, BAC_OBJ_BI, iLit0 );
Bac_ObjAlloc( pNtk, Type, -1 );
pObj->Value = Bac_ObjAlloc( pNtk, BAC_OBJ_BO, -1 );
}
}
assert( Count == Gia_ManBufNum(pGia) );
// create constant 0 drivers for COs without barbufs
Bac_ManForEachNtk( p, pNtk, i )
{
Bac_NtkForEachBox( pNtk, iBox )
Bac_BoxForEachBi( pNtk, iBox, iTerm, j )
if ( Bac_ObjFanin(pNtk, iTerm) == -1 )
Bac_NtkCreateAndConnectBuffer( NULL, NULL, pNtk, iTerm );
Bac_NtkForEachPo( pNtk, iTerm, k )
if ( pNtk != pRoot && Bac_ObjFanin(pNtk, iTerm) == -1 )
Bac_NtkCreateAndConnectBuffer( NULL, NULL, pNtk, iTerm );
}
// create node and connect POs
Gia_ManForEachPo( pGia, pObj, i )
if ( Bac_ObjFanin(pRoot, Bac_NtkPo(pRoot, i)) == -1 ) // not a feedthrough
Bac_NtkCreateAndConnectBuffer( pGia, pObj, pRoot, Bac_NtkPo(pRoot, i) );
}
Bac_Man_t * Bac_ManInsertGia( Bac_Man_t * p, Gia_Man_t * pGia )
{
Bac_Man_t * pNew = Bac_ManDupUserBoxes( p );
Bac_ManMarkNodesGia( p, pGia );
Bac_ManRemapBarbufs( pNew, p );
Bac_NtkInsertGia( pNew, pGia );
Bac_ManMoveNames( pNew, p );
return pNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Bac_Man_t * Bac_ManBlastTest( Bac_Man_t * p )
{
Gia_Man_t * pGia = Bac_ManExtract( p, 1, 0 );
Bac_Man_t * pNew = Bac_ManInsertGia( p, pGia );
Gia_ManStop( pGia );
return pNew;
}
/**Function*************************************************************
Synopsis [Mark each GIA node with the network it belongs to.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Abc_NodeIsSeriousGate( Abc_Obj_t * p )
{
return Abc_ObjIsNode(p) && Abc_ObjFaninNum(p) > 0 && !Abc_ObjIsBarBuf(p);
}
void Bac_ManMarkNodesAbc( Bac_Man_t * p, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj, * pFanin; int i, k, Count = 0;
assert( Vec_IntSize(&p->vBuf2LeafNtk) == pNtk->nBarBufs2 );
Abc_NtkForEachPi( pNtk, pObj, i )
pObj->iTemp = 1;
Abc_NtkForEachNode( pNtk, pObj, i )
{
if ( Abc_ObjIsBarBuf(pObj) )
pObj->iTemp = Vec_IntEntry( &p->vBuf2LeafNtk, Count++ );
else if ( Abc_NodeIsSeriousGate(pObj) )
{
pObj->iTemp = Abc_ObjFanin0(pObj)->iTemp;
Abc_ObjForEachFanin( pObj, pFanin, k )
assert( pObj->iTemp == pFanin->iTemp );
}
}
Abc_NtkForEachPo( pNtk, pObj, i )
{
if ( !Abc_NodeIsSeriousGate(Abc_ObjFanin0(pObj)) )
continue;
assert( Abc_ObjFanin0(pObj)->iTemp == 1 );
pObj->iTemp = Abc_ObjFanin0(pObj)->iTemp;
}
assert( Count == pNtk->nBarBufs2 );
}
void Bac_NtkCreateOrConnectFanin( Abc_Obj_t * pFanin, Bac_Ntk_t * p, int iTerm )
{
int iObj;
if ( pFanin && Abc_NodeIsSeriousGate(pFanin) )//&& Bac_ObjName(p, pFanin->iTemp) == -1 ) // gate without name
{
iObj = pFanin->iTemp;
}
else if ( pFanin && (Abc_ObjIsPi(pFanin) || Abc_ObjIsBarBuf(pFanin) || Abc_NodeIsSeriousGate(pFanin)) ) // PI/BO or gate with name
{
iObj = Bac_ObjAlloc( p, BAC_OBJ_BI, pFanin->iTemp );
Bac_ObjAlloc( p, BAC_BOX_GATE, p->pDesign->ElemGates[2] ); // buffer
iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 );
}
else
{
assert( !pFanin || Abc_NodeIsConst0(pFanin) || Abc_NodeIsConst1(pFanin) );
Bac_ObjAlloc( p, BAC_BOX_GATE, p->pDesign->ElemGates[(pFanin && Abc_NodeIsConst1(pFanin))] ); // const 0/1
iObj = Bac_ObjAlloc( p, BAC_OBJ_BO, -1 );
}
Bac_ObjSetFanin( p, iTerm, iObj );
}
void Bac_NtkPrepareLibrary( Bac_Man_t * p, Mio_Library_t * pLib )
{
Mio_Gate_t * pGate;
Mio_Gate_t * pGate0 = Mio_LibraryReadConst0( pLib );
Mio_Gate_t * pGate1 = Mio_LibraryReadConst1( pLib );
Mio_Gate_t * pGate2 = Mio_LibraryReadBuf( pLib );
if ( !pGate0 || !pGate1 || !pGate2 )
{
printf( "The library does not have one of the elementary gates.\n" );
return;
}
p->ElemGates[0] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate0), NULL );
p->ElemGates[1] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate1), NULL );
p->ElemGates[2] = Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate2), NULL );
Mio_LibraryForEachGate( pLib, pGate )
if ( pGate != pGate0 && pGate != pGate1 && pGate != pGate2 )
Abc_NamStrFindOrAdd( p->pMods, Mio_GateReadName(pGate), NULL );
assert( Abc_NamObjNumMax(p->pMods) > 1 );
}
int Bac_NtkBuildLibrary( Bac_Man_t * p )
{
int RetValue = 1;
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
if ( pLib == NULL )
printf( "The standard cell library is not available.\n" ), RetValue = 0;
else
Bac_NtkPrepareLibrary( p, pLib );
p->pMioLib = pLib;
return RetValue;
}
void Bac_NtkInsertNtk( Bac_Man_t * p, Abc_Ntk_t * pNtk )
{
Bac_Ntk_t * pCbaNtk, * pRoot = Bac_ManRoot( p );
int i, j, k, iBox, iTerm, Count = 0;
Abc_Obj_t * pObj;
assert( Abc_NtkHasMapping(pNtk) );
Bac_NtkPrepareLibrary( p, (Mio_Library_t *)pNtk->pManFunc );
p->pMioLib = pNtk->pManFunc;
Abc_NtkForEachPi( pNtk, pObj, i )
pObj->iTemp = Bac_NtkPi( pRoot, i );
Abc_NtkForEachNode( pNtk, pObj, i )
{
if ( Abc_ObjIsBarBuf(pObj) )
{
pCbaNtk = Bac_ManNtk( p, Vec_IntEntry(&p->vBuf2RootNtk, Count) );
iTerm = Vec_IntEntry( &p->vBuf2RootObj, Count );
assert( Bac_ObjIsCo(pCbaNtk, iTerm) );
if ( Bac_ObjFanin(pCbaNtk, iTerm) == -1 ) // not a feedthrough
Bac_NtkCreateOrConnectFanin( Abc_ObjFanin0(pObj), pCbaNtk, iTerm );
// prepare leaf
pObj->iTemp = Vec_IntEntry( &p->vBuf2LeafObj, Count++ );
}
else if ( Abc_NodeIsSeriousGate(pObj) )
{
pCbaNtk = Bac_ManNtk( p, pObj->iTemp );
for ( k = Abc_ObjFaninNum(pObj)-1; k >= 0; k-- )
iTerm = Bac_ObjAlloc( pCbaNtk, BAC_OBJ_BI, Abc_ObjFanin(pObj, k)->iTemp );
Bac_ObjAlloc( pCbaNtk, BAC_BOX_GATE, Abc_NamStrFind(p->pMods, Mio_GateReadName((Mio_Gate_t *)pObj->pData)) );
pObj->iTemp = Bac_ObjAlloc( pCbaNtk, BAC_OBJ_BO, -1 );
}
}
assert( Count == pNtk->nBarBufs2 );
// create constant 0 drivers for COs without barbufs
Bac_ManForEachNtk( p, pCbaNtk, i )
{
Bac_NtkForEachBox( pCbaNtk, iBox )
Bac_BoxForEachBi( pCbaNtk, iBox, iTerm, j )
if ( Bac_ObjFanin(pCbaNtk, iTerm) == -1 )
Bac_NtkCreateOrConnectFanin( NULL, pCbaNtk, iTerm );
Bac_NtkForEachPo( pCbaNtk, iTerm, k )
if ( pCbaNtk != pRoot && Bac_ObjFanin(pCbaNtk, iTerm) == -1 )
Bac_NtkCreateOrConnectFanin( NULL, pCbaNtk, iTerm );
}
// create node and connect POs
Abc_NtkForEachPo( pNtk, pObj, i )
if ( Bac_ObjFanin(pRoot, Bac_NtkPo(pRoot, i)) == -1 ) // not a feedthrough
Bac_NtkCreateOrConnectFanin( Abc_ObjFanin0(pObj), pRoot, Bac_NtkPo(pRoot, i) );
}
void * Bac_ManInsertAbc( Bac_Man_t * p, void * pAbc )
{
Abc_Ntk_t * pNtk = (Abc_Ntk_t *)pAbc;
Bac_Man_t * pNew = Bac_ManDupUserBoxes( p );
Bac_ManMarkNodesAbc( p, pNtk );
Bac_ManRemapBarbufs( pNew, p );
Bac_NtkInsertNtk( pNew, pNtk );
Bac_ManMoveNames( pNew, p );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

728
src/base/bac/bacCom.c Normal file
View File

@ -0,0 +1,728 @@
/**CFile****************************************************************
FileName [bacCom.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Command handlers.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacCom.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "bacPrs.h"
#include "proof/cec/cec.h"
#include "base/main/mainInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Bac_CommandRead ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Bac_CommandWrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Bac_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Bac_CommandPut ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Bac_CommandGet ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Bac_CommandClp ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Bac_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Bac_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
static inline Bac_Man_t * Bac_AbcGetMan( Abc_Frame_t * pAbc ) { return (Bac_Man_t *)pAbc->pAbcBac; }
static inline void Bac_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcBac ) Bac_ManFree(Bac_AbcGetMan(pAbc)); }
static inline void Bac_AbcUpdateMan( Abc_Frame_t * pAbc, Bac_Man_t * p ) { Bac_AbcFreeMan(pAbc); pAbc->pAbcBac = p; }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function********************************************************************
Synopsis [Accessing current Bac_Ntk_t.]
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Abc_FrameImportPtr( Vec_Ptr_t * vPtr )
{
Bac_Man_t * p;
if ( Abc_FrameGetGlobalFrame() == NULL )
{
printf( "ABC framework is not started.\n" );
return;
}
p = Bac_PtrTransformToCba( vPtr );
if ( p == NULL )
printf( "Converting from Ptr failed.\n" );
Bac_AbcUpdateMan( Abc_FrameGetGlobalFrame(), p );
}
Vec_Ptr_t * Abc_FrameExportPtr()
{
Vec_Ptr_t * vPtr;
Bac_Man_t * p;
if ( Abc_FrameGetGlobalFrame() == NULL )
{
printf( "ABC framework is not started.\n" );
return NULL;
}
p = Bac_AbcGetMan( Abc_FrameGetGlobalFrame() );
if ( p == NULL )
printf( "There is no CBA design present.\n" );
vPtr = Bac_PtrDeriveFromCba( p );
if ( vPtr == NULL )
printf( "Converting to Ptr has failed.\n" );
return vPtr;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Bac_Init( Abc_Frame_t * pAbc )
{
Cmd_CommandAdd( pAbc, "New word level", "@_read", Bac_CommandRead, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@_write", Bac_CommandWrite, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@_ps", Bac_CommandPs, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@_put", Bac_CommandPut, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@_get", Bac_CommandGet, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@_clp", Bac_CommandClp, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@_cec", Bac_CommandCec, 0 );
Cmd_CommandAdd( pAbc, "New word level", "@_test", Bac_CommandTest, 0 );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Bac_End( Abc_Frame_t * pAbc )
{
Bac_AbcFreeMan( pAbc );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Bac_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pFile;
Bac_Man_t * p = NULL;
Vec_Ptr_t * vDes = NULL;
char * pFileName = NULL;
int c, fUseAbc = 0, fUsePtr = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "apvh" ) ) != EOF )
{
switch ( c )
{
case 'a':
fUseAbc ^= 1;
break;
case 'p':
fUsePtr ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( argc != globalUtilOptind + 1 )
{
printf( "Bac_CommandRead(): Input file name should be given on the command line.\n" );
return 0;
}
// get the file name
pFileName = argv[globalUtilOptind];
if ( (pFile = fopen( pFileName, "r" )) == NULL )
{
Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName );
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", ".smt", ".bac", NULL )) )
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
Abc_Print( 1, "\n" );
return 0;
}
fclose( pFile );
// perform reading
if ( fUseAbc || fUsePtr )
{
extern Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk );
Abc_Ntk_t * pAbcNtk = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 0 );
Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pAbcNtk );
p = Bac_PtrTransformToCba( vDes );
Bac_PtrFree( vDes ); // points to names in pAbcNtk
if ( p )
{
ABC_FREE( p->pSpec );
p->pSpec = Abc_UtilStrsav( pAbcNtk->pSpec );
}
Abc_NtkDelete( pAbcNtk );
}
else if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
{
vDes = Psr_ManReadBlif( pFileName );
if ( vDes && Vec_PtrSize(vDes) )
p = Psr_ManBuildCba( pFileName, vDes );
if ( vDes )
Psr_ManVecFree( vDes );
}
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
{
vDes = Psr_ManReadVerilog( pFileName );
if ( vDes && Vec_PtrSize(vDes) )
p = Psr_ManBuildCba( pFileName, vDes );
if ( vDes )
Psr_ManVecFree( vDes );
}
else if ( !strcmp( Extra_FileNameExtension(pFileName), "smt" ) )
{
vDes = NULL;//Psr_ManReadSmt( pFileName );
if ( vDes && Vec_PtrSize(vDes) )
p = Psr_ManBuildCba( pFileName, vDes );
if ( vDes )
Psr_ManVecFree( vDes );
}
else if ( !strcmp( Extra_FileNameExtension(pFileName), "bac" ) )
{
p = Bac_ManReadBac( pFileName );
}
else
{
printf( "Unrecognized input file extension.\n" );
return 0;
}
Bac_AbcUpdateMan( pAbc, p );
return 0;
usage:
Abc_Print( -2, "usage: @_read [-apvh] <file_name>\n" );
Abc_Print( -2, "\t reads hierarchical design in BLIF or Verilog\n" );
Abc_Print( -2, "\t-a : toggle using old ABC parser [default = %s]\n", fUseAbc? "yes": "no" );
Abc_Print( -2, "\t-p : toggle using Ptr construction [default = %s]\n", fUsePtr? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Bac_CommandWrite( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Bac_Man_t * p = Bac_AbcGetMan(pAbc);
char * pFileName = NULL;
int fUseAssign = 1;
int fUsePtr = 0;
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "apvh" ) ) != EOF )
{
switch ( c )
{
case 'a':
fUseAssign ^= 1;
break;
case 'p':
fUsePtr ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Bac_CommandWrite(): There is no current design.\n" );
return 0;
}
if ( argc == globalUtilOptind + 1 )
pFileName = argv[globalUtilOptind];
else if ( argc == globalUtilOptind && p )
pFileName = Extra_FileNameGenericAppend( Bac_ManName(p), "_out.v" );
else
{
printf( "Output file name should be given on the command line.\n" );
return 0;
}
// perform writing
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
Bac_ManWriteBlif( pFileName, p );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
{
if ( fUsePtr )
{
Vec_Ptr_t * vPtr = Bac_PtrDeriveFromCba( p );
if ( vPtr == NULL )
printf( "Converting to Ptr has failed.\n" );
else
{
Bac_PtrDumpVerilog( pFileName, vPtr );
Bac_PtrFree( vPtr );
}
}
else
Bac_ManWriteVerilog( pFileName, p, fUseAssign );
}
else if ( !strcmp( Extra_FileNameExtension(pFileName), "bac" ) )
Bac_ManWriteBac( pFileName, p );
else
{
printf( "Unrecognized output file extension.\n" );
return 0;
}
return 0;
usage:
Abc_Print( -2, "usage: @_write [-apvh]\n" );
Abc_Print( -2, "\t writes the design into a file in BLIF or Verilog\n" );
Abc_Print( -2, "\t-a : toggle using assign-statement for primitives [default = %s]\n", fUseAssign? "yes": "no" );
Abc_Print( -2, "\t-p : toggle using Ptr construction (mapped Verilog only) [default = %s]\n", fUsePtr? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Bac_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Bac_Man_t * p = Bac_AbcGetMan(pAbc);
int c, nModules = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF )
{
switch ( c )
{
case 'M':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
goto usage;
}
nModules = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nModules < 0 )
goto usage;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Bac_CommandPs(): There is no current design.\n" );
return 0;
}
Bac_ManPrintStats( p, nModules, fVerbose );
return 0;
usage:
Abc_Print( -2, "usage: @_ps [-M num] [-vh]\n" );
Abc_Print( -2, "\t prints statistics\n" );
Abc_Print( -2, "\t-M num : the number of first modules to report [default = %d]\n", nModules );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Bac_CommandPut( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Bac_Man_t * p = Bac_AbcGetMan(pAbc);
Gia_Man_t * pGia = NULL;
int c, fBarBufs = 1, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF )
{
switch ( c )
{
case 'b':
fBarBufs ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Bac_CommandPut(): There is no current design.\n" );
return 0;
}
pGia = Bac_ManExtract( p, fBarBufs, fVerbose );
if ( pGia == NULL )
{
Abc_Print( 1, "Bac_CommandPut(): Conversion to AIG has failed.\n" );
return 0;
}
Abc_FrameUpdateGia( pAbc, pGia );
return 0;
usage:
Abc_Print( -2, "usage: @_put [-bvh]\n" );
Abc_Print( -2, "\t extracts AIG from the hierarchical design\n" );
Abc_Print( -2, "\t-b : toggle using barrier buffers [default = %s]\n", fBarBufs? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Bac_CommandGet( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Bac_Man_t * pNew = NULL, * p = Bac_AbcGetMan(pAbc);
int c, fMapped = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF )
{
switch ( c )
{
case 'm':
fMapped ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Bac_CommandGet(): There is no current design.\n" );
return 0;
}
if ( fMapped )
{
if ( pAbc->pNtkCur == NULL )
{
Abc_Print( 1, "Bac_CommandGet(): There is no current mapped design.\n" );
return 0;
}
pNew = (Bac_Man_t *)Bac_ManInsertAbc( p, pAbc->pNtkCur );
}
else
{
if ( pAbc->pGia == NULL )
{
Abc_Print( 1, "Bac_CommandGet(): There is no current AIG.\n" );
return 0;
}
pNew = Bac_ManInsertGia( p, pAbc->pGia );
}
Bac_AbcUpdateMan( pAbc, pNew );
return 0;
usage:
Abc_Print( -2, "usage: @_get [-mvh]\n" );
Abc_Print( -2, "\t inserts AIG or mapped network into the hierarchical design\n" );
Abc_Print( -2, "\t-m : toggle using mapped network from main-space [default = %s]\n", fMapped? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Bac_CommandClp( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Bac_Man_t * pNew = NULL, * p = Bac_AbcGetMan(pAbc);
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Bac_CommandGet(): There is no current design.\n" );
return 0;
}
pNew = Bac_ManCollapse( p );
Bac_AbcUpdateMan( pAbc, pNew );
return 0;
usage:
Abc_Print( -2, "usage: @_clp [-vh]\n" );
Abc_Print( -2, "\t collapses the current hierarchical design\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Bac_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Bac_Man_t * p = Bac_AbcGetMan(pAbc);
Gia_Man_t * pFirst, * pSecond, * pMiter;
Cec_ParCec_t ParsCec, * pPars = &ParsCec;
Vec_Ptr_t * vDes;
char * FileName, * pStr, ** pArgvNew;
int c, nArgcNew, fDumpMiter = 0;
FILE * pFile;
Cec_ManCecSetDefaultParams( pPars );
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
pPars->fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Bac_CommandCec(): There is no current design.\n" );
return 0;
}
pArgvNew = argv + globalUtilOptind;
nArgcNew = argc - globalUtilOptind;
if ( nArgcNew != 1 )
{
if ( p->pSpec == NULL )
{
Abc_Print( -1, "File name is not given on the command line.\n" );
return 1;
}
FileName = p->pSpec;
}
else
FileName = pArgvNew[0];
// fix the wrong symbol
for ( pStr = FileName; *pStr; pStr++ )
if ( *pStr == '>' )
*pStr = '\\';
if ( (pFile = fopen( FileName, "r" )) == NULL )
{
Abc_Print( -1, "Cannot open input file \"%s\". ", FileName );
if ( (FileName = Extra_FileGetSimilarName( FileName, ".v", ".blif", NULL, NULL, NULL )) )
Abc_Print( 1, "Did you mean \"%s\"?", FileName );
Abc_Print( 1, "\n" );
return 1;
}
fclose( pFile );
// extract AIG from the current design
pFirst = Bac_ManExtract( p, 0, 0 );
if ( pFirst == NULL )
{
Abc_Print( -1, "Extracting AIG from the current design has failed.\n" );
return 0;
}
// extract AIG from the second design
if ( !strcmp( Extra_FileNameExtension(FileName), "blif" ) )
vDes = Psr_ManReadBlif( FileName );
else if ( !strcmp( Extra_FileNameExtension(FileName), "v" ) )
vDes = Psr_ManReadVerilog( FileName );
else assert( 0 );
p = Psr_ManBuildCba( FileName, vDes );
Psr_ManVecFree( vDes );
pSecond = Bac_ManExtract( p, 0, 0 );
Bac_ManFree( p );
if ( pSecond == NULL )
{
Gia_ManStop( pFirst );
Abc_Print( -1, "Extracting AIG from the original design has failed.\n" );
return 0;
}
// compute the miter
pMiter = Gia_ManMiter( pFirst, pSecond, 0, 1, 0, 0, pPars->fVerbose );
if ( pMiter )
{
if ( fDumpMiter )
{
Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" );
Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 );
}
pAbc->Status = Cec_ManVerify( pMiter, pPars );
//Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb );
Gia_ManStop( pMiter );
}
Gia_ManStop( pFirst );
Gia_ManStop( pSecond );
return 0;
usage:
Abc_Print( -2, "usage: @_cec [-vh]\n" );
Abc_Print( -2, "\t combinational equivalence checking\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Bac_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern void Psr_ManReadBlifTest();
extern void Psr_ManReadVerilogTest();
extern void Psr_SmtReadSmtTest();
//Bac_Man_t * p = Bac_AbcGetMan(pAbc);
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
/*
if ( p == NULL )
{
Abc_Print( 1, "Bac_CommandTest(): There is no current design.\n" );
return 0;
}
*/
//Bac_PtrTransformTestTest();
//Psr_ManReadVerilogTest();
//Psr_SmtReadSmtTest();
return 0;
usage:
Abc_Print( -2, "usage: @_test [-vh]\n" );
Abc_Print( -2, "\t experiments with word-level networks\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

52
src/base/bac/bacLib.c Normal file
View File

@ -0,0 +1,52 @@
/**CFile****************************************************************
FileName [bacLib.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Library procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacLib.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

603
src/base/bac/bacNtk.c Normal file
View File

@ -0,0 +1,603 @@
/**CFile****************************************************************
FileName [bacNtk.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Netlist manipulation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacNtk.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Bac_Pair_t_ Bac_Pair_t;
struct Bac_Pair_t_
{
Bac_ObjType_t Type;
char * pName;
char * pSymb;
};
static const char * s_Pref = "ABC_";
static Bac_Pair_t s_Types[BAC_BOX_UNKNOWN] =
{
{ BAC_OBJ_NONE, "NONE", NULL },
{ BAC_OBJ_PI, "PI", NULL },
{ BAC_OBJ_PO, "PO", NULL },
{ BAC_OBJ_BI, "BI", NULL },
{ BAC_OBJ_BO, "BO", NULL },
{ BAC_OBJ_BOX, "BOX", NULL },
{ BAC_BOX_CF, "CF", "o" },
{ BAC_BOX_CT, "CT", "o" },
{ BAC_BOX_CX, "CX", "o" },
{ BAC_BOX_CZ, "CZ", "o" },
{ BAC_BOX_BUF, "BUF", "ao" },
{ BAC_BOX_INV, "INV", "ao" },
{ BAC_BOX_AND, "AND", "abo" },
{ BAC_BOX_NAND, "NAND", "abo" },
{ BAC_BOX_OR, "OR", "abo" },
{ BAC_BOX_NOR, "NOR", "abo" },
{ BAC_BOX_XOR, "XOR", "abo" },
{ BAC_BOX_XNOR, "XNOR", "abo" },
{ BAC_BOX_SHARP, "SHARP", "abo" },
{ BAC_BOX_SHARPL, "SHARPL", "abo" },
{ BAC_BOX_MUX, "MUX", "cabo" },
{ BAC_BOX_MAJ, "MAJ", "abco" },
{ BAC_BOX_RAND, "RAND", "ao" },
{ BAC_BOX_RNAND, "RNAND", "ao" },
{ BAC_BOX_ROR, "ROR", "ao" },
{ BAC_BOX_RNOR, "RNOR", "ao" },
{ BAC_BOX_RXOR, "RXOR", "ao" },
{ BAC_BOX_RXNOR, "RXNOR", "ao" },
{ BAC_BOX_LAND, "LAND", "abo" },
{ BAC_BOX_LNAND, "LNAND", "abo" },
{ BAC_BOX_LOR, "LOR", "abo" },
{ BAC_BOX_LNOR, "LNOR", "abo" },
{ BAC_BOX_LXOR, "LXOR", "abo" },
{ BAC_BOX_LXNOR, "LXNOR", "abo" },
{ BAC_BOX_NMUX, "NMUX", "abo" },
{ BAC_BOX_SEL, "SEL", "abo" },
{ BAC_BOX_PSEL, "PSEL", "iabo" },
{ BAC_BOX_ENC, "ENC", "ao" },
{ BAC_BOX_PENC, "PENC", "ao" },
{ BAC_BOX_DEC, "DEC", "ao" },
{ BAC_BOX_EDEC, "EDEC", "abo" },
{ BAC_BOX_ADD, "ADD", "iabso" },
{ BAC_BOX_SUB, "SUB", "abo" },
{ BAC_BOX_MUL, "MUL", "abo" },
{ BAC_BOX_DIV, "DIV", "abo" },
{ BAC_BOX_MOD, "MOD", "abo" },
{ BAC_BOX_REM, "REM", "abo" },
{ BAC_BOX_POW, "POW", "abo" },
{ BAC_BOX_MIN, "MIN", "ao" },
{ BAC_BOX_ABS, "ABS", "ao" },
{ BAC_BOX_LTHAN, "LTHAN", "iabo" },
{ BAC_BOX_LETHAN, "LETHAN", "abo" },
{ BAC_BOX_METHAN, "METHAN", "abo" },
{ BAC_BOX_MTHAN, "MTHAN", "abo" },
{ BAC_BOX_EQU, "EQU", "abo" },
{ BAC_BOX_NEQU, "NEQU", "abo" },
{ BAC_BOX_SHIL, "SHIL", "abo" },
{ BAC_BOX_SHIR, "SHIR", "abo" },
{ BAC_BOX_ROTL, "ROTL", "abo" },
{ BAC_BOX_ROTR, "ROTR", "abo" },
{ BAC_BOX_GATE, "GATE", "io" },
{ BAC_BOX_LUT, "LUT", "io" },
{ BAC_BOX_ASSIGN, "ASSIGN", "abo" },
{ BAC_BOX_TRI, "TRI", "abo" },
{ BAC_BOX_RAM, "RAM", "eadro" },
{ BAC_BOX_RAMR, "RAMR", "eamo" },
{ BAC_BOX_RAMW, "RAMW", "eado" },
{ BAC_BOX_RAMWC, "RAMWC", "ceado" },
{ BAC_BOX_RAMBOX, "RAMBOX", "io" },
{ BAC_BOX_LATCH, "LATCH", "dvsgq" },
{ BAC_BOX_LATCHRS, "LATCHRS", "dsrgq" },
{ BAC_BOX_DFF, "DFF", "dvscq" },
{ BAC_BOX_DFFRS, "DFFRS", "dsrcq" }
};
static inline int Bac_GetTypeId( Bac_ObjType_t Type )
{
int i;
for ( i = 1; i < BAC_BOX_UNKNOWN; i++ )
if ( s_Types[i].Type == Type )
return i;
return -1;
}
void Bac_ManSetupTypes( char ** pNames, char ** pSymbs )
{
int Type;
for ( Type = 1; Type < BAC_BOX_UNKNOWN; Type++ )
{
int Id = Bac_GetTypeId( (Bac_ObjType_t)Type );
pNames[Type] = s_Types[Id].pName;
pSymbs[Type] = s_Types[Id].pSymb;
}
}
char * Bac_NtkGenerateName( Bac_Ntk_t * p, Bac_ObjType_t Type, Vec_Int_t * vBits )
{
static char Buffer[100];
char * pTemp; int i, Bits;
char * pName = Bac_ManPrimName( p->pDesign, Type );
char * pSymb = Bac_ManPrimSymb( p->pDesign, Type );
assert( Vec_IntSize(vBits) == (int)strlen(pSymb) );
sprintf( Buffer, "%s%s_", s_Pref, pName );
pTemp = Buffer + strlen(Buffer);
Vec_IntForEachEntry( vBits, Bits, i )
{
sprintf( pTemp, "%c%d", pSymb[i], Bits );
pTemp += strlen(pTemp);
}
//Vec_IntPrint( vBits );
//printf( "%s\n", Buffer );
return Buffer;
}
Bac_ObjType_t Bac_NameToType( char * pName )
{
int i;
if ( strncmp(pName, s_Pref, strlen(s_Pref)) )
return BAC_OBJ_NONE;
pName += strlen(s_Pref);
for ( i = 1; i < BAC_BOX_UNKNOWN; i++ )
if ( !strncmp(pName, s_Types[i].pName, strlen(s_Types[i].pName)) )
return s_Types[i].Type;
return BAC_OBJ_NONE;
}
Vec_Int_t * Bac_NameToRanges( char * pName )
{
static Vec_Int_t Bits, * vBits = &Bits;
static int pArray[10];
char * pTemp;
int Num = 0, Count = 0;
// initialize array
vBits->pArray = pArray;
vBits->nSize = 0;
vBits->nCap = 10;
// check the name
assert( !strncmp(pName, s_Pref, strlen(s_Pref)) );
for ( pTemp = pName; *pTemp && !Bac_CharIsDigit(*pTemp); pTemp++ );
assert( Bac_CharIsDigit(*pTemp) );
for ( ; *pTemp; pTemp++ )
{
if ( Bac_CharIsDigit(*pTemp) )
Num = 10 * Num + *pTemp - '0';
else
Vec_IntPush( vBits, Num ), Count += Num, Num = 0;
}
assert( Num > 0 );
Vec_IntPush( vBits, Num ); Count += Num;
assert( Vec_IntSize(vBits) <= 10 );
return vBits;
}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Replaces fanin iOld by iNew in all fanouts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_NtkUpdateFanout( Bac_Ntk_t * p, int iOld, int iNew )
{
int iCo;
assert( Bac_ObjIsCi(p, iOld) );
assert( Bac_ObjIsCi(p, iNew) );
Bac_ObjForEachFanout( p, iOld, iCo )
{
assert( Bac_ObjFanin(p, iCo) == iOld );
Bac_ObjCleanFanin( p, iCo );
Bac_ObjSetFanin( p, iCo, iNew );
}
Bac_ObjSetFanout( p, iNew, Bac_ObjFanout(p, iOld) );
Bac_ObjSetFanout( p, iOld, 0 );
}
/**Function*************************************************************
Synopsis [Derives fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_NtkDeriveFanout( Bac_Ntk_t * p )
{
int iCi, iCo;
assert( !Bac_NtkHasFanouts(p) );
Bac_NtkStartFanouts( p );
Bac_NtkForEachCo( p, iCo )
{
assert( !Bac_ObjNextFanout(p, iCo) );
iCi = Bac_ObjFanin(p, iCo);
if ( Bac_ObjFanout(p, iCi) )
Bac_ObjSetNextFanout( p, Bac_ObjFanout(p, iCi), iCo );
Bac_ObjSetFanout( p, iCi, iCo );
}
Bac_NtkForEachCo( p, iCo )
if ( !Bac_ObjNextFanout(p, iCo) )
Bac_ObjSetFanout( p, Bac_ObjFanin(p, iCo), iCo );
}
void Bac_ManDeriveFanout( Bac_Man_t * p )
{
Bac_Ntk_t * pNtk; int i;
Bac_ManForEachNtk( p, pNtk, i )
Bac_NtkDeriveFanout( pNtk );
}
/**Function*************************************************************
Synopsis [Assigns word-level names.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_ManAssignInternTwo( Bac_Ntk_t * p, int iNum, int nDigits, char * pPref, Vec_Int_t * vMap )
{
char Buffer[16]; int i, NameId = 0;
for ( i = 0; !NameId || Vec_IntEntry(vMap, NameId); i++ )
{
if ( i == 0 )
sprintf( Buffer, "%s%0*d", pPref, nDigits, iNum );
else
sprintf( Buffer, "%s%0*d_%d", pPref, nDigits, iNum, i );
NameId = Abc_NamStrFindOrAdd( p->pDesign->pStrs, Buffer, NULL );
}
Vec_IntWriteEntry( vMap, NameId, 1 );
return NameId;
}
int Bac_ManAssignCountNames( Bac_Ntk_t * p )
{
int i, iObj, iBox, Count = 0;
Bac_NtkForEachPiMain( p, iObj, i )
if ( !Bac_ObjNameInt(p, iObj) )
Count++;
Bac_NtkForEachBox( p, iBox )
Bac_BoxForEachBoMain( p, iBox, iObj, i )
if ( !Bac_ObjNameInt(p, iObj) )
Count++;
return Count;
}
void Bac_ManAssignInternWordNamesNtk( Bac_Ntk_t * p, Vec_Int_t * vMap )
{
int k, iObj, iTerm, iName = -1, iBit = -1;
int nDigits, nPis = 0, nPos = 0, nNames = 1;
// start names
if ( !Bac_NtkHasNames(p) )
Bac_NtkStartNames(p);
nDigits = Abc_Base10Log( Bac_ManAssignCountNames(p) );
// populate map with the currently used names
Bac_NtkForEachCi( p, iObj )
if ( Bac_ObjNameInt(p, iObj) )
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 1 );
Bac_NtkForEachBox( p, iObj )
if ( Bac_ObjNameInt(p, iObj) )
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 1 );
// assign CI names
Bac_NtkForEachCi( p, iObj )
{
if ( Bac_ObjNameInt(p, iObj) )
{
iName = -1;
iBit = -1;
continue;
}
if ( Bac_ObjBit(p, iObj) )
{
assert( iBit > 0 );
Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iBit++, BAC_NAME_INDEX) );
}
else
{
//int Type = Bac_ObjType(p, iObj);
int Range = Bac_ObjIsPi(p, iObj) ? Bac_ObjPiRange(p, iObj) : Bac_BoxBoRange(p, iObj);
iName = Bac_ManAssignInternTwo( p, nNames++, nDigits, (char*)(Bac_ObjIsPi(p, iObj) ? "i":"n"), vMap );
if ( Range == 1 )
Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_BIN) );
else
Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_WORD) );
iBit = 1;
}
}
// transfer names to the interface
if ( Bac_NtkInfoNum(p) )
{
for ( k = 0; k < Bac_NtkInfoNum(p); k++ )
{
//char * pName = Bac_NtkName(p);
if ( Bac_NtkInfoType(p, k) == 1 ) // PI
{
iObj = Bac_NtkPi(p, nPis);
assert( !Bac_ObjBit(p, iObj) );
assert( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD );
Bac_NtkSetInfoName( p, k, Abc_Var2Lit2(Bac_ObjNameId(p, iObj), 1) );
nPis += Bac_NtkInfoRange(p, k);
}
else if ( Bac_NtkInfoType(p, k) == 2 ) // PO
{
iObj = Bac_NtkPo(p, nPos);
assert( !Bac_ObjBit(p, iObj) );
iObj = Bac_ObjFanin(p, iObj);
assert( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD );
Bac_NtkSetInfoName( p, k, Abc_Var2Lit2(Bac_ObjNameId(p, iObj), 2) );
nPos += Bac_NtkInfoRange(p, k);
}
else assert( 0 );
}
assert( nPis == Bac_NtkPiNum(p) );
assert( nPos == Bac_NtkPoNum(p) );
}
// assign instance names
nDigits = Abc_Base10Log( Bac_NtkObjNum(p) );
Bac_NtkForEachBox( p, iObj )
if ( !Bac_ObjNameInt(p, iObj) )
{
iName = Bac_ManAssignInternTwo( p, iObj, nDigits, "g", vMap );
Bac_ObjSetName( p, iObj, Abc_Var2Lit2(iName, BAC_NAME_BIN) );
}
// unmark all names
Bac_NtkForEachPi( p, iObj, k )
if ( Bac_ObjNameType(p, iObj) <= BAC_NAME_WORD )
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 0 );
Bac_NtkForEachBox( p, iObj )
{
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iObj), 0 );
Bac_BoxForEachBo( p, iObj, iTerm, k )
if ( Bac_ObjNameType(p, iTerm) <= BAC_NAME_WORD )
Vec_IntWriteEntry( vMap, Bac_ObjNameId(p, iTerm), 0 );
}
// printf( "Generated %d word-level names.\n", nNames-1 );
}
void Bac_ManAssignInternWordNames( Bac_Man_t * p )
{
Vec_Int_t * vMap = Vec_IntStart( 2*Bac_ManObjNum(p) );
Bac_Ntk_t * pNtk; int i;
Bac_ManForEachNtk( p, pNtk, i )
Bac_ManAssignInternWordNamesNtk( pNtk, vMap );
assert( Vec_IntCountEntry(vMap, 0) == Vec_IntSize(vMap) );
Vec_IntFree( vMap );
}
/**Function*************************************************************
Synopsis [Count number of objects after collapsing.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_ManClpObjNum_rec( Bac_Ntk_t * p )
{
int i, Counter = 0;
if ( p->Count >= 0 )
return p->Count;
Bac_NtkForEachBox( p, i )
Counter += Bac_ObjIsBoxUser(p, i) ? Bac_ManClpObjNum_rec( Bac_BoxNtk(p, i) ) + 3*Bac_BoxBoNum(p, i) : Bac_BoxSize(p, i);
return (p->Count = Counter);
}
int Bac_ManClpObjNum( Bac_Man_t * p )
{
Bac_Ntk_t * pNtk; int i;
Bac_ManForEachNtk( p, pNtk, i )
pNtk->Count = -1;
return Bac_NtkPioNum( Bac_ManRoot(p) ) + Bac_ManClpObjNum_rec( Bac_ManRoot(p) );
}
/**Function*************************************************************
Synopsis [Collects boxes in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_NtkDfs_rec( Bac_Ntk_t * p, int iObj, Vec_Int_t * vBoxes )
{
int k, iFanin;
if ( Bac_ObjIsBo(p, iObj) == 1 )
{
Bac_NtkDfs_rec( p, Bac_ObjFanin(p, iObj), vBoxes );
return;
}
assert( Bac_ObjIsPi(p, iObj) || Bac_ObjIsBox(p, iObj) );
if ( Bac_ObjCopy(p, iObj) > 0 ) // visited
return;
Bac_ObjSetCopy( p, iObj, 1 );
Bac_BoxForEachFanin( p, iObj, iFanin, k )
Bac_NtkDfs_rec( p, iFanin, vBoxes );
Vec_IntPush( vBoxes, iObj );
}
Vec_Int_t * Bac_NtkDfs( Bac_Ntk_t * p )
{
int i, iObj;
Vec_Int_t * vBoxes = Vec_IntAlloc( Bac_NtkBoxNum(p) );
Bac_NtkStartCopies( p ); // -1 = not visited; 1 = finished
Bac_NtkForEachPi( p, iObj, i )
Bac_ObjSetCopy( p, iObj, 1 );
Bac_NtkForEachPo( p, iObj, i )
Bac_NtkDfs_rec( p, Bac_ObjFanin(p, iObj), vBoxes );
return vBoxes;
}
/**Function*************************************************************
Synopsis [Collects user boxes in the DFS order.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_NtkDfsUserBoxes_rec( Bac_Ntk_t * p, int iObj, Vec_Int_t * vBoxes )
{
int k, iFanin;
assert( Bac_ObjIsBoxUser(p, iObj) );
if ( Bac_ObjCopy(p, iObj) == 1 ) // visited
return 1;
if ( Bac_ObjCopy(p, iObj) == 0 ) // loop
return 0;
Bac_ObjSetCopy( p, iObj, 0 );
Bac_BoxForEachFanin( p, iObj, iFanin, k )
if ( Bac_ObjIsBo(p, iFanin) && Bac_ObjIsBoxUser(p, Bac_ObjFanin(p, iFanin)) )
if ( !Bac_NtkDfsUserBoxes_rec( p, Bac_ObjFanin(p, iFanin), vBoxes ) )
return 0;
Vec_IntPush( vBoxes, iObj );
Bac_ObjSetCopy( p, iObj, 1 );
return 1;
}
int Bac_NtkDfsUserBoxes( Bac_Ntk_t * p )
{
int iObj;
Bac_NtkStartCopies( p ); // -1 = not visited; 0 = on the path; 1 = finished
Vec_IntClear( &p->vArray );
Bac_NtkForEachBoxUser( p, iObj )
if ( !Bac_NtkDfsUserBoxes_rec( p, iObj, &p->vArray ) )
{
printf( "Cyclic dependency of user boxes is detected.\n" );
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_NtkCollapse_rec( Bac_Ntk_t * pNew, Bac_Ntk_t * p, Vec_Int_t * vSigs )
{
int i, iObj, iObjNew, iTerm;
Bac_NtkStartCopies( p );
// set PI copies
assert( Vec_IntSize(vSigs) == Bac_NtkPiNum(p) );
Bac_NtkForEachPi( p, iObj, i )
Bac_ObjSetCopy( p, iObj, Vec_IntEntry(vSigs, i) );
// duplicate internal objects and create buffers for hierarchy instances
Bac_NtkForEachBox( p, iObj )
if ( Bac_ObjIsBoxPrim( p, iObj ) )
Bac_BoxDup( pNew, p, iObj );
else
{
Bac_BoxForEachBo( p, iObj, iTerm, i )
{
iObjNew = Bac_ObjAlloc( pNew, BAC_OBJ_BI, -1 );
iObjNew = Bac_ObjAlloc( pNew, BAC_BOX_BUF, -1 ); // buffer
iObjNew = Bac_ObjAlloc( pNew, BAC_OBJ_BO, -1 );
Bac_ObjSetCopy( p, iTerm, iObjNew );
}
}
// duplicate user modules and connect objects
Bac_NtkForEachBox( p, iObj )
if ( Bac_ObjIsBoxPrim( p, iObj ) )
{
Bac_BoxForEachBi( p, iObj, iTerm, i )
Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iTerm), Bac_ObjCopy(p, Bac_ObjFanin(p, iTerm)) );
}
else
{
Vec_IntClear( vSigs );
Bac_BoxForEachBi( p, iObj, iTerm, i )
Vec_IntPush( vSigs, Bac_ObjCopy(p, Bac_ObjFanin(p, iTerm)) );
Bac_NtkCollapse_rec( pNew, Bac_BoxNtk(p, iObj), vSigs );
assert( Vec_IntSize(vSigs) == Bac_BoxBoNum(p, iObj) );
Bac_BoxForEachBo( p, iObj, iTerm, i )
Bac_ObjSetFanin( pNew, Bac_ObjCopy(p, iTerm)-2, Vec_IntEntry(vSigs, i) );
}
// collect POs
Vec_IntClear( vSigs );
Bac_NtkForEachPo( p, iObj, i )
Vec_IntPush( vSigs, Bac_ObjCopy(p, Bac_ObjFanin(p, iObj)) );
}
Bac_Man_t * Bac_ManCollapse( Bac_Man_t * p )
{
int i, iObj;
Vec_Int_t * vSigs = Vec_IntAlloc( 1000 );
Bac_Man_t * pNew = Bac_ManStart( p, 1 );
Bac_Ntk_t * pRoot = Bac_ManRoot( p );
Bac_Ntk_t * pRootNew = Bac_ManRoot( pNew );
Bac_NtkAlloc( pRootNew, Bac_NtkNameId(pRoot), Bac_NtkPiNum(pRoot), Bac_NtkPoNum(pRoot), Bac_ManClpObjNum(p) );
if ( Vec_IntSize(&pRoot->vInfo) )
Vec_IntAppend( &pRootNew->vInfo, &pRoot->vInfo );
Bac_NtkForEachPi( pRoot, iObj, i )
Vec_IntPush( vSigs, Bac_ObjAlloc(pRootNew, BAC_OBJ_PI, -1) );
Bac_NtkCollapse_rec( pRootNew, pRoot, vSigs );
assert( Vec_IntSize(vSigs) == Bac_NtkPoNum(pRoot) );
Bac_NtkForEachPo( pRoot, iObj, i )
Bac_ObjAlloc( pRootNew, BAC_OBJ_PO, Vec_IntEntry(vSigs, i) );
assert( Bac_NtkObjNum(pRootNew) == Bac_NtkObjNumAlloc(pRootNew) );
Vec_IntFree( vSigs );
// transfer PI/PO names
if ( Bac_NtkHasNames(pRoot) )
{
Bac_NtkStartNames( pRootNew );
Bac_NtkForEachPi( pRoot, iObj, i )
Bac_ObjSetName( pRootNew, Bac_NtkPi(pRootNew, i), Bac_ObjName(pRoot, iObj) );
Bac_NtkForEachPoDriver( pRoot, iObj, i )
if ( !Bac_ObjIsPi(pRoot, iObj) )
Bac_ObjSetName( pRootNew, Bac_ObjCopy(pRoot, iObj), Bac_ObjName(pRoot, iObj) );
}
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

365
src/base/bac/bacOper.c Normal file
View File

@ -0,0 +1,365 @@
/**CFile****************************************************************
FileName [bacOper.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Operator procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacOper.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_BoxCreate( Bac_Ntk_t * p, Bac_ObjType_t Type, Vec_Int_t * vFanins, int nInA, int nInB, int nOuts )
{
char pName[100]; int i, iObj, iFanin;
assert( BAC_OBJ_BOX < Type && Type < BAC_BOX_UNKNOWN );
if ( BAC_BOX_CF <= Type && Type <= BAC_BOX_CZ )
{
sprintf( pName, "ABCCTo%d", nOuts );
assert( 0 == Vec_IntSize(vFanins) );
iObj = Bac_BoxAlloc( p, Type, 0, nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
}
else if ( BAC_BOX_BUF <= Type && Type <= BAC_BOX_INV )
{
char * pPref[2] = { "ABCBUF", "ABCINV" };
assert( nInA == nOuts );
assert( nInA == Vec_IntSize(vFanins) );
sprintf( pName, "%sa%do%d", pPref[Type - BAC_BOX_BUF], nInA, nOuts );
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
}
else if ( BAC_BOX_AND <= Type && Type <= BAC_BOX_XNOR )
{
char * pPref[6] = { "ABCAND", "ABCNAND", "ABCOR", "ABCNOR", "ABCXOR", "ABCXNOR" };
assert( nInA == nOuts && nInB == nOuts );
assert( nInA + nInB == Vec_IntSize(vFanins) );
sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_AND], nInA, nInB, nOuts );
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
}
else if ( Type == BAC_BOX_MUX )
{
char * pPref[1] = { "ABCMUX" };
assert( nInA == nOuts && nInB == nOuts );
assert( 1 + nInA + nInB == Vec_IntSize(vFanins) );
sprintf( pName, "%sc%da%db%do%d", pPref[Type - BAC_BOX_MUX], 1, nInA, nInB, nOuts );
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
}
else if ( Type == BAC_BOX_MAJ )
{
char * pPref[1] = { "ABCMAJ" };
assert( nInA == 1 && nInB == 1 && nOuts == 1 );
assert( 3 == Vec_IntSize(vFanins) );
sprintf( pName, "%sa%db%dc%do%d", pPref[Type - BAC_BOX_MAJ], 1, 1, 1, 1 );
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
}
else if ( BAC_BOX_RAND <= Type && Type <= BAC_BOX_RXNOR )
{
char * pPref[6] = { "ABCRAND", "ABCRNAND", "ABCROR", "ABCRNOR", "ABCRXOR", "ABCRXNOR" };
assert( nInA == nInB && 1 == nOuts );
assert( nInA + nInB == Vec_IntSize(vFanins) );
sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_RAND], nInA, nInB, nOuts );
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
}
else if ( Type == BAC_BOX_SEL )
{
char * pPref[1] = { "ABCSEL" };
assert( nInA * nOuts == nInB );
assert( nInA + nInB == Vec_IntSize(vFanins) );
sprintf( pName, "%sa%db%do%d", pPref[Type - BAC_BOX_SEL], nInA, nInB, nOuts );
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
}
else if ( Type == BAC_BOX_PSEL )
{
char * pPref[1] = { "ABCPSEL" };
assert( nInA * nOuts == nInB );
assert( 1 + nInA + nInB == Vec_IntSize(vFanins) );
sprintf( pName, "%si%da%db%do%d", pPref[Type - BAC_BOX_SEL], 1, nInA, nInB, nOuts );
iObj = Bac_BoxAlloc( p, Type, Vec_IntSize(vFanins), nOuts, Abc_NamStrFindOrAdd(p->pDesign->pMods, pName, NULL) );
}
// add fanins
Vec_IntForEachEntry( vFanins, iFanin, i )
Bac_ObjSetFanin( p, Bac_BoxBi(p, iObj, i), iFanin );
return iObj;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_ObjClpWide( Bac_Ntk_t * p, int iBox )
{
Bac_ObjType_t Type = Bac_ObjType( p, iBox );
int nBis = Bac_BoxBiNum(p, iBox);
int nBos = Bac_BoxBoNum(p, iBox);
int i, k, iObj;
assert( nBos > 1 );
Vec_IntClear( &p->vArray );
if ( BAC_BOX_BUF <= Type && Type <= BAC_BOX_INV )
{
for ( i = 0; i < nBos; i++ )
{
Vec_IntFill( &p->vArray2, 1, Bac_BoxFanin(p, iBox, i) );
iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, -1, 1 );
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
}
}
else if ( BAC_BOX_AND <= Type && Type <= BAC_BOX_XNOR )
{
assert( nBis == 2 * nBos );
for ( i = 0; i < nBos; i++ )
{
Vec_IntFillTwo( &p->vArray2, 2, Bac_BoxFanin(p, iBox, i), Bac_BoxFanin(p, iBox, nBos+i) );
iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, 1, 1 );
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
}
}
else if ( Type == BAC_BOX_MUX )
{
assert( nBis - 1 == 2 * nBos );
for ( i = 0; i < nBos; i++ )
{
Vec_IntFill( &p->vArray2, 1, Bac_BoxFanin(p, iBox, 0) );
Vec_IntPushTwo( &p->vArray2, Bac_BoxFanin(p, iBox, 1+i), Bac_BoxFanin(p, iBox, 1+nBos+i) );
iObj = Bac_BoxCreate( p, Type, &p->vArray2, 1, 1, 1 );
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
}
}
else if ( Type == BAC_BOX_NMUX )
{
int n, nIns = nBis / nBos;
assert( nBis % nBos == 0 );
for ( n = 1; n < 32; n++ )
if ( n + (1 << n) == nIns )
break;
assert( n > 1 && n < 32 );
for ( i = 0; i < nBos; i++ )
{
Vec_IntClear( &p->vArray2 );
for ( k = 0; k < n; k++ )
Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, k) );
for ( k = 0; k < (1 << n); k++ )
Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, n + (1 << n) * i + k) );
iObj = Bac_BoxCreate( p, Type, &p->vArray2, n, (1 << n), 1 );
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
}
}
else if ( Type == BAC_BOX_SEL )
{
}
else if ( Type == BAC_BOX_PSEL )
{
}
else if ( Type == BAC_BOX_DFF || Type == BAC_BOX_LATCH )
{
}
else if ( Type == BAC_BOX_DFFRS || Type == BAC_BOX_LATCHRS )
{
}
else assert( 0 );
Bac_BoxReplace( p, iBox, Vec_IntArray(&p->vArray), Vec_IntSize(&p->vArray) );
return iBox;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_ObjClpArith( Bac_Ntk_t * p, int iBox )
{
Bac_ObjType_t Type = Bac_ObjType( p, iBox );
int i, iObj = -1;
int nBis = 0;//Bac_NtkReadRangesPrim( Bac_BoxNtkName(p, iObj), &p->vArray, 0 );
assert( nBis == Bac_BoxBiNum(p, iBox) );
if ( Type == BAC_BOX_ADD )
{
int Carry = Bac_BoxFanin(p, iBox, 0);
int nBits = Vec_IntEntry(&p->vArray, 1);
assert( Vec_IntSize(&p->vArray) == 3 );
assert( Vec_IntEntry(&p->vArray, 0) == 1 );
assert( Vec_IntEntry(&p->vArray, 2) == nBits );
Vec_IntClear( &p->vArray );
for ( i = 0; i < nBits; i++ )
{
Vec_IntFill( &p->vArray2, 1, Carry );
Vec_IntPushTwo( &p->vArray2, Bac_BoxFanin(p, iBox, 1+i), Bac_BoxFanin(p, iBox, 1+nBits+i) );
iObj = Bac_BoxCreate( p, BAC_BOX_ADD, &p->vArray2, 1, 1, 1 );
Carry = Bac_BoxBo(p, iObj, 1);
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, 0) );
}
Vec_IntPush( &p->vArray, Carry );
}
else if ( Type == BAC_BOX_SUB )
{
int iConst, nBits = Vec_IntEntry(&p->vArray, 0);
assert( Vec_IntSize(&p->vArray) == 2 );
assert( Vec_IntEntry(&p->vArray, 1) == nBits );
// create inverter
Vec_IntClear( &p->vArray2 );
for ( i = 0; i < nBits; i++ )
Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, nBits+i) );
iObj = Bac_BoxCreate( p, BAC_BOX_INV, &p->vArray2, nBits, -1, nBits );
// create constant
Vec_IntClear( &p->vArray2 );
iConst = Bac_BoxCreate( p, BAC_BOX_CT, &p->vArray2, -1, -1, 1 );
// collect fanins
Vec_IntFill( &p->vArray2, 1, iConst+1 );
for ( i = 0; i < nBits; i++ )
Vec_IntPush( &p->vArray2, Bac_BoxFanin(p, iBox, i) );
for ( i = 0; i < nBits; i++ )
Vec_IntPush( &p->vArray2, Bac_BoxBo(p, iObj, i) );
// create adder
iObj = Bac_BoxCreate( p, BAC_BOX_ADD, &p->vArray2, nBits, nBits, nBits );
// collect fanins
Vec_IntClear( &p->vArray );
for ( i = 0; i < nBits; i++ )
Vec_IntPush( &p->vArray, Bac_BoxBo(p, iObj, i) );
}
else if ( Type == BAC_BOX_MUL )
{
}
else if ( Type == BAC_BOX_DIV )
{
}
else if ( Type == BAC_BOX_MOD )
{
}
else if ( Type == BAC_BOX_REM )
{
}
else if ( Type == BAC_BOX_POW )
{
}
else if ( Type == BAC_BOX_MIN )
{
}
else if ( Type == BAC_BOX_ABS )
{
}
else if ( Type == BAC_BOX_LTHAN )
{
}
else if ( Type == BAC_BOX_LETHAN )
{
}
else if ( Type == BAC_BOX_METHAN )
{
}
else if ( Type == BAC_BOX_MTHAN )
{
}
else if ( Type == BAC_BOX_EQU )
{
}
else if ( Type == BAC_BOX_NEQU )
{
}
else if ( Type == BAC_BOX_SHIL )
{
}
else if ( Type == BAC_BOX_SHIR )
{
}
else if ( Type == BAC_BOX_ROTL )
{
}
else if ( Type == BAC_BOX_ROTR )
{
}
Bac_BoxReplace( p, iBox, Vec_IntArray(&p->vArray), Vec_IntSize(&p->vArray) );
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_ObjClpMemory( Bac_Ntk_t * p, int iBox )
{
int i, En, iNext, nItems = Bac_BoxBiNum(p, iBox);
assert( Bac_ObjType(p, iBox) == BAC_BOX_RAMBOX );
assert( Bac_BoxBiNum(p, iBox) == Bac_BoxBoNum(p, iBox) );
// for each fanin of RAMBOX, make sure address width is the same
Bac_BoxForEachFaninBox( p, iBox, iNext, i )
assert( Bac_ObjType(p, iNext) == BAC_BOX_RAMWC );
// create decoders, selectors and flops
for ( i = 0; i < nItems; i++ )
{
int BoxW = Bac_ObjFanin(p, Bac_BoxBi(p, iBox, i));
int BoxR = Bac_ObjFanout(p, Bac_BoxBo(p, iBox, 0));
assert( Bac_ObjType(p, BoxW) == BAC_BOX_RAMWC );
assert( Bac_ObjType(p, BoxR) == BAC_BOX_RAMR );
// create enable
Vec_IntFillTwo( &p->vArray2, 2, Bac_BoxFanin(p, BoxW, 1), Bac_BoxFanin(p, BoxR, 0) );
En = Bac_BoxCreate( p, BAC_BOX_AND, &p->vArray2, 1, 1, 1 );
En = Bac_BoxBo( p, En, 0 );
// collect address
}
// for each fanout of RAMBOX, makes ure address width is the same
// Bac_BoxForEachFanoutBox( p, iBox, iNext, i )
// assert( Bac_ObjType(p, iNext) == BAC_BOX_RAMR );
// create selectors and connect them
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

363
src/base/bac/bacPrs.h Normal file
View File

@ -0,0 +1,363 @@
/**CFile****************************************************************
FileName [bacPrs.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Parser declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacPrs.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef ABC__base__prs__prs_h
#define ABC__base__prs__prs_h
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include "aig/gia/gia.h"
#include "misc/util/utilNam.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_HEADER_START
// parser name types
typedef enum {
BAC_PRS_NAME = 0, // 0: name/variable
BAC_PRS_SLICE, // 1: slice
BAC_PRS_CONST, // 2: constant
BAC_PRS_CONCAT, // 3: concatentation
} Psr_ManType_t;
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
// network
typedef struct Psr_Ntk_t_ Psr_Ntk_t;
struct Psr_Ntk_t_
{
// general info
int iModuleName;
unsigned fMapped : 1;
unsigned fSlices : 1;
unsigned fHasC0s : 1;
unsigned fHasC1s : 1;
unsigned fHasCXs : 1;
unsigned fHasCZs : 1;
Abc_Nam_t * pStrs;
// interface
Vec_Int_t vOrder; // order of signals
// signal names
Vec_Int_t vInouts; // inouts
Vec_Int_t vInputs; // inputs
Vec_Int_t vOutputs; // outputs
Vec_Int_t vWires; // wires
// signal ranges
Vec_Int_t vInoutsR; // inouts
Vec_Int_t vInputsR; // inputs
Vec_Int_t vOutputsR; // outputs
Vec_Int_t vWiresR; // wires
// slices/concatenations/objects
Vec_Int_t vSlices; // NameId + RangeId
Vec_Int_t vConcats; // array of NameId/SliceId/ConstId
Vec_Int_t vBoxes; // ModuleId + InstId + array of pairs {FormNameId, ActSignalId(NameId/SliceId/ConstId/ConcatId)}
Vec_Int_t vObjs; // box handles
};
// parser
typedef struct Psr_Man_t_ Psr_Man_t;
struct Psr_Man_t_
{
// input data
char * pName; // file name
char * pBuffer; // file contents
char * pLimit; // end of file
char * pCur; // current position
Abc_Nam_t * pStrs; // string manager
Psr_Ntk_t * pNtk; // current network
Vec_Ptr_t * vNtks; // input networks
// temporary data
Vec_Str_t vCover; // one SOP cover
Vec_Int_t vTemp; // array of tokens
Vec_Int_t vTemp2; // array of tokens
// statistics
Vec_Int_t vKnown;
Vec_Int_t vFailed;
Vec_Int_t vSucceeded;
// error handling
int fUsingTemp2; // vTemp2 is in use
char ErrorStr[1000]; // error
};
static inline Psr_Ntk_t * Psr_ManNtk( Vec_Ptr_t * vPrs, int i ) { return i >= 0 && i < Vec_PtrSize(vPrs) ? (Psr_Ntk_t *)Vec_PtrEntry(vPrs, i) : NULL; }
static inline Psr_Ntk_t * Psr_ManRoot( Vec_Ptr_t * vPrs ) { return Psr_ManNtk(vPrs, 0); }
static inline Abc_Nam_t * Psr_ManNameMan( Vec_Ptr_t * vPrs ) { return Psr_ManRoot(vPrs)->pStrs; }
static inline int Psr_NtkId( Psr_Ntk_t * p ) { return p->iModuleName; }
static inline int Psr_NtkPioNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vInouts); }
static inline int Psr_NtkPiNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vInputs); }
static inline int Psr_NtkPoNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vOutputs); }
static inline int Psr_NtkBoxNum( Psr_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); }
static inline int Psr_NtkObjNum( Psr_Ntk_t * p ) { return Psr_NtkPioNum(p) + Psr_NtkPiNum(p) + Psr_NtkPoNum(p) + Psr_NtkBoxNum(p); }
static inline char * Psr_NtkStr( Psr_Ntk_t * p, int h ) { return Abc_NamStr(p->pStrs, h); }
static inline char * Psr_NtkName( Psr_Ntk_t * p ) { return Psr_NtkStr(p, Psr_NtkId(p)); }
static inline int Psr_NtkSigName( Psr_Ntk_t * p, int i ) { if (!p->fSlices) return i; assert(Abc_Lit2Att2(i) == BAC_PRS_NAME); return Abc_Lit2Var2(i); }
static inline int Psr_SliceName( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h); }
static inline int Psr_SliceRange( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h+1); }
static inline int Psr_CatSize( Psr_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vConcats, h); }
static inline int * Psr_CatArray( Psr_Ntk_t * p, int h ) { return Vec_IntEntryP(&p->vConcats, h+1); }
static inline Vec_Int_t * Psr_CatSignals( Psr_Ntk_t * p, int h ) { static Vec_Int_t V; V.nSize = V.nCap = Psr_CatSize(p, h); V.pArray = Psr_CatArray(p, h); return &V; }
static inline int Psr_BoxHand( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vObjs, i); }
static inline int Psr_BoxSize( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i))-2; }
static inline int Psr_BoxIONum( Psr_Ntk_t * p, int i ) { return Psr_BoxSize(p, i) / 2; }
static inline int Psr_BoxNtk( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+1); }
static inline void Psr_BoxSetNtk( Psr_Ntk_t * p, int i, int m ) { Vec_IntWriteEntry(&p->vBoxes, Psr_BoxHand(p, i)+1, m); }
static inline int Psr_BoxName( Psr_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+2); }
static inline int Psr_BoxIsNode( Psr_Ntk_t * p, int i ) { return!Vec_IntEntry(&p->vBoxes, Psr_BoxHand(p, i)+3); } // no formal names
static inline int * Psr_BoxArray( Psr_Ntk_t * p, int i ) { return Vec_IntEntryP(&p->vBoxes, Psr_BoxHand(p, i)+3); }
static inline Vec_Int_t * Psr_BoxSignals( Psr_Ntk_t * p, int i ) { static Vec_Int_t V; V.nSize = V.nCap = Psr_BoxSize(p, i); V.pArray = Psr_BoxArray(p, i); return &V; }
#define Psr_ManForEachNameVec( vVec, p, pName, i ) \
for ( i = 0; (i < Vec_IntSize(vVec)) && ((pName) = Abc_NamStr(p->pStrs, Vec_IntEntry(vVec,i))); i++ )
#define Psr_NtkForEachPio( p, NameId, i ) \
for ( i = 0; i < Psr_NtkPioNum(p) && ((NameId) = Vec_IntEntry(&p->vInouts, i)); i++ )
#define Psr_NtkForEachPi( p, NameId, i ) \
for ( i = 0; i < Psr_NtkPiNum(p) && ((NameId) = Vec_IntEntry(&p->vInputs, i)); i++ )
#define Psr_NtkForEachPo( p, NameId, i ) \
for ( i = 0; i < Psr_NtkPoNum(p) && ((NameId) = Vec_IntEntry(&p->vOutputs, i)); i++ )
#define Psr_NtkForEachBox( p, vVec, i ) \
for ( i = 0; i < Psr_NtkBoxNum(p) && ((vVec) = Psr_BoxSignals(p, i)); i++ )
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// create error message
static inline int Psr_ManErrorSet( Psr_Man_t * p, char * pError, int Value )
{
assert( !p->ErrorStr[0] );
sprintf( p->ErrorStr, "%s", pError );
return Value;
}
// clear error message
static inline void Psr_ManErrorClear( Psr_Man_t * p )
{
p->ErrorStr[0] = '\0';
}
// print error message
static inline int Psr_ManErrorPrint( Psr_Man_t * p )
{
char * pThis; int iLine = 0;
if ( !p->ErrorStr[0] ) return 1;
for ( pThis = p->pBuffer; pThis < p->pCur; pThis++ )
iLine += (int)(*pThis == '\n');
printf( "Line %d: %s\n", iLine, p->ErrorStr );
return 0;
}
// parsing network
static inline void Psr_ManInitializeNtk( Psr_Man_t * p, int iName, int fSlices )
{
assert( p->pNtk == NULL );
p->pNtk = ABC_CALLOC( Psr_Ntk_t, 1 );
p->pNtk->iModuleName = iName;
p->pNtk->fSlices = fSlices;
p->pNtk->pStrs = Abc_NamRef( p->pStrs );
Vec_PtrPush( p->vNtks, p->pNtk );
}
static inline void Psr_ManFinalizeNtk( Psr_Man_t * p )
{
assert( p->pNtk != NULL );
p->pNtk = NULL;
}
// parsing slice/concatentation/box
static inline int Psr_NtkAddSlice( Psr_Ntk_t * p, int Name, int Range )
{
int Value = Vec_IntSize(&p->vSlices);
Vec_IntPushTwo( &p->vSlices, Name, Range );
return Value;
}
static inline int Psr_NtkAddConcat( Psr_Ntk_t * p, Vec_Int_t * vTemp )
{
int Value;
if ( !(Vec_IntSize(&p->vConcats) & 1) )
Vec_IntPush(&p->vConcats, -1);
Value = Vec_IntSize(&p->vConcats);
assert( Value & 1 );
Vec_IntPush( &p->vConcats, Vec_IntSize(vTemp) );
Vec_IntAppend( &p->vConcats, vTemp );
return Value;
}
static inline void Psr_NtkAddBox( Psr_Ntk_t * p, int ModName, int InstName, Vec_Int_t * vTemp )
{
int Value;
assert( Vec_IntSize(vTemp) % 2 == 0 );
if ( !(Vec_IntSize(&p->vBoxes) & 1) )
Vec_IntPush(&p->vBoxes, -1);
Value = Vec_IntSize(&p->vBoxes);
assert( Value & 1 );
Vec_IntPush( &p->vObjs, Value );
// create entry
Vec_IntPush( &p->vBoxes, Vec_IntSize(vTemp)+2 );
Vec_IntPush( &p->vBoxes, ModName );
Vec_IntPush( &p->vBoxes, InstName );
Vec_IntAppend( &p->vBoxes, vTemp );
}
static inline char * Psr_ManLoadFile( char * pFileName, char ** ppLimit )
{
char * pBuffer;
int nFileSize, RetValue;
FILE * pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
printf( "Cannot open input file.\n" );
return NULL;
}
// get the file size, in bytes
fseek( pFile, 0, SEEK_END );
nFileSize = ftell( pFile );
// move the file current reading position to the beginning
rewind( pFile );
// load the contents of the file into memory
pBuffer = ABC_ALLOC( char, nFileSize + 16 );
pBuffer[0] = '\n';
RetValue = fread( pBuffer+1, nFileSize, 1, pFile );
fclose( pFile );
// terminate the string with '\0'
pBuffer[nFileSize + 1] = '\n';
pBuffer[nFileSize + 2] = '\0';
*ppLimit = pBuffer + nFileSize + 3;
return pBuffer;
}
static inline Psr_Man_t * Psr_ManAlloc( char * pFileName )
{
Psr_Man_t * p;
char * pBuffer, * pLimit;
pBuffer = Psr_ManLoadFile( pFileName, &pLimit );
if ( pBuffer == NULL )
return NULL;
p = ABC_CALLOC( Psr_Man_t, 1 );
p->pName = pFileName;
p->pBuffer = pBuffer;
p->pLimit = pLimit;
p->pCur = pBuffer;
p->pStrs = Abc_NamStart( 1000, 24 );
p->vNtks = Vec_PtrAlloc( 100 );
return p;
}
static inline void Psr_NtkFree( Psr_Ntk_t * p )
{
if ( p->pStrs )
Abc_NamDeref( p->pStrs );
Vec_IntErase( &p->vOrder );
Vec_IntErase( &p->vInouts );
Vec_IntErase( &p->vInputs );
Vec_IntErase( &p->vOutputs );
Vec_IntErase( &p->vWires );
Vec_IntErase( &p->vInoutsR );
Vec_IntErase( &p->vInputsR );
Vec_IntErase( &p->vOutputsR );
Vec_IntErase( &p->vWiresR );
Vec_IntErase( &p->vSlices );
Vec_IntErase( &p->vConcats );
Vec_IntErase( &p->vBoxes );
Vec_IntErase( &p->vObjs );
ABC_FREE( p );
}
static inline void Psr_ManVecFree( Vec_Ptr_t * vPrs )
{
Psr_Ntk_t * pNtk; int i;
Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i )
Psr_NtkFree( pNtk );
Vec_PtrFree( vPrs );
}
static inline void Psr_ManFree( Psr_Man_t * p )
{
if ( p->pStrs )
Abc_NamDeref( p->pStrs );
if ( p->vNtks )
Psr_ManVecFree( p->vNtks );
// temporary
Vec_StrErase( &p->vCover );
Vec_IntErase( &p->vTemp );
Vec_IntErase( &p->vTemp2 );
Vec_IntErase( &p->vKnown );
Vec_IntErase( &p->vFailed );
Vec_IntErase( &p->vSucceeded );
ABC_FREE( p->pBuffer );
ABC_FREE( p );
}
static inline int Psr_NtkMemory( Psr_Ntk_t * p )
{
int nMem = sizeof(Psr_Ntk_t);
nMem += Vec_IntMemory( &p->vOrder );
nMem += Vec_IntMemory( &p->vInouts );
nMem += Vec_IntMemory( &p->vInputs );
nMem += Vec_IntMemory( &p->vOutputs );
nMem += Vec_IntMemory( &p->vWires );
nMem += Vec_IntMemory( &p->vInoutsR );
nMem += Vec_IntMemory( &p->vInputsR );
nMem += Vec_IntMemory( &p->vOutputsR );
nMem += Vec_IntMemory( &p->vWiresR );
nMem += Vec_IntMemory( &p->vSlices );
nMem += Vec_IntMemory( &p->vBoxes );
nMem += Vec_IntMemory( &p->vConcats );
return nMem;
}
static inline int Psr_ManMemory( Vec_Ptr_t * vPrs )
{
Psr_Ntk_t * pNtk; int i;
int nMem = Vec_PtrMemory(vPrs);
Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i )
nMem += Psr_NtkMemory( pNtk );
nMem += Abc_NamMemUsed(Psr_ManNameMan(vPrs));
return nMem;
}
////////////////////////////////////////////////////////////////////////
/// ITERATORS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== bac.c ========================================================*/
ABC_NAMESPACE_HEADER_END
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

356
src/base/bac/bacPrsBuild.c Normal file
View File

@ -0,0 +1,356 @@
/**CFile****************************************************************
FileName [bacPrsBuild.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Parse tree to netlist transformation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacPrsBuild.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "bacPrs.h"
#include "map/mio/mio.h"
#include "base/main/main.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Psr_ManIsMapped( Psr_Ntk_t * pNtk )
{
Vec_Int_t * vSigs; int iBox;
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
if ( pLib == NULL )
return 0;
Psr_NtkForEachBox( pNtk, vSigs, iBox )
if ( !Psr_BoxIsNode(pNtk, iBox) )
{
int NtkId = Psr_BoxNtk( pNtk, iBox );
if ( Mio_LibraryReadGateByName(pLib, Psr_NtkStr(pNtk, NtkId), NULL) )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Psr_NtkCountObjects( Psr_Ntk_t * pNtk )
{
Vec_Int_t * vFanins;
int i, Count = Psr_NtkObjNum(pNtk);
Psr_NtkForEachBox( pNtk, vFanins, i )
Count += Psr_BoxIONum(pNtk, i);
return Count;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
// replaces NameIds of formal names by their index in the box model
void Psr_ManRemapOne( Vec_Int_t * vSigs, Psr_Ntk_t * pNtkBox, Vec_Int_t * vMap )
{
int i, NameId;
// map formal names into I/O indexes
Psr_NtkForEachPi( pNtkBox, NameId, i )
{
assert( Vec_IntEntry(vMap, NameId) == -1 );
Vec_IntWriteEntry( vMap, NameId, i + 1 ); // +1 to keep 1st form input non-zero
}
Psr_NtkForEachPo( pNtkBox, NameId, i )
{
assert( Vec_IntEntry(vMap, NameId) == -1 );
Vec_IntWriteEntry( vMap, NameId, Psr_NtkPiNum(pNtkBox) + i + 1 ); // +1 to keep 1st form input non-zero
}
// remap box
assert( Vec_IntSize(vSigs) % 2 == 0 );
Vec_IntForEachEntry( vSigs, NameId, i )
{
assert( Vec_IntEntry(vMap, NameId) != -1 );
Vec_IntWriteEntry( vSigs, i++, Vec_IntEntry(vMap, NameId) );
}
// unmap formal inputs
Psr_NtkForEachPi( pNtkBox, NameId, i )
Vec_IntWriteEntry( vMap, NameId, -1 );
Psr_NtkForEachPo( pNtkBox, NameId, i )
Vec_IntWriteEntry( vMap, NameId, -1 );
}
void Psr_ManRemapGate( Vec_Int_t * vSigs )
{
int i, FormId;
Vec_IntForEachEntry( vSigs, FormId, i )
Vec_IntWriteEntry( vSigs, i, i/2 + 1 ), i++;
}
void Psr_ManRemapBoxes( Bac_Man_t * pNew, Vec_Ptr_t * vDes, Psr_Ntk_t * pNtk, Vec_Int_t * vMap )
{
Vec_Int_t * vSigs; int iBox;
Psr_NtkForEachBox( pNtk, vSigs, iBox )
if ( !Psr_BoxIsNode(pNtk, iBox) )
{
int NtkId = Psr_BoxNtk( pNtk, iBox );
int NtkIdNew = Bac_ManNtkFindId( pNew, Psr_NtkStr(pNtk, NtkId) );
assert( NtkIdNew > 0 );
Psr_BoxSetNtk( pNtk, iBox, NtkIdNew );
if ( NtkIdNew <= Bac_ManNtkNum(pNew) )
Psr_ManRemapOne( vSigs, Psr_ManNtk(vDes, NtkIdNew-1), vMap );
//else
// Psr_ManRemapGate( vSigs );
}
}
void Psr_ManCleanMap( Psr_Ntk_t * pNtk, Vec_Int_t * vMap )
{
Vec_Int_t * vSigs;
int i, k, NameId, Sig;
Psr_NtkForEachPi( pNtk, NameId, i )
Vec_IntWriteEntry( vMap, NameId, -1 );
Psr_NtkForEachBox( pNtk, vSigs, i )
Vec_IntForEachEntryDouble( vSigs, NameId, Sig, k )
Vec_IntWriteEntry( vMap, Psr_NtkSigName(pNtk, Sig), -1 );
Psr_NtkForEachPo( pNtk, NameId, i )
Vec_IntWriteEntry( vMap, NameId, -1 );
}
// create maps of NameId and boxes
void Psr_ManBuildNtk( Bac_Ntk_t * pNew, Vec_Ptr_t * vDes, Psr_Ntk_t * pNtk, Vec_Int_t * vMap, Vec_Int_t * vBoxes )
{
Psr_Ntk_t * pNtkBox; Vec_Int_t * vSigs; int iBox;
int i, Index, NameId, iObj, iConst0, iTerm;
int iNonDriven = -1, nNonDriven = 0;
assert( Psr_NtkPioNum(pNtk) == 0 );
Psr_ManRemapBoxes( pNew->pDesign, vDes, pNtk, vMap );
Bac_NtkStartNames( pNew );
// create primary inputs
Psr_NtkForEachPi( pNtk, NameId, i )
{
if ( Vec_IntEntry(vMap, NameId) != -1 )
printf( "Primary inputs %d and %d have the same name.\n", Vec_IntEntry(vMap, NameId), i );
iObj = Bac_ObjAlloc( pNew, BAC_OBJ_PI, -1 );
Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
Vec_IntWriteEntry( vMap, NameId, iObj );
}
// create box outputs
Vec_IntClear( vBoxes );
Psr_NtkForEachBox( pNtk, vSigs, iBox )
if ( !Psr_BoxIsNode(pNtk, iBox) )
{
pNtkBox = Psr_ManNtk( vDes, Psr_BoxNtk(pNtk, iBox)-1 );
if ( pNtkBox == NULL )
{
iObj = Bac_BoxAlloc( pNew, BAC_BOX_GATE, Vec_IntSize(vSigs)/2-1, 1, Psr_BoxNtk(pNtk, iBox) );
Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(Psr_BoxName(pNtk, iBox), BAC_NAME_BIN) );
// consider box output
NameId = Vec_IntEntryLast( vSigs );
NameId = Psr_NtkSigName( pNtk, NameId );
if ( Vec_IntEntry(vMap, NameId) != -1 )
printf( "Box output name %d is already driven.\n", NameId );
iTerm = Bac_BoxBo( pNew, iObj, 0 );
Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
Vec_IntWriteEntry( vMap, NameId, iTerm );
}
else
{
iObj = Bac_BoxAlloc( pNew, BAC_OBJ_BOX, Psr_NtkPiNum(pNtkBox), Psr_NtkPoNum(pNtkBox), Psr_BoxNtk(pNtk, iBox) );
Bac_ObjSetName( pNew, iObj, Abc_Var2Lit2(Psr_BoxName(pNtk, iBox), BAC_NAME_BIN) );
Bac_NtkSetHost( Bac_ManNtk(pNew->pDesign, Psr_BoxNtk(pNtk, iBox)), Bac_NtkId(pNew), iObj );
Vec_IntForEachEntry( vSigs, Index, i )
{
i++;
if ( --Index < Psr_NtkPiNum(pNtkBox) )
continue;
assert( Index - Psr_NtkPiNum(pNtkBox) < Psr_NtkPoNum(pNtkBox) );
// consider box output
NameId = Vec_IntEntry( vSigs, i );
NameId = Psr_NtkSigName( pNtk, NameId );
if ( Vec_IntEntry(vMap, NameId) != -1 )
printf( "Box output name %d is already driven.\n", NameId );
iTerm = Bac_BoxBo( pNew, iObj, Index - Psr_NtkPiNum(pNtkBox) );
Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
Vec_IntWriteEntry( vMap, NameId, iTerm );
}
}
// remember box
Vec_IntPush( vBoxes, iObj );
}
else
{
iObj = Bac_BoxAlloc( pNew, (Bac_ObjType_t)Psr_BoxNtk(pNtk, iBox), Psr_BoxIONum(pNtk, iBox)-1, 1, -1 );
// consider box output
NameId = Vec_IntEntryLast( vSigs );
NameId = Psr_NtkSigName( pNtk, NameId );
if ( Vec_IntEntry(vMap, NameId) != -1 )
printf( "Node output name %d is already driven.\n", NameId );
iTerm = Bac_BoxBo( pNew, iObj, 0 );
Bac_ObjSetName( pNew, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
Vec_IntWriteEntry( vMap, NameId, iTerm );
// remember box
Vec_IntPush( vBoxes, iObj );
}
// add fanins for box inputs
Psr_NtkForEachBox( pNtk, vSigs, iBox )
if ( !Psr_BoxIsNode(pNtk, iBox) )
{
pNtkBox = Psr_ManNtk( vDes, Psr_BoxNtk(pNtk, iBox)-1 );
iObj = Vec_IntEntry( vBoxes, iBox );
if ( pNtkBox == NULL )
{
Vec_IntForEachEntryStop( vSigs, Index, i, Vec_IntSize(vSigs)-2 )
{
i++;
NameId = Vec_IntEntry( vSigs, i );
NameId = Psr_NtkSigName( pNtk, NameId );
iTerm = Bac_BoxBi( pNew, iObj, i/2 );
if ( Vec_IntEntry(vMap, NameId) == -1 )
{
iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 );
Vec_IntWriteEntry( vMap, NameId, iConst0+1 );
if ( iNonDriven == -1 )
iNonDriven = NameId;
nNonDriven++;
}
Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) );
}
}
else
{
Vec_IntForEachEntry( vSigs, Index, i )
{
i++;
if ( --Index >= Psr_NtkPiNum(pNtkBox) )
continue;
NameId = Vec_IntEntry( vSigs, i );
NameId = Psr_NtkSigName( pNtk, NameId );
iTerm = Bac_BoxBi( pNew, iObj, Index );
if ( Vec_IntEntry(vMap, NameId) == -1 )
{
iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 );
Vec_IntWriteEntry( vMap, NameId, iConst0+1 );
if ( iNonDriven == -1 )
iNonDriven = NameId;
nNonDriven++;
}
Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) );
}
}
}
else
{
iObj = Vec_IntEntry( vBoxes, iBox );
Vec_IntForEachEntryStop( vSigs, Index, i, Vec_IntSize(vSigs)-2 )
{
NameId = Vec_IntEntry( vSigs, ++i );
NameId = Psr_NtkSigName( pNtk, NameId );
iTerm = Bac_BoxBi( pNew, iObj, i/2 );
if ( Vec_IntEntry(vMap, NameId) == -1 )
{
iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 );
Vec_IntWriteEntry( vMap, NameId, iConst0+1 );
if ( iNonDriven == -1 )
iNonDriven = NameId;
nNonDriven++;
}
Bac_ObjSetFanin( pNew, iTerm, Vec_IntEntry(vMap, NameId) );
}
}
// add fanins for primary outputs
Psr_NtkForEachPo( pNtk, NameId, i )
if ( Vec_IntEntry(vMap, NameId) == -1 )
{
iConst0 = Bac_BoxAlloc( pNew, BAC_BOX_CF, 0, 1, -1 );
Vec_IntWriteEntry( vMap, NameId, iConst0+1 );
if ( iNonDriven == -1 )
iNonDriven = NameId;
nNonDriven++;
}
Psr_NtkForEachPo( pNtk, NameId, i )
iObj = Bac_ObjAlloc( pNew, BAC_OBJ_PO, Vec_IntEntry(vMap, NameId) );
if ( nNonDriven )
printf( "Module %s has %d non-driven nets (for example, %s).\n", Psr_NtkName(pNtk), nNonDriven, Psr_NtkStr(pNtk, iNonDriven) );
Psr_ManCleanMap( pNtk, vMap );
// setup info
Vec_IntForEachEntry( &pNtk->vOrder, NameId, i )
Bac_NtkAddInfo( pNew, NameId, -1, -1 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Bac_Man_t * Psr_ManBuildCba( char * pFileName, Vec_Ptr_t * vDes )
{
Psr_Ntk_t * pNtk = Psr_ManRoot( vDes ); int i;
Bac_Man_t * pNew = Bac_ManAlloc( pFileName, Vec_PtrSize(vDes) );
Vec_Int_t * vMap = Vec_IntStartFull( Abc_NamObjNumMax(pNtk->pStrs) + 1 );
Vec_Int_t * vTmp = Vec_IntAlloc( Psr_NtkBoxNum(pNtk) );
Abc_NamDeref( pNew->pStrs );
pNew->pStrs = Abc_NamRef( pNtk->pStrs );
Vec_PtrForEachEntry( Psr_Ntk_t *, vDes, pNtk, i )
Bac_NtkAlloc( Bac_ManNtk(pNew, i+1), Psr_NtkId(pNtk), Psr_NtkPiNum(pNtk), Psr_NtkPoNum(pNtk), Psr_NtkCountObjects(pNtk) );
if ( (pNtk->fMapped || (pNtk->fSlices && Psr_ManIsMapped(pNtk))) && !Bac_NtkBuildLibrary(pNew) )
Bac_ManFree(pNew), pNew = NULL;
else
Vec_PtrForEachEntry( Psr_Ntk_t *, vDes, pNtk, i )
Psr_ManBuildNtk( Bac_ManNtk(pNew, i+1), vDes, pNtk, vMap, vTmp );
assert( Vec_IntCountEntry(vMap, -1) == Vec_IntSize(vMap) );
Vec_IntFree( vMap );
Vec_IntFree( vTmp );
// Vec_StrPrint( &Bac_ManNtk(pNew, 1)->vType, 1 );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

211
src/base/bac/bacPrsTrans.c Normal file
View File

@ -0,0 +1,211 @@
/**CFile****************************************************************
FileName [bacPrsTrans.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Parse tree to netlist transformation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacPrsTrans.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "bacPrs.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Bac_Trip_t_ Bac_Trip_t;
struct Bac_Trip_t_
{
Bac_ObjType_t Type;
char * pName;
char * pCode;
char * pSigs[6];
};
/*
static Bac_Trip_t s_Types[100] =
{
{ BAC_BOX_CT , "VERIFIC_PWR", "1", {"o"} },
{ BAC_BOX_CF , "VERIFIC_GND", "1", {"o"} },
{ BAC_BOX_CX , "VERIFIC_X", "1", {"o"} },
{ BAC_BOX_CZ , "VERIFIC_Z", "1", {"o"} },
{ BAC_BOX_INV , "VERIFIC_INV", "11", {"i","o"} },
{ BAC_BOX_BUF , "VERIFIC_BUF", "11", {"i","o"} },
{ BAC_BOX_AND , "VERIFIC_AND", "111", {"a0","a1","o"} },
{ BAC_BOX_NAND , "VERIFIC_NAND", "111", {"a0","a1","o"} },
{ BAC_BOX_OR , "VERIFIC_OR", "111", {"a0","a1","o"} },
{ BAC_BOX_NOR , "VERIFIC_NOR", "111", {"a0","a1","o"} },
{ BAC_BOX_XOR , "VERIFIC_XOR", "111", {"a0","a1","o"} },
{ BAC_BOX_XNOR , "VERIFIC_XNOR", "111", {"a0","a1","o"} },
{ BAC_BOX_MUX , "VERIFIC_MUX", "1111", {"c","a1","a0","o"} }, // changed order
{ (Bac_ObjType_t)-1, "VERIFIC_PULLUP", "1", {"o"} },
{ (Bac_ObjType_t)-1, "VERIFIC_PULLDOWN", "1", {"o"} },
{ BAC_BOX_TRI , "VERIFIC_TRI", "111", {"i","c","o"} },
{ BAC_BOX_LATCH , "VERIFIC_DLATCH", "11111", {"d","async_val","async_cond","gate","q"} }, // changed order
{ BAC_BOX_LATCHRS , "VERIFIC_DLATCHRS", "11111", {"d","s","r","gate","q"} }, // changed order
{ BAC_BOX_DFF , "VERIFIC_DFF", "11111", {"d","async_val","async_cond","clk","q"} }, // changed order
{ BAC_BOX_DFFRS , "VERIFIC_DFFRS", "11111", {"d","s","r","clk","q"} }, // changed order
{ (Bac_ObjType_t)-1, "VERIFIC_NMOS", "111", {"c","d","o"} },
{ (Bac_ObjType_t)-1, "VERIFIC_PMOS", "111", {"c","d","o"} },
{ (Bac_ObjType_t)-1, "VERIFIC_CMOS", "1111", {"d","nc","pc","o"} },
{ (Bac_ObjType_t)-1, "VERIFIC_TRAN", "111", {"inout1","inout2","control"} },
{ BAC_BOX_ADD , "VERIFIC_FADD", "11111", {"cin","a","b","o","cout"} },
{ (Bac_ObjType_t)-1, "VERIFIC_RCMOS", "1111", {"d","nc","pc","o"} },
{ (Bac_ObjType_t)-1, "VERIFIC_RNMOS", "111", {"c","d","o"} },
{ (Bac_ObjType_t)-1, "VERIFIC_RPMOS", "111", {"c","d","o"} },
{ (Bac_ObjType_t)-1, "VERIFIC_RTRAN", "111", {"inout1","inout2","control"} },
{ (Bac_ObjType_t)-1, "VERIFIC_HDL_ASSERTION", "1", {"condition"} },
{ BAC_BOX_ADD , "add_", "1aba1", {"cin","a","b","o","cout"} },
{ BAC_BOX_MUL , "mult_", "ab?", {"a","b","o"} }, // ? = a * b
{ BAC_BOX_DIV , "div_", "ab?", {"a","b","o"} }, // ? =
{ BAC_BOX_MOD , "mod_", "ab?", {"a","b","o"} }, // ? =
{ BAC_BOX_REM , "rem_", "ab?", {"a","b","o"} }, // ? =
{ BAC_BOX_SHIL , "shift_left_", "1aba", {"cin","a","amount","o"} },
{ BAC_BOX_SHIR , "shift_right_", "1aba", {"cin","a","amount","o"} },
{ BAC_BOX_ROTL , "rotate_left_", "aba", {"a","amount","o"} },
{ BAC_BOX_ROTR , "rotate_right_", "aba", {"a","amount","o"} },
{ BAC_BOX_RAND , "reduce_and_", "ab1", {"a","o"} },
{ BAC_BOX_ROR , "reduce_or_", "ab1", {"a","o"} },
{ BAC_BOX_RXOR , "reduce_xor_", "ab1", {"a","o"} },
{ BAC_BOX_RNAND , "reduce_nand_", "ab1", {"a","o"} },
{ BAC_BOX_RNOR , "reduce_nor_", "ab1", {"a","o"} },
{ BAC_BOX_RXNOR , "reduce_xnor_", "ab1", {"a","o"} },
{ BAC_BOX_LTHAN , "LessThan_", "1ab1", {"cin","a","b","o"} },
{ BAC_BOX_NMUX , "Mux_", "ab1", {"sel","data","o"} },
{ BAC_BOX_SEL , "Select_", "aaa", {"sel","data","o"} },
{ BAC_BOX_DEC , "Decoder_", "a?", {"a","o"} }, // ? = (1 << a)
{ BAC_BOX_EDEC , "EnabledDecoder_", "1a?", {"en","i","o"} }, // ? = (1 << a)
{ BAC_BOX_PSEL , "PrioSelect_", "1aaa", {"cin","sel","data","o"} },
{ BAC_BOX_RAM , "DualPortRam_", "1abab", {"write_enable","write_address","write_data","read_address","read_data"} },
{ BAC_BOX_RAMR , "ReadPort_", "1a1b", {"read_enable", "read_address", "RAM", "read_data" } },
{ BAC_BOX_RAMW , "WritePort_", "1ab1", {"write_enable","write_address","write_data", "RAM"} },
{ BAC_BOX_RAMWC , "ClockedWritePort_", "11ab1", {"clk","write_enable","write_address","write_data", "RAM"} },
{ BAC_BOX_LUT , "lut", "?", {"i","o"} },
{ BAC_BOX_AND , "and_", "aaa", {"a","b","o"} },
{ BAC_BOX_OR , "or_", "aaa", {"a","b","o"} },
{ BAC_BOX_XOR , "xor_", "aaa", {"a","b","o"} },
{ BAC_BOX_NAND , "nand_", "aaa", {"a","b","o"} },
{ BAC_BOX_NOR , "nor_", "aaa", {"a","b","o"} },
{ BAC_BOX_XNOR , "xnor_", "aaa", {"a","b","o"} },
{ BAC_BOX_BUF , "buf_", "aa", {"i","o"} },
{ BAC_BOX_INV , "inv_", "aa", {"i","o"} },
{ BAC_BOX_TRI , "tri_", "a1a", {"i","c","o"} },
{ BAC_BOX_SUB , "sub_", "aaa", {"a","b","o"} },
{ BAC_BOX_MIN , "unary_minus_", "aa", {"i","o"} },
{ BAC_BOX_EQU , "equal_", "aa1", {"a","b","o"} },
{ BAC_BOX_NEQU , "not_equal_", "aa1", {"a","b","o"} },
{ BAC_BOX_MUX , "mux_", "1aaa", {"cond","d1","d0","o"} }, // changed order
{ BAC_BOX_NMUX , "wide_mux_", "ab?", {"sel","data","o"} }, // ? = b / (1 << a)
{ BAC_BOX_SEL , "wide_select_", "ab?", {"sel","data","o"} }, // ? = b / a
{ BAC_BOX_DFF , "wide_dff_", "aaa1a", {"d","async_val","async_cond","clock","q"} },
{ BAC_BOX_DFFRS , "wide_dlatch_", "aaa1a", {"d","set","reset","clock","q"} },
{ BAC_BOX_LATCHRS , "wide_dffrs_", "aaa1a", {"d","set","reset","clock","q"} },
{ BAC_BOX_LATCH , "wide_dlatchrs_", "aaa1a", {"d","async_val","async_cond","clock","q"} },
{ BAC_BOX_PSEL , "wide_prio_select_", "ab??", {"sel","data","carry_in","o"} }, // ? = b / a
{ BAC_BOX_POW , "pow_", "abc", {"a","b","o"} }, // ? =
{ BAC_BOX_PENC , "PrioEncoder_", "a?", {"sel","o"} },
{ BAC_BOX_ABS , "abs", "aa", {"i","o"} }
};
*/
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Count range size.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Psr_ManRangeSizeName( Psr_Ntk_t * p, int Name )
{
return 1;
}
static inline int Psr_ManRangeSizeRange( Psr_Ntk_t * p, int Range )
{
char * pStr;
int Left, Right;
if ( Range == 0 )
return 1;
pStr = Psr_NtkStr( p, Range );
assert( pStr[0] == '[' );
Left = Right = atoi( pStr + 1 );
pStr = strstr( pStr, "=" );
if ( pStr )
Right = atoi( pStr + 1 );
return 1 + (Left > Right ? Left - Right : Right - Left);
}
static inline int Psr_ManRangeSizeConst( Psr_Ntk_t * p, int Const )
{
return atoi( Psr_NtkStr(p, Const) );
}
static inline int Psr_ManRangeSizeConcat( Psr_Ntk_t * p, int Con )
{
extern int Psr_ManRangeSizeArray( Psr_Ntk_t * p, Vec_Int_t * vSlices, int Start, int Stop );
Vec_Int_t * vSigs = Psr_CatSignals(p, Con);
return Psr_ManRangeSizeArray( p, vSigs, 0, Vec_IntSize(vSigs) );
}
static inline int Psr_ManRangeSizeSignal( Psr_Ntk_t * p, int Sig )
{
int Value = Abc_Lit2Var2( Sig );
Psr_ManType_t Type = (Psr_ManType_t)Abc_Lit2Att2( Sig );
if ( Type == BAC_PRS_NAME )
return Psr_ManRangeSizeName( p, Value );
if ( Type == BAC_PRS_SLICE )
return Psr_ManRangeSizeRange( p, Psr_SliceRange(p, Value) );
if ( Type == BAC_PRS_CONST )
return Psr_ManRangeSizeConst( p, Value );
if ( Type == BAC_PRS_CONCAT )
return Psr_ManRangeSizeConcat( p, Value );
assert( 0 );
return 0;
}
int Psr_ManRangeSizeArray( Psr_Ntk_t * p, Vec_Int_t * vSlices, int Start, int Stop )
{
int i, Sig, Count = 0;
assert( Vec_IntSize(vSlices) > 0 );
Vec_IntForEachEntryStartStop( vSlices, Sig, i, Start, Stop )
Count += Psr_ManRangeSizeSignal( p, Sig );
return Count;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

470
src/base/bac/bacPtr.c Normal file
View File

@ -0,0 +1,470 @@
/**CFile****************************************************************
FileName [bacPtr.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Simple interface with external tools.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacPtr.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "base/main/mainInt.h"
#include "map/mio/mio.h"
#include "bac.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*
design = array containing design name (as the first entry in the array) followed by pointers to modules
module = array containing module name (as the first entry in the array) followed by pointers to 6 arrays:
{array of input names; array of output names; array of nodes; array of boxes,
array of floating-point input-arrival times; array of floating-point output-required times}
node = array containing output name, followed by node type, followed by input names
box = array containing model name, instance name, followed by pairs of formal/actual names for each port
Comments:
- in describing boxes
- input formal/actual name pairs should be listed before output name pairs
- the order of formal names should be the same as the order of inputs/outputs in the module description
- all formal names present in the module description should be listed
- if an input pin is not driven or an output pin has no fanout, the actual pin name is NULL
- word-level formal name "a" is written as bit-level names (a[0]. a[1], etc) ordered LSB to MSB
- the boxes can appear in any order (topological order is not expected)
- in description of nodes and boxes, primitive names should be given as char*-strings ("AndT", "OrT", etc)
- constant 0/1 nets should be driven by constant nodes having primitive names "Const0T" and "Const1T"
- primitive modules should not be written, but the list of primitives and formal names should be provided
- currently only "boxes" are supported (the array of "nodes" should contain no entries)
- arrays of input-arrival/output-required times in the module description are optional
*/
// elementary gates
typedef enum {
PTR_GATE_NONE = 0,
PTR_GATE_C0, // Const0T
PTR_GATE_C1, // Const1T
PTR_GATE_BUF, // BufT
PTR_GATE_INV, // InvT
PTR_GATE_AND, // AndT
PTR_GATE_NAND, // NandT
PTR_GATE_OR, // OrT
PTR_GATE_NOR, // NorT
PTR_GATE_XOR, // XorT
PTR_GATE_XNOR, // XnorT
PTR_GATE_UNKNOWN
} Ptr_ObjType_t;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Free Ptr.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_PtrFreeNtk( Vec_Ptr_t * vNtk )
{
Vec_PtrFree( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1) );
Vec_PtrFree( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2) );
Vec_VecFree( (Vec_Vec_t *)Vec_PtrEntry(vNtk, 3) );
Vec_VecFree( (Vec_Vec_t *)Vec_PtrEntry(vNtk, 4) );
if ( Vec_PtrSize(vNtk) > 5 )
Vec_FltFree( (Vec_Flt_t *)Vec_PtrEntry(vNtk, 5) );
if ( Vec_PtrSize(vNtk) > 6 )
Vec_FltFree( (Vec_Flt_t *)Vec_PtrEntry(vNtk, 6) );
Vec_PtrFree( vNtk );
}
void Bac_PtrFree( Vec_Ptr_t * vDes )
{
Vec_Ptr_t * vNtk; int i;
if ( !vDes ) return;
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
Bac_PtrFreeNtk( vNtk );
Vec_PtrFree( vDes );
}
/**Function*************************************************************
Synopsis [Count memory used by Ptr.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Bac_PtrMemoryArray( Vec_Ptr_t * vArray )
{
return (int)Vec_PtrMemory(vArray);
}
int Bac_PtrMemoryArrayArray( Vec_Ptr_t * vArrayArray )
{
Vec_Ptr_t * vArray; int i, nBytes = 0;
Vec_PtrForEachEntry( Vec_Ptr_t *, vArrayArray, vArray, i )
nBytes += Bac_PtrMemoryArray(vArray);
return nBytes;
}
int Bac_PtrMemoryNtk( Vec_Ptr_t * vNtk )
{
int nBytes = (int)Vec_PtrMemory(vNtk);
nBytes += Bac_PtrMemoryArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1) );
nBytes += Bac_PtrMemoryArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2) );
nBytes += Bac_PtrMemoryArrayArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3) );
nBytes += Bac_PtrMemoryArrayArray( (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) );
return nBytes;
}
int Bac_PtrMemory( Vec_Ptr_t * vDes )
{
Vec_Ptr_t * vNtk; int i, nBytes = (int)Vec_PtrMemory(vDes);
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
nBytes += Bac_PtrMemoryNtk(vNtk);
return nBytes;
}
/**Function*************************************************************
Synopsis [Dumping Ptr into a BLIF file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_PtrDumpSignalsBlif( FILE * pFile, Vec_Ptr_t * vSigs, int fSkipLastComma )
{
char * pSig; int i;
Vec_PtrForEachEntry( char *, vSigs, pSig, i )
fprintf( pFile, " %s", pSig );
}
void Bac_PtrDumpBoxBlif( FILE * pFile, Vec_Ptr_t * vBox )
{
char * pName; int i;
fprintf( pFile, ".subckt" );
fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 0) );
//fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 1) ); // do not write intance name in BLIF
Vec_PtrForEachEntryStart( char *, vBox, pName, i, 2 )
fprintf( pFile, " %s=%s", pName, (char *)Vec_PtrEntry(vBox, i+1) ), i++;
fprintf( pFile, "\n" );
}
void Bac_PtrDumpBoxesBlif( FILE * pFile, Vec_Ptr_t * vBoxes )
{
Vec_Ptr_t * vBox; int i;
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
Bac_PtrDumpBoxBlif( pFile, vBox );
}
void Bac_PtrDumpModuleBlif( FILE * pFile, Vec_Ptr_t * vNtk )
{
fprintf( pFile, ".model %s\n", (char *)Vec_PtrEntry(vNtk, 0) );
fprintf( pFile, ".inputs" );
Bac_PtrDumpSignalsBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 0 );
fprintf( pFile, "\n" );
fprintf( pFile, ".outputs" );
Bac_PtrDumpSignalsBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 1 );
fprintf( pFile, "\n" );
assert( Vec_PtrSize((Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3)) == 0 ); // no nodes; only boxes
Bac_PtrDumpBoxesBlif( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) );
fprintf( pFile, ".end\n\n" );
}
void Bac_PtrDumpBlif( char * pFileName, Vec_Ptr_t * vDes )
{
FILE * pFile;
Vec_Ptr_t * vNtk; int i;
pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open output file \"%s\".\n", pFileName );
return;
}
fprintf( pFile, "// Design \"%s\" written via Ptr in ABC on %s\n\n", (char *)Vec_PtrEntry(vDes, 0), Extra_TimeStamp() );
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
Bac_PtrDumpModuleBlif( pFile, vNtk );
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Dumping Ptr into a Verilog file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_PtrDumpSignalsVerilog( FILE * pFile, Vec_Ptr_t * vSigs, int fAlwaysComma )
{
char * pSig; int i;
Vec_PtrForEachEntry( char *, vSigs, pSig, i )
fprintf( pFile, " %s%s", pSig, (fAlwaysComma || i < Vec_PtrSize(vSigs) - 1) ? ",":"" );
}
void Bac_PtrDumpBoxVerilog( FILE * pFile, Vec_Ptr_t * vBox )
{
char * pName; int i;
fprintf( pFile, " %s", (char *)Vec_PtrEntry(vBox, 0) );
fprintf( pFile, " %s (", (char *)Vec_PtrEntry(vBox, 1) ); // write intance name in Verilog
Vec_PtrForEachEntryStart( char *, vBox, pName, i, 2 )
fprintf( pFile, ".%s(%s)%s", pName, (char *)Vec_PtrEntry(vBox, i+1), i < Vec_PtrSize(vBox) - 2 ? ", ":"" ), i++;
fprintf( pFile, ");\n" );
}
void Bac_PtrDumpBoxesVerilog( FILE * pFile, Vec_Ptr_t * vBoxes )
{
Vec_Ptr_t * vBox; int i;
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
Bac_PtrDumpBoxVerilog( pFile, vBox );
}
void Bac_PtrDumpModuleVerilog( FILE * pFile, Vec_Ptr_t * vNtk )
{
fprintf( pFile, "module %s (\n ", (char *)Vec_PtrEntry(vNtk, 0) );
Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 1 );
Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 0 );
fprintf( pFile, "\n );\n" );
fprintf( pFile, " input" );
Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1), 0 );
fprintf( pFile, ";\n" );
fprintf( pFile, " output" );
Bac_PtrDumpSignalsVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2), 0 );
fprintf( pFile, ";\n" );
assert( Vec_PtrSize((Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3)) == 0 ); // no nodes; only boxes
Bac_PtrDumpBoxesVerilog( pFile, (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4) );
fprintf( pFile, "endmodule\n\n" );
}
void Bac_PtrDumpVerilog( char * pFileName, Vec_Ptr_t * vDes )
{
FILE * pFile;
Vec_Ptr_t * vNtk; int i;
pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open output file \"%s\".\n", pFileName );
return;
}
fprintf( pFile, "// Design \"%s\" written via Ptr in ABC on %s\n\n", (char *)Vec_PtrEntry(vDes, 0), Extra_TimeStamp() );
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
Bac_PtrDumpModuleVerilog( pFile, vNtk );
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Collect elementary gates from the library.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_ManCollectGateNameOne( Mio_Library_t * pLib, Ptr_ObjType_t Type, word Truth, Vec_Ptr_t * vGateNames )
{
Mio_Gate_t * pGate = Mio_LibraryReadGateByTruth( pLib, Truth );
if ( pGate != NULL )
Vec_PtrWriteEntry( vGateNames, Type, Mio_GateReadName(pGate) );
}
Vec_Ptr_t * Bac_ManCollectGateNamesByTruth( Mio_Library_t * pLib )
{
static word uTruths6[3] = {
ABC_CONST(0xAAAAAAAAAAAAAAAA),
ABC_CONST(0xCCCCCCCCCCCCCCCC),
ABC_CONST(0xF0F0F0F0F0F0F0F0),
};
Vec_Ptr_t * vGateNames = Vec_PtrStart( PTR_GATE_UNKNOWN );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_C0, 0, vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_C1, ~(word)0, vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_BUF, uTruths6[0], vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_INV, ~uTruths6[0], vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_AND, (uTruths6[0] & uTruths6[1]), vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_NAND, ~(uTruths6[0] & uTruths6[1]), vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_OR, (uTruths6[0] | uTruths6[1]), vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_NOR, ~(uTruths6[0] | uTruths6[1]), vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_XOR, (uTruths6[0] ^ uTruths6[1]), vGateNames );
Bac_ManCollectGateNameOne( pLib, PTR_GATE_XNOR, ~(uTruths6[0] ^ uTruths6[1]), vGateNames );
return vGateNames;
}
/**Function*************************************************************
Synopsis [This procedure transforms tech-ind Ptr into mapped Ptr.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_PtrUpdateBox( Vec_Ptr_t * vBox, Vec_Ptr_t * vGatesNames )
{
Mio_Gate_t * pGate; Mio_Pin_t * pPin; int i = 1;
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
// update gate name
char * pNameNew, * pName = (char *)Vec_PtrEntry(vBox, 0);
if ( !strcmp(pName, "Const0T") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_C0);
else if ( !strcmp(pName, "Const1T") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_C1);
else if ( !strcmp(pName, "BufT") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_BUF);
else if ( !strcmp(pName, "InvT") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_INV);
else if ( !strcmp(pName, "AndT") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_AND);
else if ( !strcmp(pName, "NandT") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_NAND);
else if ( !strcmp(pName, "OrT") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_OR);
else if ( !strcmp(pName, "NorT") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_NOR);
else if ( !strcmp(pName, "XorT") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_XOR);
else if ( !strcmp(pName, "XnorT") )
pNameNew = (char *)Vec_PtrEntry(vGatesNames, PTR_GATE_XNOR);
else // user hierarchy
return;
ABC_FREE( pName );
Vec_PtrWriteEntry( vBox, 0, Abc_UtilStrsav(pNameNew) );
// remove instance name
pName = (char *)Vec_PtrEntry(vBox, 1);
ABC_FREE( pName );
Vec_PtrWriteEntry( vBox, 1, NULL );
// update formal input names
pGate = Mio_LibraryReadGateByName( pLib, pNameNew, NULL );
Mio_GateForEachPin( pGate, pPin )
{
pName = (char *)Vec_PtrEntry( vBox, 2 * i );
ABC_FREE( pName );
pNameNew = Mio_PinReadName(pPin);
Vec_PtrWriteEntry( vBox, 2 * i++, Abc_UtilStrsav(pNameNew) );
}
// update output name
pName = (char *)Vec_PtrEntry( vBox, 2 * i );
pNameNew = Mio_GateReadOutName(pGate);
Vec_PtrWriteEntry( vBox, 2 * i++, Abc_UtilStrsav(pNameNew) );
assert( 2 * i == Vec_PtrSize(vBox) );
}
Vec_Ptr_t * Bac_PtrTransformSigs( Vec_Ptr_t * vSig )
{
char * pName; int i;
Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vSig) );
Vec_PtrForEachEntry( char *, vSig, pName, i )
Vec_PtrPush( vNew, Abc_UtilStrsav(pName) );
return vNew;
}
Vec_Ptr_t * Bac_PtrTransformBox( Vec_Ptr_t * vBox, Vec_Ptr_t * vGatesNames )
{
char * pName; int i;
Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vBox) );
Vec_PtrForEachEntry( char *, vBox, pName, i )
Vec_PtrPush( vNew, Abc_UtilStrsav(pName) );
if ( vGatesNames )
Bac_PtrUpdateBox( vNew, vGatesNames );
return vNew;
}
Vec_Ptr_t * Bac_PtrTransformBoxes( Vec_Ptr_t * vBoxes, Vec_Ptr_t * vGatesNames )
{
Vec_Ptr_t * vBox; int i;
Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vBoxes) );
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
Vec_PtrPush( vNew, Bac_PtrTransformBox(vBox, vGatesNames) );
return vNew;
}
Vec_Ptr_t * Bac_PtrTransformNtk( Vec_Ptr_t * vNtk, Vec_Ptr_t * vGatesNames )
{
char * pName = (char *)Vec_PtrEntry(vNtk, 0);
Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1);
Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2);
Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4);
Vec_Ptr_t * vNew = Vec_PtrAllocExact( Vec_PtrSize(vNtk) );
Vec_PtrPush( vNew, Abc_UtilStrsav(pName) );
Vec_PtrPush( vNew, Bac_PtrTransformSigs(vInputs) );
Vec_PtrPush( vNew, Bac_PtrTransformSigs(vOutputs) );
Vec_PtrPush( vNew, Vec_PtrAllocExact(0) );
Vec_PtrPush( vNew, Bac_PtrTransformBoxes(vBoxes, vGatesNames) );
return vNew;
}
Vec_Ptr_t * Bac_PtrTransformTest( Vec_Ptr_t * vDes )
{
Mio_Library_t * pLib;
Vec_Ptr_t * vGatesNames;
Vec_Ptr_t * vNtk, * vNew; int i;
// dump BLIF before transformation
Bac_PtrDumpBlif( "test1.blif", vDes );
if ( Abc_FrameGetGlobalFrame() == NULL )
{
printf( "ABC framework is not started.\n" );
return NULL;
}
pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
if ( pLib == NULL )
{
printf( "Standard cell library is not entered.\n" );
return NULL;
}
vGatesNames = Bac_ManCollectGateNamesByTruth( pLib );
// transform
vNew = Vec_PtrAllocExact( Vec_PtrSize(vDes) );
Vec_PtrPush( vNew, Abc_UtilStrsav((char *)Vec_PtrEntry(vDes, 0)) );
Vec_PtrForEachEntryStart( Vec_Ptr_t *, vDes, vNtk, i, 1 )
Vec_PtrPush( vNew, Bac_PtrTransformNtk(vNtk, vGatesNames) );
// dump BLIF after transformation
Bac_PtrDumpBlif( "test2.blif", vNew );
Vec_PtrFree( vGatesNames );
return vNew;
}
/**Function*************************************************************
Synopsis [Test the testing procedure.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_PtrTransformTestTest()
{
char * pFileName = "c/hie/dump/1/netlist_1.v";
Abc_Ntk_t * pNtk = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 0 );
extern Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk );
Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pNtk );
Vec_Ptr_t * vNew = Bac_PtrTransformTest( vDes );
Bac_PtrFree( vDes );
Bac_PtrFree( vNew );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

486
src/base/bac/bacPtrAbc.c Normal file
View File

@ -0,0 +1,486 @@
/**CFile****************************************************************
FileName [bacPtrAbc.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Simple interface with external tools.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacPtrAbc.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "base/abc/abc.h"
#include "map/mio/mio.h"
#include "base/main/mainInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Node type conversions.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Ptr_HopToType( Abc_Obj_t * pObj )
{
static word uTruth, uTruths6[3] = {
ABC_CONST(0xAAAAAAAAAAAAAAAA),
ABC_CONST(0xCCCCCCCCCCCCCCCC),
ABC_CONST(0xF0F0F0F0F0F0F0F0),
};
assert( Abc_ObjIsNode(pObj) );
uTruth = Hop_ManComputeTruth6( (Hop_Man_t *)Abc_ObjNtk(pObj)->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj) );
/*
if ( uTruth == 0 ) return "BAC_BOX_C0";
if ( uTruth == ~(word)0 ) return "BAC_BOX_C1";
if ( uTruth == uTruths6[0] ) return "BAC_BOX_BUF";
if ( uTruth == ~uTruths6[0] ) return "BAC_BOX_INV";
if ( uTruth == (uTruths6[0] & uTruths6[1]) ) return "BAC_BOX_AND";
if ( uTruth ==~(uTruths6[0] & uTruths6[1]) ) return "BAC_BOX_NAND";
if ( uTruth == (uTruths6[0] | uTruths6[1]) ) return "BAC_BOX_OR";
if ( uTruth ==~(uTruths6[0] | uTruths6[1]) ) return "BAC_BOX_NOR";
if ( uTruth == (uTruths6[0] ^ uTruths6[1]) ) return "BAC_BOX_XOR";
if ( uTruth ==~(uTruths6[0] ^ uTruths6[1]) ) return "BAC_BOX_XNOR";
*/
if ( uTruth == 0 ) return "Const0T";
if ( uTruth == ~(word)0 ) return "Const1T";
if ( uTruth == uTruths6[0] ) return "BufT";
if ( uTruth == ~uTruths6[0] ) return "InvT";
if ( uTruth == (uTruths6[0] & uTruths6[1]) ) return "AndT";
if ( uTruth ==~(uTruths6[0] & uTruths6[1]) ) return "NandT";
if ( uTruth == (uTruths6[0] | uTruths6[1]) ) return "OrT";
if ( uTruth ==~(uTruths6[0] | uTruths6[1]) ) return "NorT";
if ( uTruth == (uTruths6[0] ^ uTruths6[1]) ) return "XorT";
if ( uTruth ==~(uTruths6[0] ^ uTruths6[1]) ) return "XnorT";
assert( 0 );
return NULL;
}
/**Function*************************************************************
Synopsis [Create Ptr from Abc_Ntk_t.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
char * Ptr_AbcObjName( Abc_Obj_t * pObj )
{
if ( Abc_ObjIsNet(pObj) || Abc_ObjIsBox(pObj) )
return Abc_ObjName(pObj);
if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) )
return Ptr_AbcObjName(Abc_ObjFanout0(pObj));
if ( Abc_ObjIsCo(pObj) )
return Ptr_AbcObjName(Abc_ObjFanin0(pObj));
assert( 0 );
return NULL;
}
static int Ptr_CheckArray( Vec_Ptr_t * vArray )
{
assert( Vec_PtrSize(vArray) == Vec_PtrCap(vArray) );
return 1;
}
Vec_Ptr_t * Ptr_AbcDeriveNode( Abc_Obj_t * pObj )
{
Abc_Obj_t * pFanin; int i;
Vec_Ptr_t * vNode = Vec_PtrAllocExact( 2 + 2 * (1 + Abc_ObjFaninNum(pObj)) );
assert( Abc_ObjIsNode(pObj) );
if ( Abc_NtkHasAig(pObj->pNtk) )
Vec_PtrPush( vNode, Ptr_HopToType(pObj) );
else if ( Abc_NtkHasSop(pObj->pNtk) )
Vec_PtrPush( vNode, Ptr_SopToTypeName((char *)pObj->pData) );
else assert( 0 );
Vec_PtrPush( vNode, Ptr_AbcObjName(pObj) );
assert( Abc_ObjFaninNum(pObj) <= 2 );
Abc_ObjForEachFanin( pObj, pFanin, i )
{
Vec_PtrPush( vNode, (void*)(i ? "r" : "l") );
Vec_PtrPush( vNode, Ptr_AbcObjName(pFanin) );
}
Vec_PtrPush( vNode, (void*)("o") );
Vec_PtrPush( vNode, Ptr_AbcObjName(pObj) );
assert( Ptr_CheckArray(vNode) );
return vNode;
}
Vec_Ptr_t * Ptr_AbcDeriveBox( Abc_Obj_t * pObj )
{
Abc_Obj_t * pNext; int i;
Abc_Ntk_t * pNtk = Abc_ObjModel(pObj);
Vec_Ptr_t * vBox = Vec_PtrAllocExact( 2 + 2 * Abc_ObjFaninNum(pObj) + 2 * Abc_ObjFanoutNum(pObj) );
assert( Abc_ObjIsBox(pObj) );
Vec_PtrPush( vBox, Abc_NtkName(pNtk) );
Vec_PtrPush( vBox, Ptr_AbcObjName(pObj) );
Abc_ObjForEachFanin( pObj, pNext, i )
{
Vec_PtrPush( vBox, Ptr_AbcObjName(Abc_NtkPi(pNtk, i)) );
Vec_PtrPush( vBox, Ptr_AbcObjName(pNext) );
}
Abc_ObjForEachFanout( pObj, pNext, i )
{
Vec_PtrPush( vBox, Ptr_AbcObjName(Abc_NtkPo(pNtk, i)) );
Vec_PtrPush( vBox, Ptr_AbcObjName(pNext) );
}
assert( Ptr_CheckArray(vBox) );
return vBox;
}
Vec_Ptr_t * Ptr_AbcDeriveBoxes( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj; int i;
Vec_Ptr_t * vBoxes = Vec_PtrAllocExact( Abc_NtkBoxNum(pNtk) + Abc_NtkNodeNum(pNtk) );
Abc_NtkForEachBox( pNtk, pObj, i )
Vec_PtrPush( vBoxes, Ptr_AbcDeriveBox(pObj) );
Abc_NtkForEachNode( pNtk, pObj, i )
Vec_PtrPush( vBoxes, Ptr_AbcDeriveNode(pObj) );
assert( Ptr_CheckArray(vBoxes) );
return vBoxes;
}
Vec_Ptr_t * Ptr_AbcDeriveInputs( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj; int i;
Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Abc_NtkPiNum(pNtk) );
Abc_NtkForEachPi( pNtk, pObj, i )
Vec_PtrPush( vSigs, Ptr_AbcObjName(pObj) );
assert( Ptr_CheckArray(vSigs) );
return vSigs;
}
Vec_Ptr_t * Ptr_AbcDeriveOutputs( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj; int i;
Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Abc_NtkPoNum(pNtk) );
Abc_NtkForEachPo( pNtk, pObj, i )
Vec_PtrPush( vSigs, Ptr_AbcObjName(pObj) );
assert( Ptr_CheckArray(vSigs) );
return vSigs;
}
Vec_Ptr_t * Ptr_AbcDeriveNtk( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNtk = Vec_PtrAllocExact( 5 );
Vec_PtrPush( vNtk, Abc_NtkName(pNtk) );
Vec_PtrPush( vNtk, Ptr_AbcDeriveInputs(pNtk) );
Vec_PtrPush( vNtk, Ptr_AbcDeriveOutputs(pNtk) );
Vec_PtrPush( vNtk, Vec_PtrAllocExact(0) );
Vec_PtrPush( vNtk, Ptr_AbcDeriveBoxes(pNtk) );
assert( Ptr_CheckArray(vNtk) );
return vNtk;
}
Vec_Ptr_t * Ptr_AbcDeriveDes( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vDes;
Abc_Ntk_t * pTemp; int i;
vDes = Vec_PtrAllocExact( 1 + Vec_PtrSize(pNtk->pDesign->vModules) );
Vec_PtrPush( vDes, pNtk->pDesign->pName );
Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
Vec_PtrPush( vDes, Ptr_AbcDeriveNtk(pTemp) );
assert( Ptr_CheckArray(vDes) );
return vDes;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Ptr_ManExperiment( Abc_Ntk_t * pNtk )
{
abctime clk = Abc_Clock();
char * pFileName = Extra_FileNameGenericAppend(pNtk->pDesign->pName, "_out.blif");
Vec_Ptr_t * vDes = Ptr_AbcDeriveDes( pNtk );
printf( "Converting to Ptr: Memory = %6.3f MB ", 1.0*Bac_PtrMemory(vDes)/(1<<20) );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
Bac_PtrDumpBlif( pFileName, vDes );
printf( "Finished writing output file \"%s\". ", pFileName );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
Bac_PtrFree( vDes );
}
/**Function*************************************************************
Synopsis [Create Bac_Man_t from tech-ind Ptr.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Ptr_NameToType( char * pSop )
{
if ( !strcmp(pSop, "Const0T") ) return BAC_BOX_CF;
if ( !strcmp(pSop, "Const1T") ) return BAC_BOX_CT;
if ( !strcmp(pSop, "BufT") ) return BAC_BOX_BUF;
if ( !strcmp(pSop, "InvT") ) return BAC_BOX_INV;
if ( !strcmp(pSop, "AndT") ) return BAC_BOX_AND;
if ( !strcmp(pSop, "NandT") ) return BAC_BOX_NAND;
if ( !strcmp(pSop, "OrT") ) return BAC_BOX_OR;
if ( !strcmp(pSop, "NorT") ) return BAC_BOX_NOR;
if ( !strcmp(pSop, "XorT") ) return BAC_BOX_XOR;
if ( !strcmp(pSop, "XnorT") ) return BAC_BOX_XNOR;
return BAC_OBJ_BOX;
}
int Ptr_ManCountNtk( Vec_Ptr_t * vNtk )
{
Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1);
Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2);
Vec_Ptr_t * vNodes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 3);
Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4);
Vec_Ptr_t * vBox; int i, Counter = 0;
assert( Vec_PtrSize(vNodes) == 0 );
Counter += Vec_PtrSize(vInputs);
Counter += Vec_PtrSize(vOutputs);
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
Counter += Vec_PtrSize(vBox)/2;
return Counter;
}
int Bac_BoxCountOutputs( Bac_Ntk_t * pNtk, char * pBoxNtk )
{
int ModuleId = Bac_ManNtkFindId( pNtk->pDesign, pBoxNtk );
if ( ModuleId == 0 )
return 1;
return Bac_NtkPoNumAlloc( Bac_ManNtk(pNtk->pDesign, ModuleId) );
}
int Bac_NtkDeriveFromPtr( Bac_Ntk_t * pNtk, Vec_Ptr_t * vNtk, Vec_Int_t * vMap, Vec_Int_t * vBox2Id )
{
char * pName, * pModuleName = (char *)Vec_PtrEntry(vNtk, 0);
Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1);
Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2);
Vec_Ptr_t * vBoxes = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 4), * vBox;
int i, k, iObj, iTerm, NameId;
// start network with the given name
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pModuleName, NULL );
assert( Bac_NtkNameId(pNtk) == NameId );
// map driven NameIds into their ObjIds for PIs
Vec_PtrForEachEntry( char *, vInputs, pName, i )
{
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL );
if ( Vec_IntGetEntryFull(vMap, NameId) != -1 )
{ printf( "PI with name \"%s\" is not unique module \"%s\".\n", pName, pModuleName ); return 0; }
iObj = Bac_ObjAlloc( pNtk, BAC_OBJ_PI, -1 );
Bac_ObjSetName( pNtk, iObj, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
Vec_IntSetEntryFull( vMap, NameId, iObj );
Bac_NtkAddInfo( pNtk, Abc_Var2Lit2(NameId, 1), -1, -1 );
}
// map driven NameIds into their ObjIds for BOs
Vec_IntClear( vBox2Id );
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
{
char * pBoxNtk = (char *)Vec_PtrEntry(vBox, 0);
char * pBoxName = (char *)Vec_PtrEntry(vBox, 1);
int nOutputs = Bac_BoxCountOutputs( pNtk, pBoxNtk );
int nInputs = Vec_PtrSize(vBox)/2 - nOutputs - 1;
int NtkId = Bac_ManNtkFindId( pNtk->pDesign, pBoxNtk );
assert( Vec_PtrSize(vBox) % 2 == 0 );
assert( nOutputs > 0 && 2*(nOutputs + 1) <= Vec_PtrSize(vBox) );
iObj = Bac_BoxAlloc( pNtk, (Bac_ObjType_t)Ptr_NameToType(pBoxNtk), nInputs, nOutputs, NtkId );
if ( NtkId > 0 )
Bac_NtkSetHost( Bac_ManNtk(pNtk->pDesign, NtkId), Bac_NtkId(pNtk), iObj );
Bac_ObjSetName( pNtk, iObj, Abc_Var2Lit2(Abc_NamStrFindOrAdd(pNtk->pDesign->pStrs, pBoxName, NULL), BAC_NAME_BIN) );
Bac_BoxForEachBo( pNtk, iObj, iTerm, k )
{
pName = (char *)Vec_PtrEntry( vBox, Vec_PtrSize(vBox) - 2*(nOutputs - k) + 1 );
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL );
if ( Vec_IntGetEntryFull(vMap, NameId) != -1 )
{ printf( "Signal \"%s\" has multiple drivers in module \"%s\".\n", pName, pModuleName ); return 0; }
Bac_ObjSetName( pNtk, iTerm, Abc_Var2Lit2(NameId, BAC_NAME_BIN) );
Vec_IntSetEntryFull( vMap, NameId, iTerm );
}
Vec_IntPush( vBox2Id, iObj );
}
assert( Vec_IntSize(vBox2Id) == Vec_PtrSize(vBoxes) );
// connect BIs
Vec_PtrForEachEntry( Vec_Ptr_t *, vBoxes, vBox, i )
{
iObj = Vec_IntEntry( vBox2Id, i );
Bac_BoxForEachBi( pNtk, iObj, iTerm, k )
{
pName = (char *)Vec_PtrEntry( vBox, 2*(k + 1) + 1 );
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL );
if ( Vec_IntGetEntryFull(vMap, NameId) == -1 )
printf( "Signal \"%s\" in not driven in module \"%s\".\n", pName, pModuleName );
Bac_ObjSetFanin( pNtk, iTerm, Vec_IntGetEntryFull(vMap, NameId) );
}
}
// connect POs
Vec_PtrForEachEntry( char *, vOutputs, pName, i )
{
NameId = Abc_NamStrFindOrAdd( pNtk->pDesign->pStrs, pName, NULL );
if ( Vec_IntGetEntryFull(vMap, NameId) == -1 )
printf( "PO with name \"%s\" in not driven in module \"%s\".\n", pName, pModuleName );
iObj = Bac_ObjAlloc( pNtk, BAC_OBJ_PO, Vec_IntGetEntryFull(vMap, NameId) );
Bac_NtkAddInfo( pNtk, Abc_Var2Lit2(NameId, 2), -1, -1 );
}
// update map
Bac_NtkForEachCi( pNtk, iObj )
Vec_IntSetEntryFull( vMap, Bac_ObjNameId(pNtk, iObj), -1 );
// double check
Vec_IntForEachEntry( vMap, iObj, i )
assert( iObj == -1 );
assert( Bac_NtkObjNum(pNtk) == Vec_StrCap(&pNtk->vType) );
return 1;
}
Bac_Man_t * Bac_PtrTransformToCba( Vec_Ptr_t * vDes )
{
char * pName = (char *)Vec_PtrEntry(vDes, 0);
Bac_Man_t * pNew = Bac_ManAlloc( pName, Vec_PtrSize(vDes) - 1 );
Vec_Int_t * vMap = Vec_IntStartFull( 1000 );
Vec_Int_t * vBox2Id = Vec_IntAlloc( 1000 );
// create interfaces
Bac_Ntk_t * pNtk; int i;
Bac_ManForEachNtk( pNew, pNtk, i )
{
Vec_Ptr_t * vNtk = (Vec_Ptr_t *)Vec_PtrEntry(vDes, i);
Vec_Ptr_t * vInputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 1);
Vec_Ptr_t * vOutputs = (Vec_Ptr_t *)Vec_PtrEntry(vNtk, 2);
int NameId = Abc_NamStrFindOrAdd( pNew->pStrs, (char *)Vec_PtrEntry(vNtk, 0), NULL );
Bac_NtkAlloc( pNtk, NameId, Vec_PtrSize(vInputs), Vec_PtrSize(vOutputs), Ptr_ManCountNtk(vNtk) );
Bac_NtkStartNames( pNtk );
}
// parse the networks
Bac_ManForEachNtk( pNew, pNtk, i )
{
Vec_Ptr_t * vNtk = (Vec_Ptr_t *)Vec_PtrEntry(vDes, i);
if ( !Bac_NtkDeriveFromPtr( pNtk, vNtk, vMap, vBox2Id ) )
break;
}
if ( i <= Bac_ManNtkNum(pNew) )
Bac_ManFree(pNew), pNew = NULL;
Vec_IntFree( vBox2Id );
Vec_IntFree( vMap );
return pNew;
}
/**Function*************************************************************
Synopsis [Create Ptr from mapped Bac_Man_t.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Bac_NtkTransformToPtrBox( Bac_Ntk_t * p, int iBox )
{
int i, iTerm, fUser = Bac_ObjIsBoxUser( p, iBox );
Bac_Ntk_t * pBoxNtk = Bac_BoxNtk( p, iBox );
Mio_Library_t * pLib = (Mio_Library_t *)p->pDesign->pMioLib;
Mio_Gate_t * pGate = pLib ? Mio_LibraryReadGateByName( pLib, Bac_BoxNtkName(p, iBox), NULL ) : NULL;
Vec_Ptr_t * vBox = Vec_PtrAllocExact( 2*Bac_BoxSize(p, iBox) );
Vec_PtrPush( vBox, Bac_BoxNtkName(p, iBox) );
Vec_PtrPush( vBox, Bac_ObjNameStr(p, iBox) );
Bac_BoxForEachBi( p, iBox, iTerm, i )
{
Vec_PtrPush( vBox, fUser ? Bac_ObjNameStr(pBoxNtk, Bac_NtkPi(pBoxNtk, i)) : Mio_GateReadPinName(pGate, i) );
Vec_PtrPush( vBox, Bac_ObjNameStr(p, iTerm) );
}
Bac_BoxForEachBo( p, iBox, iTerm, i )
{
Vec_PtrPush( vBox, fUser ? Bac_ObjNameStr(pBoxNtk, Bac_NtkPo(pBoxNtk, i)) : Mio_GateReadOutName(pGate) );
Vec_PtrPush( vBox, Bac_ObjNameStr(p, iTerm) );
}
assert( Ptr_CheckArray(vBox) );
return vBox;
}
Vec_Ptr_t * Bac_NtkTransformToPtrBoxes( Bac_Ntk_t * p )
{
int iBox;
Vec_Ptr_t * vBoxes = Vec_PtrAllocExact( Bac_NtkBoxNum(p) );
Bac_NtkForEachBox( p, iBox )
Vec_PtrPush( vBoxes, Bac_NtkTransformToPtrBox(p, iBox) );
assert( Ptr_CheckArray(vBoxes) );
return vBoxes;
}
Vec_Ptr_t * Bac_NtkTransformToPtrInputs( Bac_Ntk_t * p )
{
int i, iTerm;
Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Bac_NtkPiNum(p) );
Bac_NtkForEachPi( p, iTerm, i )
Vec_PtrPush( vSigs, Bac_ObjNameStr(p, iTerm) );
assert( Ptr_CheckArray(vSigs) );
return vSigs;
}
Vec_Ptr_t * Bac_NtkTransformToPtrOutputs( Bac_Ntk_t * p )
{
int i, iTerm;
Vec_Ptr_t * vSigs = Vec_PtrAllocExact( Bac_NtkPoNum(p) );
Bac_NtkForEachPo( p, iTerm, i )
Vec_PtrPush( vSigs, Bac_ObjNameStr(p, iTerm) );
assert( Ptr_CheckArray(vSigs) );
return vSigs;
}
Vec_Ptr_t * Bac_NtkTransformToPtr( Bac_Ntk_t * p )
{
Vec_Ptr_t * vNtk = Vec_PtrAllocExact(5);
Vec_PtrPush( vNtk, Bac_NtkName(p) );
Vec_PtrPush( vNtk, Bac_NtkTransformToPtrInputs(p) );
Vec_PtrPush( vNtk, Bac_NtkTransformToPtrOutputs(p) );
Vec_PtrPush( vNtk, Vec_PtrAllocExact(0) );
Vec_PtrPush( vNtk, Bac_NtkTransformToPtrBoxes(p) );
assert( Ptr_CheckArray(vNtk) );
return vNtk;
}
Vec_Ptr_t * Bac_PtrDeriveFromCba( Bac_Man_t * p )
{
Vec_Ptr_t * vDes;
Bac_Ntk_t * pTemp; int i;
if ( p == NULL )
return NULL;
if ( p->pMioLib == NULL )
{
printf( "Cannot transform CBA network into Ptr because it is not mapped.\n" );
return NULL;
}
Bac_ManAssignInternWordNames( p );
vDes = Vec_PtrAllocExact( 1 + Bac_ManNtkNum(p) );
Vec_PtrPush( vDes, p->pName );
Bac_ManForEachNtk( p, pTemp, i )
Vec_PtrPush( vDes, Bac_NtkTransformToPtr(pTemp) );
assert( Ptr_CheckArray(vDes) );
return vDes;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

453
src/base/bac/bacReadBlif.c Normal file
View File

@ -0,0 +1,453 @@
/**CFile****************************************************************
FileName [bacReadBlif.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [BLIF parser.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "bacPrs.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// BLIF keywords
typedef enum {
PRS_BLIF_NONE = 0, // 0: unused
PRS_BLIF_MODEL, // 1: .model
PRS_BLIF_INOUTS, // 2: .inouts
PRS_BLIF_INPUTS, // 3: .inputs
PRS_BLIF_OUTPUTS, // 4: .outputs
PRS_BLIF_NAMES, // 5: .names
PRS_BLIF_SUBCKT, // 6: .subckt
PRS_BLIF_GATE, // 7: .gate
PRS_BLIF_LATCH, // 8: .latch
PRS_BLIF_SHORT, // 9: .short
PRS_BLIF_END, // 10: .end
PRS_BLIF_UNKNOWN // 11: unknown
} Bac_BlifType_t;
static const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = {
NULL, // 0: unused
".model", // 1: .model
".inouts", // 2: .inputs
".inputs", // 3: .inputs
".outputs", // 4: .outputs
".names", // 5: .names
".subckt", // 6: .subckt
".gate", // 7: .gate
".latch", // 8: .latch
".short", // 9: .short
".end", // 10: .end
NULL // 11: unknown
};
static inline void Psr_NtkAddBlifDirectives( Psr_Man_t * p )
{
int i;
for ( i = 1; s_BlifTypes[i]; i++ )
Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL );
assert( Abc_NamObjNumMax(p->pStrs) == i );
}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Reading characters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Psr_CharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r'; }
static inline int Psr_CharIsStop( char c ) { return c == '#' || c == '\\' || c == '\n' || c == '='; }
static inline int Psr_CharIsLit( char c ) { return c == '0' || c == '1' || c == '-'; }
static inline int Psr_ManIsSpace( Psr_Man_t * p ) { return Psr_CharIsSpace(*p->pCur); }
static inline int Psr_ManIsStop( Psr_Man_t * p ) { return Psr_CharIsStop(*p->pCur); }
static inline int Psr_ManIsLit( Psr_Man_t * p ) { return Psr_CharIsLit(*p->pCur); }
static inline int Psr_ManIsChar( Psr_Man_t * p, char c ) { return *p->pCur == c; }
static inline int Psr_ManIsChar2( Psr_Man_t * p, char c ) { return *p->pCur++ == c; }
static inline void Psr_ManSkip( Psr_Man_t * p ) { p->pCur++; }
static inline char Psr_ManSkip2( Psr_Man_t * p ) { return *p->pCur++; }
/**Function*************************************************************
Synopsis [Reading names.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Psr_ManSkipToChar( Psr_Man_t * p, char c )
{
while ( !Psr_ManIsChar(p, c) )
Psr_ManSkip(p);
}
static inline void Psr_ManSkipSpaces( Psr_Man_t * p )
{
while ( 1 )
{
while ( Psr_ManIsSpace(p) )
Psr_ManSkip(p);
if ( Psr_ManIsChar(p, '\\') )
{
Psr_ManSkipToChar( p, '\n' );
Psr_ManSkip(p);
continue;
}
if ( Psr_ManIsChar(p, '#') )
Psr_ManSkipToChar( p, '\n' );
break;
}
assert( !Psr_ManIsSpace(p) );
}
static inline int Psr_ManReadName( Psr_Man_t * p )
{
char * pStart;
Psr_ManSkipSpaces( p );
if ( Psr_ManIsChar(p, '\n') )
return 0;
pStart = p->pCur;
while ( !Psr_ManIsSpace(p) && !Psr_ManIsStop(p) )
Psr_ManSkip(p);
if ( pStart == p->pCur )
return 0;
return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
}
static inline int Psr_ManReadList( Psr_Man_t * p, Vec_Int_t * vOrder, int Type )
{
int iToken;
Vec_IntClear( &p->vTemp );
while ( (iToken = Psr_ManReadName(p)) )
{
Vec_IntPush( &p->vTemp, iToken );
Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) );
}
if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Signal list is empty.", 1);
return 0;
}
static inline int Psr_ManReadList2( Psr_Man_t * p )
{
int iToken;
Vec_IntClear( &p->vTemp );
while ( (iToken = Psr_ManReadName(p)) )
Vec_IntPushTwo( &p->vTemp, 0, iToken );
if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Signal list is empty.", 1);
return 0;
}
static inline int Psr_ManReadList3( Psr_Man_t * p )
{
Vec_IntClear( &p->vTemp );
while ( !Psr_ManIsChar(p, '\n') )
{
int iToken = Psr_ManReadName(p);
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read formal name.", 1);
Vec_IntPush( &p->vTemp, iToken );
Psr_ManSkipSpaces( p );
if ( !Psr_ManIsChar2(p, '=') ) return Psr_ManErrorSet(p, "Cannot find symbol \"=\".", 1);
iToken = Psr_ManReadName(p);
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read actual name.", 1);
Vec_IntPush( &p->vTemp, iToken );
Psr_ManSkipSpaces( p );
}
if ( Vec_IntSize(&p->vTemp) == 0 ) return Psr_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1);
if ( Vec_IntSize(&p->vTemp) % 2 ) return Psr_ManErrorSet(p, "The number of formal/actual names is not even.", 1);
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Psr_ManReadCube( Psr_Man_t * p )
{
assert( Psr_ManIsLit(p) );
while ( Psr_ManIsLit(p) )
Vec_StrPush( &p->vCover, Psr_ManSkip2(p) );
Psr_ManSkipSpaces( p );
if ( Psr_ManIsChar(p, '\n') )
{
if ( Vec_StrSize(&p->vCover) != 1 ) return Psr_ManErrorSet(p, "Cannot read cube.", 1);
// fix single literal cube by adding space
Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) );
Vec_StrWriteEntry( &p->vCover, 0, ' ' );
Vec_StrPush( &p->vCover, '\n' );
return 0;
}
if ( !Psr_ManIsLit(p) ) return Psr_ManErrorSet(p, "Cannot read output literal.", 1);
Vec_StrPush( &p->vCover, ' ' );
Vec_StrPush( &p->vCover, Psr_ManSkip2(p) );
Vec_StrPush( &p->vCover, '\n' );
Psr_ManSkipSpaces( p );
if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Cannot read end of cube.", 1);
return 0;
}
static inline void Psr_ManSaveCover( Psr_Man_t * p )
{
int iToken;
if ( Vec_StrSize(&p->vCover) == 0 )
p->pNtk->fHasC0s = 1;
else if ( Vec_StrSize(&p->vCover) == 2 )
{
if ( Vec_StrEntryLast(&p->vCover) == '0' )
p->pNtk->fHasC0s = 1;
else if ( Vec_StrEntryLast(&p->vCover) == '1' )
p->pNtk->fHasC1s = 1;
else assert( 0 );
}
assert( Vec_StrSize(&p->vCover) > 0 );
Vec_StrPush( &p->vCover, '\0' );
//iToken = Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL );
iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) );
Vec_StrClear( &p->vCover );
// set the cover to the module of this box
assert( Psr_BoxNtk(p->pNtk, Psr_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0
Psr_BoxSetNtk( p->pNtk, Psr_NtkBoxNum(p->pNtk)-1, iToken );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Psr_ManReadInouts( Psr_Man_t * p )
{
if ( Psr_ManReadList(p, &p->pNtk->vOrder, 3) ) return 1;
Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp );
return 0;
}
static inline int Psr_ManReadInputs( Psr_Man_t * p )
{
if ( Psr_ManReadList(p, &p->pNtk->vOrder, 1) ) return 1;
Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp );
return 0;
}
static inline int Psr_ManReadOutputs( Psr_Man_t * p )
{
if ( Psr_ManReadList(p, &p->pNtk->vOrder, 2) ) return 1;
Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp );
return 0;
}
static inline int Psr_ManReadNode( Psr_Man_t * p )
{
if ( Psr_ManReadList2(p) ) return 1;
// save results
Psr_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function
return 0;
}
static inline int Psr_ManReadBox( Psr_Man_t * p, int fGate )
{
int iToken = Psr_ManReadName(p);
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read model name.", 1);
if ( Psr_ManReadList3(p) ) return 1;
// save results
Psr_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
if ( fGate ) p->pNtk->fMapped = 1;
return 0;
}
static inline int Psr_ManReadLatch( Psr_Man_t * p )
{
int iToken = Psr_ManReadName(p);
Vec_IntClear( &p->vTemp );
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read latch input.", 1);
Vec_IntWriteEntry( &p->vTemp, 1, iToken );
iToken = Psr_ManReadName(p);
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read latch output.", 1);
Vec_IntWriteEntry( &p->vTemp, 0, iToken );
Psr_ManSkipSpaces( p );
if ( Psr_ManIsChar(p, '0') )
iToken = 0;
else if ( Psr_ManIsChar(p, '1') )
iToken = 1;
else
iToken = 2;
Psr_ManSkipToChar( p, '\n' );
// save results
Psr_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch
return 0;
}
static inline int Psr_ManReadShort( Psr_Man_t * p )
{
int iToken = Psr_ManReadName(p);
Vec_IntClear( &p->vTemp );
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read .short input.", 1);
Vec_IntWriteEntry( &p->vTemp, 1, iToken );
iToken = Psr_ManReadName(p);
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read .short output.", 1);
Vec_IntWriteEntry( &p->vTemp, 0, iToken );
Psr_ManSkipSpaces( p );
if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .short line.", 1);
// save results
iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL );
Psr_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
return 0;
}
static inline int Psr_ManReadModel( Psr_Man_t * p )
{
int iToken;
if ( p->pNtk != NULL ) return Psr_ManErrorSet(p, "Parsing previous model is unfinished.", 1);
iToken = Psr_ManReadName(p);
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read model name.", 1);
Psr_ManInitializeNtk( p, iToken, 0 );
Psr_ManSkipSpaces( p );
if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .model line.", 1);
return 0;
}
static inline int Psr_ManReadEnd( Psr_Man_t * p )
{
if ( p->pNtk == 0 ) return Psr_ManErrorSet(p, "Directive .end without .model.", 1);
//printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) );
Psr_ManFinalizeNtk( p );
Psr_ManSkipSpaces( p );
if ( !Psr_ManIsChar(p, '\n') ) return Psr_ManErrorSet(p, "Trailing symbols on .end line.", 1);
return 0;
}
static inline int Psr_ManReadDirective( Psr_Man_t * p )
{
int iToken;
if ( !Psr_ManIsChar(p, '.') )
return Psr_ManReadCube( p );
if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node
Psr_ManSaveCover( p );
iToken = Psr_ManReadName( p );
if ( iToken == PRS_BLIF_MODEL )
return Psr_ManReadModel( p );
if ( iToken == PRS_BLIF_INOUTS )
return Psr_ManReadInouts( p );
if ( iToken == PRS_BLIF_INPUTS )
return Psr_ManReadInputs( p );
if ( iToken == PRS_BLIF_OUTPUTS )
return Psr_ManReadOutputs( p );
if ( iToken == PRS_BLIF_NAMES )
return Psr_ManReadNode( p );
if ( iToken == PRS_BLIF_SUBCKT )
return Psr_ManReadBox( p, 0 );
if ( iToken == PRS_BLIF_GATE )
return Psr_ManReadBox( p, 1 );
if ( iToken == PRS_BLIF_LATCH )
return Psr_ManReadLatch( p );
if ( iToken == PRS_BLIF_SHORT )
return Psr_ManReadShort( p );
if ( iToken == PRS_BLIF_END )
return Psr_ManReadEnd( p );
printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
return 1;
}
static inline int Psr_ManReadLines( Psr_Man_t * p )
{
while ( p->pCur[1] != '\0' )
{
assert( Psr_ManIsChar(p, '\n') );
Psr_ManSkip(p);
Psr_ManSkipSpaces( p );
if ( Psr_ManIsChar(p, '\n') )
continue;
if ( Psr_ManReadDirective(p) )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Psr_ManReadBlif( char * pFileName )
{
Vec_Ptr_t * vPrs = NULL;
Psr_Man_t * p = Psr_ManAlloc( pFileName );
if ( p == NULL )
return NULL;
Psr_NtkAddBlifDirectives( p );
Psr_ManReadLines( p );
if ( Psr_ManErrorPrint(p) )
ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
Psr_ManFree( p );
return vPrs;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Psr_ManReadBlifTest()
{
abctime clk = Abc_Clock();
extern void Psr_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs );
// Vec_Ptr_t * vPrs = Psr_ManReadBlif( "aga/ray/ray_hie_oper.blif" );
Vec_Ptr_t * vPrs = Psr_ManReadBlif( "c/hie/dump/1/netlist_1_out8.blif" );
if ( !vPrs ) return;
printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) );
printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
// Abc_NamPrint( p->pStrs );
Psr_ManWriteBlif( "c/hie/dump/1/netlist_1_out8_out.blif", vPrs );
Psr_ManVecFree( vPrs );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

42
src/base/bac/bacReadSmt.c Normal file
View File

@ -0,0 +1,42 @@
/**CFile****************************************************************
FileName [bacReadSmt.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [BLIF parser.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacReadSmt.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

875
src/base/bac/bacReadVer.c Normal file
View File

@ -0,0 +1,875 @@
/**CFile****************************************************************
FileName [bacReadVer.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [BLIF writer.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacReadVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "bacPrs.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// Verilog keywords
typedef enum {
PRS_VER_NONE = 0, // 0: unused
PRS_VER_INPUT, // 1: input
PRS_VER_OUTPUT, // 2: output
PRS_VER_INOUT, // 3: inout
PRS_VER_WIRE, // 4: wire
PRS_VER_MODULE, // 5: module
PRS_VER_ASSIGN, // 6: assign
PRS_VER_REG, // 7: reg
PRS_VER_ALWAYS, // 8: always
PRS_VER_DEFPARAM, // 9: always
PRS_VER_BEGIN, // 10: begin
PRS_VER_END, // 11: end
PRS_VER_ENDMODULE, // 12: endmodule
PRS_VER_UNKNOWN // 13: unknown
} Bac_VerType_t;
static const char * s_VerTypes[PRS_VER_UNKNOWN+1] = {
NULL, // 0: unused
"input", // 1: input
"output", // 2: output
"inout", // 3: inout
"wire", // 4: wire
"module", // 5: module
"assign", // 6: assign
"reg", // 7: reg
"always", // 8: always
"defparam", // 9: defparam
"begin", // 10: begin
"end", // 11: end
"endmodule", // 12: endmodule
NULL // 13: unknown
};
static inline void Psr_NtkAddVerilogDirectives( Psr_Man_t * p )
{
int i;
for ( i = 1; s_VerTypes[i]; i++ )
Abc_NamStrFindOrAdd( p->pStrs, (char *)s_VerTypes[i], NULL );
assert( Abc_NamObjNumMax(p->pStrs) == i );
}
// character recognition
static inline int Psr_CharIsSpace( char c ) { return (c == ' ' || c == '\t' || c == '\r' || c == '\n'); }
static inline int Psr_CharIsDigit( char c ) { return (c >= '0' && c <= '9'); }
static inline int Psr_CharIsDigitB( char c ) { return (c == '0' || c == '1' || c == 'x' || c == 'z'); }
static inline int Psr_CharIsDigitH( char c ) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); }
static inline int Psr_CharIsChar( char c ) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
static inline int Psr_CharIsSymb1( char c ) { return Psr_CharIsChar(c) || c == '_'; }
static inline int Psr_CharIsSymb2( char c ) { return Psr_CharIsSymb1(c) || Psr_CharIsDigit(c) || c == '$'; }
static inline int Psr_ManIsChar( Psr_Man_t * p, char c ) { return p->pCur[0] == c; }
static inline int Psr_ManIsChar1( Psr_Man_t * p, char c ) { return p->pCur[1] == c; }
static inline int Psr_ManIsDigit( Psr_Man_t * p ) { return Psr_CharIsDigit(*p->pCur); }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
// collect predefined modules names
static const char * s_VerilogModules[100] =
{
"const0", // BAC_BOX_CF,
"const1", // BAC_BOX_CT,
"constX", // BAC_BOX_CX,
"constZ", // BAC_BOX_CZ,
"buf", // BAC_BOX_BUF,
"not", // BAC_BOX_INV,
"and", // BAC_BOX_AND,
"nand", // BAC_BOX_NAND,
"or", // BAC_BOX_OR,
"nor", // BAC_BOX_NOR,
"xor", // BAC_BOX_XOR,
"xnor", // BAC_BOX_XNOR,
"sharp", // BAC_BOX_SHARP,
"mux", // BAC_BOX_MUX,
"maj", // BAC_BOX_MAJ,
NULL
};
static const char * s_KnownModules[100] =
{
"VERIFIC_",
"add_",
"mult_",
"div_",
"mod_",
"rem_",
"shift_left_",
"shift_right_",
"rotate_left_",
"rotate_right_",
"reduce_and_",
"reduce_or_",
"reduce_xor_",
"reduce_nand_",
"reduce_nor_",
"reduce_xnor_",
"LessThan_",
"Mux_",
"Select_",
"Decoder_",
"EnabledDecoder_",
"PrioSelect_",
"DualPortRam_",
"ReadPort_",
"WritePort_",
"ClockedWritePort_",
"lut",
"and_",
"or_",
"xor_",
"nand_",
"nor_",
"xnor_",
"buf_",
"inv_",
"tri_",
"sub_",
"unary_minus_",
"equal_",
"not_equal_",
"mux_",
"wide_mux_",
"wide_select_",
"wide_dff_",
"wide_dlatch_",
"wide_dffrs_",
"wide_dlatchrs_",
"wide_prio_select_",
"pow_",
"PrioEncoder_",
"abs",
NULL
};
// check if it is a Verilog predefined module
static inline int Psr_ManIsVerilogModule( Psr_Man_t * p, char * pName )
{
int i;
for ( i = 0; s_VerilogModules[i]; i++ )
if ( !strcmp(pName, s_VerilogModules[i]) )
return BAC_BOX_CF + i;
return 0;
}
// check if it is a known module
static inline int Psr_ManIsKnownModule( Psr_Man_t * p, char * pName )
{
int i;
for ( i = 0; s_KnownModules[i]; i++ )
if ( !strncmp(pName, s_KnownModules[i], strlen(s_KnownModules[i])) )
return i;
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
// skips Verilog comments (returns 1 if some comments were skipped)
static inline int Psr_ManUtilSkipComments( Psr_Man_t * p )
{
if ( !Psr_ManIsChar(p, '/') )
return 0;
if ( Psr_ManIsChar1(p, '/') )
{
for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ )
if ( Psr_ManIsChar(p, '\n') )
{ p->pCur++; return 1; }
}
else if ( Psr_ManIsChar1(p, '*') )
{
for ( p->pCur += 2; p->pCur < p->pLimit; p->pCur++ )
if ( Psr_ManIsChar(p, '*') && Psr_ManIsChar1(p, '/') )
{ p->pCur++; p->pCur++; return 1; }
}
return 0;
}
static inline int Psr_ManUtilSkipName( Psr_Man_t * p )
{
if ( !Psr_ManIsChar(p, '\\') )
return 0;
for ( p->pCur++; p->pCur < p->pLimit; p->pCur++ )
if ( Psr_ManIsChar(p, ' ') )
{ p->pCur++; return 1; }
return 0;
}
// skip any number of spaces and comments
static inline int Psr_ManUtilSkipSpaces( Psr_Man_t * p )
{
while ( p->pCur < p->pLimit )
{
while ( Psr_CharIsSpace(*p->pCur) )
p->pCur++;
if ( !*p->pCur )
return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1);
if ( !Psr_ManUtilSkipComments(p) )
return 0;
}
return Psr_ManErrorSet(p, "Unexpectedly reached end-of-file.", 1);
}
// skip everything including comments until the given char
static inline int Psr_ManUtilSkipUntil( Psr_Man_t * p, char c )
{
while ( p->pCur < p->pLimit )
{
if ( Psr_ManIsChar(p, c) )
return 1;
if ( Psr_ManUtilSkipComments(p) )
continue;
if ( Psr_ManUtilSkipName(p) )
continue;
p->pCur++;
}
return 0;
}
// skip everything including comments until the given word
static inline int Psr_ManUtilSkipUntilWord( Psr_Man_t * p, char * pWord )
{
char * pPlace = strstr( p->pCur, pWord );
if ( pPlace == NULL ) return 1;
p->pCur = pPlace + strlen(pWord);
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Psr_ManReadName( Psr_Man_t * p )
{
char * pStart = p->pCur;
if ( Psr_ManIsChar(p, '\\') ) // escaped name
{
pStart = ++p->pCur;
while ( !Psr_ManIsChar(p, ' ') )
p->pCur++;
}
else if ( Psr_CharIsSymb1(*p->pCur) ) // simple name
{
p->pCur++;
while ( Psr_CharIsSymb2(*p->pCur) )
p->pCur++;
}
else
return 0;
return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
}
static inline int Psr_ManReadNameList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb )
{
Vec_IntClear( vTemp );
while ( 1 )
{
int Item = Psr_ManReadName(p);
if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read name in the list.", 0);
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 1.", 0);
if ( Item == PRS_VER_WIRE )
continue;
Vec_IntPush( vTemp, Item );
if ( Psr_ManIsChar(p, LastSymb) ) break;
if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0);
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 2.", 0);
}
return 1;
}
static inline int Psr_ManReadConstant( Psr_Man_t * p )
{
char * pStart = p->pCur;
assert( Psr_ManIsDigit(p) );
while ( Psr_ManIsDigit(p) )
p->pCur++;
if ( !Psr_ManIsChar(p, '\'') ) return Psr_ManErrorSet(p, "Cannot read constant.", 0);
p->pCur++;
if ( Psr_ManIsChar(p, 'b') )
{
p->pCur++;
while ( Psr_CharIsDigitB(*p->pCur) )
{
if ( *p->pCur == '0' )
p->pNtk->fHasC0s = 1;
else if ( *p->pCur == '1' )
p->pNtk->fHasC1s = 1;
else if ( *p->pCur == 'x' )
p->pNtk->fHasCXs = 1;
else if ( *p->pCur == 'z' )
p->pNtk->fHasCZs = 1;
p->pCur++;
}
}
else if ( Psr_ManIsChar(p, 'h') )
{
p->pCur++;
p->pNtk->fHasC0s = 1;
while ( Psr_CharIsDigitH(*p->pCur) )
{
if ( *p->pCur != '0' )
p->pNtk->fHasC1s = 1;
p->pCur++;
}
}
else if ( Psr_ManIsChar(p, 'd') )
{
p->pCur++;
p->pNtk->fHasC0s = 1;
while ( Psr_ManIsDigit(p) )
{
if ( *p->pCur != '0' )
p->pNtk->fHasC1s = 1;
p->pCur++;
}
}
else return Psr_ManErrorSet(p, "Cannot read radix of constant.", 0);
return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
}
static inline int Psr_ManReadRange( Psr_Man_t * p )
{
assert( Psr_ManIsChar(p, '[') );
Vec_StrClear( &p->vCover );
Vec_StrPush( &p->vCover, *p->pCur++ );
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 3.", 0);
if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0);
while ( Psr_ManIsDigit(p) )
Vec_StrPush( &p->vCover, *p->pCur++ );
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 4.", 0);
if ( Psr_ManIsChar(p, ':') )
{
Vec_StrPush( &p->vCover, *p->pCur++ );
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 5.", 0);
if ( !Psr_ManIsDigit(p) ) return Psr_ManErrorSet(p, "Cannot read digit in range specification.", 0);
while ( Psr_ManIsDigit(p) )
Vec_StrPush( &p->vCover, *p->pCur++ );
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 6.", 0);
}
if ( !Psr_ManIsChar(p, ']') ) return Psr_ManErrorSet(p, "Cannot read closing brace in range specification.", 0);
Vec_StrPush( &p->vCover, *p->pCur++ );
Vec_StrPush( &p->vCover, '\0' );
return Abc_NamStrFindOrAdd( p->pStrs, Vec_StrArray(&p->vCover), NULL );
}
static inline int Psr_ManReadConcat( Psr_Man_t * p, Vec_Int_t * vTemp2 )
{
extern int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm );
assert( Psr_ManIsChar(p, '{') );
p->pCur++;
if ( !Psr_ManReadSignalList( p, vTemp2, '}', 0 ) ) return Psr_ManErrorSet(p, "Error number 7.", 0);
// check final
assert( Psr_ManIsChar(p, '}') );
p->pCur++;
// return special case
assert( Vec_IntSize(vTemp2) > 0 );
if ( Vec_IntSize(vTemp2) == 1 )
return Vec_IntEntry(vTemp2, 0);
return Abc_Var2Lit2( Psr_NtkAddConcat(p->pNtk, vTemp2), BAC_PRS_CONCAT );
}
static inline int Psr_ManReadSignal( Psr_Man_t * p )
{
int Item;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 8.", 0);
if ( Psr_ManIsDigit(p) )
{
Item = Psr_ManReadConstant(p);
if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 9.", 0);
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 10.", 0);
return Abc_Var2Lit2( Item, BAC_PRS_CONST );
}
if ( Psr_ManIsChar(p, '{') )
{
if ( p->fUsingTemp2 ) return Psr_ManErrorSet(p, "Cannot read nested concatenations.", 0);
p->fUsingTemp2 = 1;
Item = Psr_ManReadConcat(p, &p->vTemp2);
p->fUsingTemp2 = 0;
if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 11.", 0);
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 12.", 0);
return Item;
}
else
{
Item = Psr_ManReadName( p );
if ( Item == 0 ) return Psr_ManErrorSet(p, "Error number 13.", 0); // was return 1;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 14.", 0);
if ( Psr_ManIsChar(p, '[') )
{
int Range = Psr_ManReadRange(p);
if ( Range == 0 ) return Psr_ManErrorSet(p, "Error number 15.", 0);
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 16.", 0);
return Abc_Var2Lit2( Psr_NtkAddSlice(p->pNtk, Item, Range), BAC_PRS_SLICE );
}
return Abc_Var2Lit2( Item, BAC_PRS_NAME );
}
}
int Psr_ManReadSignalList( Psr_Man_t * p, Vec_Int_t * vTemp, char LastSymb, int fAddForm )
{
Vec_IntClear( vTemp );
while ( 1 )
{
int Item = Psr_ManReadSignal(p);
if ( Item == 0 ) return Psr_ManErrorSet(p, "Cannot read signal in the list.", 0);
if ( fAddForm )
Vec_IntPush( vTemp, 0 );
Vec_IntPush( vTemp, Item );
if ( Psr_ManIsChar(p, LastSymb) ) break;
if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the list.", 0);
p->pCur++;
}
return 1;
}
static inline int Psr_ManReadSignalList2( Psr_Man_t * p, Vec_Int_t * vTemp )
{
int FormId, ActItem;
Vec_IntClear( vTemp );
assert( Psr_ManIsChar(p, '.') );
while ( Psr_ManIsChar(p, '.') )
{
p->pCur++;
FormId = Psr_ManReadName( p );
if ( FormId == 0 ) return Psr_ManErrorSet(p, "Cannot read formal name of the instance.", 0);
if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot read \"(\" in the instance.", 0);
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 17.", 0);
ActItem = Psr_ManReadSignal( p );
if ( ActItem == 0 ) return Psr_ManErrorSet(p, "Cannot read actual name of the instance.", 0);
if ( !Psr_ManIsChar(p, ')') ) return Psr_ManErrorSet(p, "Cannot read \")\" in the instance.", 0);
p->pCur++;
Vec_IntPushTwo( vTemp, FormId, ActItem );
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 18.", 0);
if ( Psr_ManIsChar(p, ')') ) break;
if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0);
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 19.", 0);
}
assert( Vec_IntSize(vTemp) > 0 );
assert( Vec_IntSize(vTemp) % 2 == 0 );
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Psr_ManReadDeclaration( Psr_Man_t * p, int Type )
{
int i, NameId, RangeId = 0;
Vec_Int_t * vNames[4] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts, &p->pNtk->vWires };
Vec_Int_t * vNamesR[4] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR, &p->pNtk->vWiresR };
assert( Type >= PRS_VER_INPUT && Type <= PRS_VER_WIRE );
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 20.", 0);
if ( Psr_ManIsChar(p, '[') && !(RangeId = Psr_ManReadRange(p)) ) return Psr_ManErrorSet(p, "Error number 21.", 0);
if ( !Psr_ManReadNameList( p, &p->vTemp, ';' ) ) return Psr_ManErrorSet(p, "Error number 22.", 0);
Vec_IntForEachEntry( &p->vTemp, NameId, i )
{
Vec_IntPush( vNames[Type - PRS_VER_INPUT], NameId );
Vec_IntPush( vNamesR[Type - PRS_VER_INPUT], RangeId );
if ( Type < PRS_VER_WIRE )
Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(NameId, Type) );
}
return 1;
}
static inline int Psr_ManReadAssign( Psr_Man_t * p )
{
int OutItem, InItem, fCompl = 0, fCompl2 = 0, Oper = 0;
// read output name
OutItem = Psr_ManReadSignal( p );
if ( OutItem == 0 ) return Psr_ManErrorSet(p, "Cannot read output in assign-statement.", 0);
if ( !Psr_ManIsChar(p, '=') ) return Psr_ManErrorSet(p, "Expecting \"=\" in assign-statement.", 0);
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 23.", 0);
if ( Psr_ManIsChar(p, '~') )
{
fCompl = 1;
p->pCur++;
}
// read first name
InItem = Psr_ManReadSignal( p );
if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read first input name in the assign-statement.", 0);
Vec_IntClear( &p->vTemp );
Vec_IntPush( &p->vTemp, 0 );
Vec_IntPush( &p->vTemp, InItem );
// check unary operator
if ( Psr_ManIsChar(p, ';') )
{
Vec_IntPush( &p->vTemp, 0 );
Vec_IntPush( &p->vTemp, OutItem );
Oper = fCompl ? BAC_BOX_INV : BAC_BOX_BUF;
Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp );
return 1;
}
if ( Psr_ManIsChar(p, '&') )
Oper = BAC_BOX_AND;
else if ( Psr_ManIsChar(p, '|') )
Oper = BAC_BOX_OR;
else if ( Psr_ManIsChar(p, '^') )
Oper = BAC_BOX_XOR;
else if ( Psr_ManIsChar(p, '?') )
Oper = BAC_BOX_MUX;
else return Psr_ManErrorSet(p, "Unrecognized operator in the assign-statement.", 0);
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 24.", 0);
if ( Psr_ManIsChar(p, '~') )
{
fCompl2 = 1;
p->pCur++;
}
// read second name
InItem = Psr_ManReadSignal( p );
if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read second input name in the assign-statement.", 0);
Vec_IntPush( &p->vTemp, 0 );
Vec_IntPush( &p->vTemp, InItem );
// read third argument
if ( Oper == BAC_BOX_MUX )
{
assert( fCompl == 0 );
if ( !Psr_ManIsChar(p, ':') ) return Psr_ManErrorSet(p, "Expected colon in the MUX assignment.", 0);
p->pCur++;
// read third name
InItem = Psr_ManReadSignal( p );
if ( InItem == 0 ) return Psr_ManErrorSet(p, "Cannot read third input name in the assign-statement.", 0);
Vec_IntPush( &p->vTemp, 0 );
Vec_IntPush( &p->vTemp, InItem );
if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expected semicolon at the end of the assign-statement.", 0);
}
else
{
// figure out operator
if ( Oper == BAC_BOX_AND )
{
if ( fCompl && !fCompl2 )
Oper = BAC_BOX_SHARPL;
else if ( !fCompl && fCompl2 )
Oper = BAC_BOX_SHARP;
else if ( fCompl && fCompl2 )
Oper = BAC_BOX_NOR;
}
else if ( Oper == BAC_BOX_OR )
{
if ( fCompl && fCompl2 )
Oper = BAC_BOX_NAND;
else assert( !fCompl && !fCompl2 );
}
else if ( Oper == BAC_BOX_XOR )
{
if ( fCompl && !fCompl2 )
Oper = BAC_BOX_XNOR;
else assert( !fCompl && !fCompl2 );
}
}
// write binary operator
Vec_IntPush( &p->vTemp, 0 );
Vec_IntPush( &p->vTemp, OutItem );
Psr_NtkAddBox( p->pNtk, Oper, 0, &p->vTemp );
return 1;
}
static inline int Psr_ManReadInstance( Psr_Man_t * p, int Func )
{
int InstId, Status;
/*
static Counter = 0;
if ( ++Counter == 7 )
{
int s=0;
}
*/
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 25.", 0);
if ( (InstId = Psr_ManReadName(p)) )
if (Psr_ManUtilSkipSpaces(p)) return Psr_ManErrorSet(p, "Error number 26.", 0);
if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Expecting \"(\" in module instantiation.", 0);
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 27.", 0);
if ( Psr_ManIsChar(p, '.') ) // box
Status = Psr_ManReadSignalList2(p, &p->vTemp);
else // node
{
//char * s = Abc_NamStr(p->pStrs, Func);
// translate elementary gate
int iFuncNew = Psr_ManIsVerilogModule(p, Abc_NamStr(p->pStrs, Func));
if ( iFuncNew == 0 ) return Psr_ManErrorSet(p, "Cannot find elementary gate.", 0);
Func = iFuncNew;
Status = Psr_ManReadSignalList( p, &p->vTemp, ')', 1 );
}
if ( Status == 0 ) return Psr_ManErrorSet(p, "Error number 28.", 0);
assert( Psr_ManIsChar(p, ')') );
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 29.", 0);
if ( !Psr_ManIsChar(p, ';') ) return Psr_ManErrorSet(p, "Expecting semicolon in the instance.", 0);
// add box
Psr_NtkAddBox( p->pNtk, Func, InstId, &p->vTemp );
return 1;
}
static inline int Psr_ManReadArguments( Psr_Man_t * p )
{
int iRange = 0, iType = -1;
Vec_Int_t * vSigs[3] = { &p->pNtk->vInputs, &p->pNtk->vOutputs, &p->pNtk->vInouts };
Vec_Int_t * vSigsR[3] = { &p->pNtk->vInputsR, &p->pNtk->vOutputsR, &p->pNtk->vInoutsR };
assert( Psr_ManIsChar(p, '(') );
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 30.", 0);
while ( 1 )
{
int iName = Psr_ManReadName( p );
if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 31.", 0);
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 32.", 0);
if ( iName >= PRS_VER_INPUT && iName <= PRS_VER_INOUT ) // declaration
{
iType = iName;
if ( Psr_ManIsChar(p, '[') )
{
iRange = Psr_ManReadRange(p);
if ( iRange == 0 ) return Psr_ManErrorSet(p, "Error number 33.", 0);
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 34.", 0);
}
iName = Psr_ManReadName( p );
if ( iName == 0 ) return Psr_ManErrorSet(p, "Error number 35.", 0);
}
if ( iType > 0 )
{
Vec_IntPush( vSigs[iType - PRS_VER_INPUT], iName );
Vec_IntPush( vSigsR[iType - PRS_VER_INPUT], iRange );
Vec_IntPush( &p->pNtk->vOrder, Abc_Var2Lit2(iName, iType) );
}
if ( Psr_ManIsChar(p, ')') )
break;
if ( !Psr_ManIsChar(p, ',') ) return Psr_ManErrorSet(p, "Expecting comma in the instance.", 0);
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return Psr_ManErrorSet(p, "Error number 36.", 0);
}
// check final
assert( Psr_ManIsChar(p, ')') );
return 1;
}
// this procedure can return:
// 0 = reached end-of-file; 1 = successfully parsed; 2 = recognized as primitive; 3 = failed and skipped; 4 = error (failed and could not skip)
static inline int Psr_ManReadModule( Psr_Man_t * p )
{
int iToken, Status;
if ( p->pNtk != NULL ) return Psr_ManErrorSet(p, "Parsing previous module is unfinished.", 4);
if ( Psr_ManUtilSkipSpaces(p) )
{
Psr_ManErrorClear( p );
return 0;
}
// read keyword
iToken = Psr_ManReadName( p );
if ( iToken != PRS_VER_MODULE ) return Psr_ManErrorSet(p, "Cannot read \"module\" keyword.", 4);
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
// read module name
iToken = Psr_ManReadName( p );
if ( iToken == 0 ) return Psr_ManErrorSet(p, "Cannot read module name.", 4);
if ( Psr_ManIsKnownModule(p, Abc_NamStr(p->pStrs, iToken)) )
{
if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4);
//printf( "Warning! Skipped known module \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
Vec_IntPush( &p->vKnown, iToken );
return 2;
}
Psr_ManInitializeNtk( p, iToken, 1 );
// skip arguments
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
if ( !Psr_ManIsChar(p, '(') ) return Psr_ManErrorSet(p, "Cannot find \"(\" in the argument declaration.", 4);
if ( !Psr_ManReadArguments(p) ) return 4;
assert( *p->pCur == ')' );
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
// read declarations and instances
while ( Psr_ManIsChar(p, ';') )
{
p->pCur++;
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
iToken = Psr_ManReadName( p );
if ( iToken == PRS_VER_ENDMODULE )
{
Vec_IntPush( &p->vSucceeded, p->pNtk->iModuleName );
Psr_ManFinalizeNtk( p );
return 1;
}
if ( iToken >= PRS_VER_INPUT && iToken <= PRS_VER_WIRE ) // declaration
Status = Psr_ManReadDeclaration( p, iToken );
else if ( iToken == PRS_VER_REG || iToken == PRS_VER_DEFPARAM ) // unsupported keywords
Status = Psr_ManUtilSkipUntil( p, ';' );
else // read instance
{
if ( iToken == PRS_VER_ASSIGN )
Status = Psr_ManReadAssign( p );
else
Status = Psr_ManReadInstance( p, iToken );
if ( Status == 0 )
{
if ( Psr_ManUtilSkipUntilWord( p, "endmodule" ) ) return Psr_ManErrorSet(p, "Cannot find \"endmodule\" keyword.", 4);
//printf( "Warning! Failed to parse \"%s\". Adding module \"%s\" as blackbox.\n",
// Abc_NamStr(p->pStrs, iToken), Abc_NamStr(p->pStrs, p->pNtk->iModuleName) );
Vec_IntPush( &p->vFailed, p->pNtk->iModuleName );
// cleanup
Vec_IntErase( &p->pNtk->vWires );
Vec_IntErase( &p->pNtk->vWiresR );
Vec_IntErase( &p->pNtk->vSlices );
Vec_IntErase( &p->pNtk->vConcats );
Vec_IntErase( &p->pNtk->vBoxes );
Vec_IntErase( &p->pNtk->vObjs );
p->fUsingTemp2 = 0;
// add
Psr_ManFinalizeNtk( p );
Psr_ManErrorClear( p );
return 3;
}
}
if ( !Status ) return 4;
if ( Psr_ManUtilSkipSpaces(p) ) return 4;
}
return Psr_ManErrorSet(p, "Cannot find \";\" in the module definition.", 4);
}
static inline int Psr_ManReadDesign( Psr_Man_t * p )
{
while ( 1 )
{
int RetValue = Psr_ManReadModule( p );
if ( RetValue == 0 ) // end of file
break;
if ( RetValue == 1 ) // successfully parsed
continue;
if ( RetValue == 2 ) // recognized as primitive
continue;
if ( RetValue == 3 ) // failed and skipped
continue;
if ( RetValue == 4 ) // error
return 0;
assert( 0 );
}
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Psr_ManPrintModules( Psr_Man_t * p )
{
char * pName; int i;
printf( "Succeeded parsing %d models:\n", Vec_IntSize(&p->vSucceeded) );
Psr_ManForEachNameVec( &p->vSucceeded, p, pName, i )
printf( " %s", pName );
printf( "\n" );
printf( "Skipped %d known models:\n", Vec_IntSize(&p->vKnown) );
Psr_ManForEachNameVec( &p->vKnown, p, pName, i )
printf( " %s", pName );
printf( "\n" );
printf( "Skipped %d failed models:\n", Vec_IntSize(&p->vFailed) );
Psr_ManForEachNameVec( &p->vFailed, p, pName, i )
printf( " %s", pName );
printf( "\n" );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Psr_ManReadVerilog( char * pFileName )
{
Vec_Ptr_t * vPrs = NULL;
Psr_Man_t * p = Psr_ManAlloc( pFileName );
if ( p == NULL )
return NULL;
Psr_NtkAddVerilogDirectives( p );
Psr_ManReadDesign( p );
//Psr_ManPrintModules( p );
if ( Psr_ManErrorPrint(p) )
ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
Psr_ManFree( p );
return vPrs;
}
void Psr_ManReadVerilogTest( char * pFileName )
{
abctime clk = Abc_Clock();
extern void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * p );
Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "c/hie/dump/1/netlist_1.v" );
// Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/me/me_wide.v" );
// Vec_Ptr_t * vPrs = Psr_ManReadVerilog( "aga/ray/ray_wide.v" );
if ( !vPrs ) return;
printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
printf( "NameIDs = %d. ", Abc_NamObjNumMax(Psr_ManNameMan(vPrs)) );
printf( "Memory = %.2f MB. ", 1.0*Psr_ManMemory(vPrs)/(1<<20) );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
Psr_ManWriteVerilog( "c/hie/dump/1/netlist_1_out_new.v", vPrs );
// Psr_ManWriteVerilog( "aga/me/me_wide_out.v", vPrs );
// Psr_ManWriteVerilog( "aga/ray/ray_wide_out.v", vPrs );
// Abc_NamPrint( p->pStrs );
Psr_ManVecFree( vPrs );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

236
src/base/bac/bacWriteBlif.c Normal file
View File

@ -0,0 +1,236 @@
/**CFile****************************************************************
FileName [bacWriteBlif.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Verilog parser.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacWriteBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "bacPrs.h"
#include "map/mio/mio.h"
#include "base/main/main.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Writing parser state into a file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static void Psr_ManWriteBlifArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vFanins )
{
int i, NameId;
Vec_IntForEachEntry( vFanins, NameId, i )
fprintf( pFile, " %s", Psr_NtkStr(p, NameId) );
fprintf( pFile, "\n" );
}
static void Psr_ManWriteBlifLines( FILE * pFile, Psr_Ntk_t * p )
{
Vec_Int_t * vBox;
int i, k, FormId, ActId;
Psr_NtkForEachBox( p, vBox, i )
{
int NtkId = Psr_BoxNtk(p, i);
assert( Psr_BoxIONum(p, i) > 0 );
assert( Vec_IntSize(vBox) % 2 == 0 );
if ( NtkId == -1 ) // latch
{
fprintf( pFile, ".latch" );
fprintf( pFile, " %s", Psr_NtkStr(p, Vec_IntEntry(vBox, 1)) );
fprintf( pFile, " %s", Psr_NtkStr(p, Vec_IntEntry(vBox, 3)) );
fprintf( pFile, " %c\n", '0' + Psr_BoxName(p, i) );
}
else if ( Psr_BoxIsNode(p, i) ) // node
{
fprintf( pFile, ".names" );
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
fprintf( pFile, " %s", Psr_NtkStr(p, ActId) );
fprintf( pFile, "\n%s", Psr_NtkStr(p, NtkId) );
}
else // box
{
fprintf( pFile, ".subckt" );
fprintf( pFile, " %s", Psr_NtkStr(p, NtkId) );
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
fprintf( pFile, " %s=%s", Psr_NtkStr(p, FormId), Psr_NtkStr(p, ActId) );
fprintf( pFile, "\n" );
}
}
}
static void Psr_ManWriteBlifNtk( FILE * pFile, Psr_Ntk_t * p )
{
// write header
fprintf( pFile, ".model %s\n", Psr_NtkStr(p, p->iModuleName) );
if ( Vec_IntSize(&p->vInouts) )
fprintf( pFile, ".inouts" );
if ( Vec_IntSize(&p->vInouts) )
Psr_ManWriteBlifArray( pFile, p, &p->vInouts );
fprintf( pFile, ".inputs" );
Psr_ManWriteBlifArray( pFile, p, &p->vInputs );
fprintf( pFile, ".outputs" );
Psr_ManWriteBlifArray( pFile, p, &p->vOutputs );
// write objects
Psr_ManWriteBlifLines( pFile, p );
fprintf( pFile, ".end\n\n" );
}
void Psr_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs )
{
Psr_Ntk_t * pNtk = Psr_ManRoot(vPrs);
FILE * pFile = fopen( pFileName, "wb" ); int i;
if ( pFile == NULL )
{
printf( "Cannot open output file \"%s\".\n", pFileName );
return;
}
fprintf( pFile, "# Design \"%s\" written by ABC on %s\n\n", Psr_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() );
Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i )
Psr_ManWriteBlifNtk( pFile, pNtk );
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Write elaborated design.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Bac_ManWriteBlifGate( FILE * pFile, Bac_Ntk_t * p, Mio_Gate_t * pGate, Vec_Int_t * vFanins, int iObj )
{
int iFanin, i;
Vec_IntForEachEntry( vFanins, iFanin, i )
fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, i), Bac_ObjNameStr(p, iFanin) );
fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Bac_ObjNameStr(p, iObj) );
fprintf( pFile, "\n" );
}
void Bac_ManWriteBlifArray( FILE * pFile, Bac_Ntk_t * p, Vec_Int_t * vFanins, int iObj )
{
int iFanin, i;
Vec_IntForEachEntry( vFanins, iFanin, i )
fprintf( pFile, " %s", Bac_ObjNameStr(p, iFanin) );
if ( iObj >= 0 )
fprintf( pFile, " %s", Bac_ObjNameStr(p, iObj) );
fprintf( pFile, "\n" );
}
void Bac_ManWriteBlifArray2( FILE * pFile, Bac_Ntk_t * p, int iObj )
{
int iTerm, i;
Bac_Ntk_t * pModel = Bac_BoxNtk( p, iObj );
Bac_NtkForEachPi( pModel, iTerm, i )
fprintf( pFile, " %s=%s", Bac_ObjNameStr(pModel, iTerm), Bac_ObjNameStr(p, Bac_BoxBi(p, iObj, i)) );
Bac_NtkForEachPo( pModel, iTerm, i )
fprintf( pFile, " %s=%s", Bac_ObjNameStr(pModel, iTerm), Bac_ObjNameStr(p, Bac_BoxBo(p, iObj, i)) );
fprintf( pFile, "\n" );
}
void Bac_ManWriteBlifLines( FILE * pFile, Bac_Ntk_t * p )
{
int i, k, iTerm;
Bac_NtkForEachBox( p, i )
{
if ( Bac_ObjIsBoxUser(p, i) )
{
fprintf( pFile, ".subckt" );
fprintf( pFile, " %s", Bac_NtkName(Bac_BoxNtk(p, i)) );
Bac_ManWriteBlifArray2( pFile, p, i );
}
else if ( Bac_ObjIsGate(p, i) )
{
char * pGateName = Abc_NamStr(p->pDesign->pMods, Bac_BoxNtkId(p, i));
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL );
fprintf( pFile, ".gate %s", pGateName );
Bac_BoxForEachBi( p, i, iTerm, k )
fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, k), Bac_ObjNameStr(p, iTerm) );
Bac_BoxForEachBo( p, i, iTerm, k )
fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Bac_ObjNameStr(p, iTerm) );
fprintf( pFile, "\n" );
}
else
{
fprintf( pFile, ".names" );
Bac_BoxForEachBi( p, i, iTerm, k )
fprintf( pFile, " %s", Bac_ObjNameStr(p, Bac_ObjFanin(p, iTerm)) );
Bac_BoxForEachBo( p, i, iTerm, k )
fprintf( pFile, " %s", Bac_ObjNameStr(p, iTerm) );
fprintf( pFile, "\n%s", Ptr_TypeToSop(Bac_ObjType(p, i)) );
}
}
}
void Bac_ManWriteBlifNtk( FILE * pFile, Bac_Ntk_t * p )
{
assert( Vec_IntSize(&p->vFanin) == Bac_NtkObjNum(p) );
// write header
fprintf( pFile, ".model %s\n", Bac_NtkName(p) );
fprintf( pFile, ".inputs" );
Bac_ManWriteBlifArray( pFile, p, &p->vInputs, -1 );
fprintf( pFile, ".outputs" );
Bac_ManWriteBlifArray( pFile, p, &p->vOutputs, -1 );
// write objects
Bac_ManWriteBlifLines( pFile, p );
fprintf( pFile, ".end\n\n" );
}
void Bac_ManWriteBlif( char * pFileName, Bac_Man_t * p )
{
FILE * pFile;
Bac_Ntk_t * pNtk;
int i;
// check the library
if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() )
{
printf( "Genlib library used in the mapped design is not longer a current library.\n" );
return;
}
pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open output file \"%s\".\n", pFileName );
return;
}
fprintf( pFile, "# Design \"%s\" written via CBA package in ABC on %s\n\n", Bac_ManName(p), Extra_TimeStamp() );
Bac_ManAssignInternWordNames( p );
Bac_ManForEachNtk( p, pNtk, i )
Bac_ManWriteBlifNtk( pFile, pNtk );
fclose( pFile );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

View File

@ -0,0 +1,52 @@
/**CFile****************************************************************
FileName [bacWriteSmt.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Verilog parser.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacWriteSmt.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

703
src/base/bac/bacWriteVer.c Normal file
View File

@ -0,0 +1,703 @@
/**CFile****************************************************************
FileName [bacWriteVer.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Verilog writer.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: bacWriteVer.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "bac.h"
#include "bacPrs.h"
#include "map/mio/mio.h"
#include "base/main/main.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Writing parser state into a file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static void Psr_ManWriteVerilogConcat( FILE * pFile, Psr_Ntk_t * p, int Con )
{
extern void Psr_ManWriteVerilogArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs, int Start, int Stop, int fOdd );
Vec_Int_t * vSigs = Psr_CatSignals(p, Con);
fprintf( pFile, "{" );
Psr_ManWriteVerilogArray( pFile, p, vSigs, 0, Vec_IntSize(vSigs), 0 );
fprintf( pFile, "}" );
}
static void Psr_ManWriteVerilogSignal( FILE * pFile, Psr_Ntk_t * p, int Sig )
{
int Value = Abc_Lit2Var2( Sig );
Psr_ManType_t Type = (Psr_ManType_t)Abc_Lit2Att2( Sig );
if ( Type == BAC_PRS_NAME || Type == BAC_PRS_CONST )
fprintf( pFile, "%s", Psr_NtkStr(p, Value) );
else if ( Type == BAC_PRS_SLICE )
fprintf( pFile, "%s%s", Psr_NtkStr(p, Psr_SliceName(p, Value)), Psr_NtkStr(p, Psr_SliceRange(p, Value)) );
else if ( Type == BAC_PRS_CONCAT )
Psr_ManWriteVerilogConcat( pFile, p, Value );
else assert( 0 );
}
void Psr_ManWriteVerilogArray( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs, int Start, int Stop, int fOdd )
{
int i, Sig;
assert( Vec_IntSize(vSigs) > 0 );
Vec_IntForEachEntryStartStop( vSigs, Sig, i, Start, Stop )
{
if ( fOdd && !(i & 1) )
continue;
Psr_ManWriteVerilogSignal( pFile, p, Sig );
fprintf( pFile, "%s", i == Stop - 1 ? "" : ", " );
}
}
static void Psr_ManWriteVerilogArray2( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs )
{
int i, FormId, ActSig;
assert( Vec_IntSize(vSigs) % 2 == 0 );
Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i )
{
fprintf( pFile, "." );
fprintf( pFile, "%s", Psr_NtkStr(p, FormId) );
fprintf( pFile, "(" );
Psr_ManWriteVerilogSignal( pFile, p, ActSig );
fprintf( pFile, ")%s", (i == Vec_IntSize(vSigs) - 2) ? "" : ", " );
}
}
static void Psr_ManWriteVerilogMux( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vSigs )
{
int i, FormId, ActSig;
char * pStrs[4] = { " = ", " ? ", " : ", ";\n" };
assert( Vec_IntSize(vSigs) == 8 );
fprintf( pFile, " assign " );
Psr_ManWriteVerilogSignal( pFile, p, Vec_IntEntryLast(vSigs) );
fprintf( pFile, "%s", pStrs[0] );
Vec_IntForEachEntryDouble( vSigs, FormId, ActSig, i )
{
Psr_ManWriteVerilogSignal( pFile, p, ActSig );
fprintf( pFile, "%s", pStrs[1+i/2] );
if ( i == 4 )
break;
}
}
static void Psr_ManWriteVerilogBoxes( FILE * pFile, Psr_Ntk_t * p )
{
Vec_Int_t * vBox; int i;
Psr_NtkForEachBox( p, vBox, i )
{
Bac_ObjType_t NtkId = (Bac_ObjType_t)Psr_BoxNtk(p, i);
if ( NtkId == BAC_BOX_MUX )
Psr_ManWriteVerilogMux( pFile, p, vBox );
else if ( Psr_BoxIsNode(p, i) ) // node ------- check order of fanins
{
fprintf( pFile, " %s (", Ptr_TypeToName(NtkId) );
Psr_ManWriteVerilogSignal( pFile, p, Vec_IntEntryLast(vBox) );
if ( Psr_BoxIONum(p, i) > 1 )
fprintf( pFile, ", " );
Psr_ManWriteVerilogArray( pFile, p, vBox, 0, Vec_IntSize(vBox)-2, 1 );
fprintf( pFile, ");\n" );
}
else // box
{
//char * s = Psr_NtkStr(p, Vec_IntEntry(vBox, 0));
fprintf( pFile, " %s %s (", Psr_NtkStr(p, NtkId), Psr_BoxName(p, i) ? Psr_NtkStr(p, Psr_BoxName(p, i)) : "" );
Psr_ManWriteVerilogArray2( pFile, p, vBox );
fprintf( pFile, ");\n" );
}
}
}
static void Psr_ManWriteVerilogIos( FILE * pFile, Psr_Ntk_t * p, int SigType )
{
int NameId, RangeId, i;
char * pSigNames[4] = { "inout", "input", "output", "wire" };
Vec_Int_t * vSigs[4] = { &p->vInouts, &p->vInputs, &p->vOutputs, &p->vWires };
Vec_Int_t * vSigsR[4] = { &p->vInoutsR, &p->vInputsR, &p->vOutputsR, &p->vWiresR };
if ( SigType == 3 )
fprintf( pFile, "\n" );
Vec_IntForEachEntryTwo( vSigs[SigType], vSigsR[SigType], NameId, RangeId, i )
fprintf( pFile, " %s %s%s;\n", pSigNames[SigType], RangeId ? Psr_NtkStr(p, RangeId) : "", Psr_NtkStr(p, NameId) );
}
static void Psr_ManWriteVerilogIoOrder( FILE * pFile, Psr_Ntk_t * p, Vec_Int_t * vOrder )
{
int i, NameId;
Vec_IntForEachEntry( vOrder, NameId, i )
fprintf( pFile, "%s%s", Psr_NtkStr(p, NameId), i == Vec_IntSize(vOrder) - 1 ? "" : ", " );
}
static void Psr_ManWriteVerilogNtk( FILE * pFile, Psr_Ntk_t * p )
{
int s;
// write header
fprintf( pFile, "module %s (\n ", Psr_NtkStr(p, p->iModuleName) );
Psr_ManWriteVerilogIoOrder( pFile, p, &p->vOrder );
fprintf( pFile, "\n );\n" );
// write declarations
for ( s = 0; s < 4; s++ )
Psr_ManWriteVerilogIos( pFile, p, s );
fprintf( pFile, "\n" );
// write objects
Psr_ManWriteVerilogBoxes( pFile, p );
fprintf( pFile, "endmodule\n\n" );
}
void Psr_ManWriteVerilog( char * pFileName, Vec_Ptr_t * vPrs )
{
Psr_Ntk_t * pNtk = Psr_ManRoot(vPrs); int i;
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open output file \"%s\".\n", pFileName );
return;
}
fprintf( pFile, "// Design \"%s\" written by ABC on %s\n\n", Psr_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() );
Vec_PtrForEachEntry( Psr_Ntk_t *, vPrs, pNtk, i )
Psr_ManWriteVerilogNtk( pFile, pNtk );
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Writing word-level Verilog.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
// compute range of a name (different from range of a multi-bit wire)
static inline int Bac_ObjGetRange( Bac_Ntk_t * p, int iObj )
{
int i, NameId = Bac_ObjName(p, iObj);
assert( Bac_ObjIsCi(p, iObj) );
// if ( Bac_NameType(NameId) == BAC_NAME_INDEX )
// NameId = Bac_ObjName(p, iObj - Abc_Lit2Var2(NameId));
assert( Bac_NameType(NameId) == BAC_NAME_WORD || Bac_NameType(NameId) == BAC_NAME_INFO );
for ( i = iObj + 1; i < Bac_NtkObjNum(p); i++ )
if ( !Bac_ObjIsCi(p, i) || Bac_ObjNameType(p, i) != BAC_NAME_INDEX )
break;
return i - iObj;
}
static inline void Bac_ManWriteVar( Bac_Ntk_t * p, int RealName )
{
Vec_StrPrintStr( p->pDesign->vOut, Bac_NtkStr(p, RealName) );
}
static inline void Bac_ManWriteRange( Bac_Ntk_t * p, int Beg, int End )
{
Vec_Str_t * vStr = p->pDesign->vOut;
Vec_StrPrintStr( vStr, "[" );
if ( End >= 0 )
{
Vec_StrPrintNum( vStr, End );
Vec_StrPrintStr( vStr, ":" );
}
Vec_StrPrintNum( vStr, Beg );
Vec_StrPrintStr( vStr, "]" );
}
static inline void Bac_ManWriteConstBit( Bac_Ntk_t * p, int iObj, int fHead )
{
Vec_Str_t * vStr = p->pDesign->vOut;
int Const = Bac_ObjGetConst(p, iObj);
assert( Const );
if ( fHead )
Vec_StrPrintStr( vStr, "1\'b" );
if ( Const == BAC_BOX_CF )
Vec_StrPush( vStr, '0' );
else if ( Const == BAC_BOX_CT )
Vec_StrPush( vStr, '1' );
else if ( Const == BAC_BOX_CX )
Vec_StrPush( vStr, 'x' );
else if ( Const == BAC_BOX_CZ )
Vec_StrPush( vStr, 'z' );
else assert( 0 );
}
static inline int Bac_ManFindRealNameId( Bac_Ntk_t * p, int iObj )
{
int NameId = Bac_ObjName(p, iObj);
assert( Bac_ObjIsCi(p, iObj) );
if ( Bac_NameType(NameId) == BAC_NAME_INDEX )
NameId = Bac_ObjName(p, iObj - Abc_Lit2Var2(NameId));
if ( Bac_NameType(NameId) == BAC_NAME_INFO )
return Bac_NtkInfoName(p, Abc_Lit2Var2(NameId));
assert( Bac_NameType(NameId) == BAC_NAME_BIN || Bac_NameType(NameId) == BAC_NAME_WORD );
return Abc_Lit2Var2(NameId);
}
static inline int Bac_ManFindRealIndex( Bac_Ntk_t * p, int iObj )
{
int iBit = 0, NameId = Bac_ObjName(p, iObj);
assert( Bac_ObjIsCi(p, iObj) );
assert( Bac_NameType(NameId) != BAC_NAME_BIN );
if ( Bac_NameType(NameId) == BAC_NAME_INDEX )
NameId = Bac_ObjName(p, iObj - (iBit = Abc_Lit2Var2(NameId)));
if ( Bac_NameType(NameId) == BAC_NAME_INFO )
return Bac_NtkInfoIndex(p, Abc_Lit2Var2(NameId), iBit);
assert( Bac_NameType(NameId) == BAC_NAME_WORD );
return iBit;
}
static inline void Bac_ManWriteSig( Bac_Ntk_t * p, int iObj )
{
if ( Bac_ObjIsCo(p, iObj) )
iObj = Bac_ObjFanin(p, iObj);
assert( Bac_ObjIsCi(p, iObj) );
if ( Bac_ObjGetConst(p, iObj) )
Bac_ManWriteConstBit( p, iObj, 1 );
else
{
int NameId = Bac_ObjName(p, iObj);
if ( Bac_NameType(NameId) == BAC_NAME_BIN )
Bac_ManWriteVar( p, Abc_Lit2Var2(NameId) );
else
{
Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, iObj) );
Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, iObj), -1 );
}
}
}
static inline void Bac_ManWriteConcat( Bac_Ntk_t * p, int iStart, int nObjs )
{
Vec_Str_t * vStr = p->pDesign->vOut;
assert( nObjs >= 1 );
if ( nObjs == 1 )
{
Bac_ManWriteSig( p, iStart );
return;
}
Vec_StrPrintStr( vStr, "{" );
if ( Bac_ObjIsBo(p, iStart) ) // box output
{
int i;
for ( i = iStart + nObjs - 1; i >= iStart; i-- )
{
if ( Bac_ObjNameType(p, i) == BAC_NAME_INDEX )
continue;
if ( Vec_StrEntryLast(vStr) != '{' )
Vec_StrPrintStr( vStr, ", " );
Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, i) );
}
}
else if ( Bac_ObjIsBi(p, iStart) ) // box input
{
int e, b, k, NameId;
for ( e = iStart - nObjs + 1; e <= iStart; )
{
if ( Vec_StrEntryLast(vStr) != '{' )
Vec_StrPrintStr( vStr, ", " );
// write constant
if ( Bac_ObjGetConst(p, Bac_ObjFanin(p, e)) )
{
int fBinary = Bac_ObjIsConstBin(p, Bac_ObjFanin(p, e)-1);
for ( b = e + 1; b <= iStart; b++ )
{
if ( !Bac_ObjGetConst(p, Bac_ObjFanin(p, b)) )
break;
if ( !Bac_ObjIsConstBin(p, Bac_ObjFanin(p, b)-1) )
fBinary = 0;
}
Vec_StrPrintNum( vStr, b - e );
if ( fBinary && b - e > 8 ) // write hex if more than 8 bits
{
int Digit = 0, nBits = ((b - e) & 3) ? (b - e) & 3 : 4;
Vec_StrPrintStr( vStr, "\'h" );
for ( k = e; k < b; k++ )
{
Digit = 2*Digit + Bac_ObjGetConst(p, Bac_ObjFanin(p, k)) - BAC_BOX_CF;
assert( Digit < 16 );
if ( --nBits == 0 )
{
Vec_StrPush( vStr, (char)(Digit < 10 ? '0' + Digit : 'a' + Digit - 10) );
nBits = 4;
Digit = 0;
}
}
assert( nBits == 4 );
assert( Digit == 0 );
}
else
{
Vec_StrPrintStr( vStr, "\'b" );
for ( k = e; k < b; k++ )
Bac_ManWriteConstBit( p, Bac_ObjFanin(p, k), 0 );
}
e = b;
continue;
}
// try replication
for ( b = e + 1; b <= iStart; b++ )
if ( Bac_ObjFanin(p, b) != Bac_ObjFanin(p, e) )
break;
if ( b > e + 2 ) // more than two
{
Vec_StrPrintNum( vStr, b - e );
Vec_StrPrintStr( vStr, "{" );
Bac_ManWriteSig( p, e );
Vec_StrPrintStr( vStr, "}" );
e = b;
continue;
}
NameId = Bac_ObjName(p, Bac_ObjFanin(p, e));
if ( Bac_NameType(NameId) == BAC_NAME_BIN )
{
Bac_ManWriteVar( p, Abc_Lit2Var2(NameId) );
e++;
continue;
}
// find end of the slice
for ( b = e + 1; b <= iStart; b++ )
if ( Bac_ObjFanin(p, e) - Bac_ObjFanin(p, b) != b - e )
break;
// write signal name
Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, Bac_ObjFanin(p, e)) );
if ( b == e + 1 ) // literal
Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, Bac_ObjFanin(p, e)), -1 );
else // slice or complete variable
{
// consider first variable of the slice
int f = Bac_ObjFanin( p, b-1 );
assert( Bac_ObjNameType(p, f) != BAC_NAME_BIN );
if ( Bac_ObjNameType(p, f) == BAC_NAME_INDEX || Bac_ObjGetRange(p, f) != b - e ) // slice
Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, f), Bac_ManFindRealIndex(p, Bac_ObjFanin(p, e)) );
// else this is complete variable
}
e = b;
}
}
else assert( 0 );
Vec_StrPrintStr( vStr, "}" );
}
static inline void Bac_ManWriteGate( Bac_Ntk_t * p, int iObj )
{
Vec_Str_t * vStr = p->pDesign->vOut; int iTerm, k;
char * pGateName = Abc_NamStr(p->pDesign->pMods, Bac_BoxNtkId(p, iObj));
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL );
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, pGateName );
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" );
Vec_StrPrintStr( vStr, " (" );
Bac_BoxForEachBi( p, iObj, iTerm, k )
{
Vec_StrPrintStr( vStr, k ? ", ." : "." );
Vec_StrPrintStr( vStr, Mio_GateReadPinName(pGate, k) );
Vec_StrPrintStr( vStr, "(" );
Bac_ManWriteSig( p, iTerm );
Vec_StrPrintStr( vStr, ")" );
}
Bac_BoxForEachBo( p, iObj, iTerm, k )
{
Vec_StrPrintStr( vStr, Bac_BoxBiNum(p, iObj) ? ", ." : "." );
Vec_StrPrintStr( vStr, Mio_GateReadOutName(pGate) );
Vec_StrPrintStr( vStr, "(" );
Bac_ManWriteSig( p, iTerm );
Vec_StrPrintStr( vStr, ")" );
}
Vec_StrPrintStr( vStr, ");\n" );
}
static inline void Bac_ManWriteAssign( Bac_Ntk_t * p, int iObj )
{
Vec_Str_t * vStr = p->pDesign->vOut;
Bac_ObjType_t Type = Bac_ObjType(p, iObj);
int nInputs = Bac_BoxBiNum(p, iObj);
int nOutputs = Bac_BoxBoNum(p, iObj);
assert( nOutputs == 1 );
Vec_StrPrintStr( vStr, " assign " );
Bac_ManWriteSig( p, iObj + 1 );
Vec_StrPrintStr( vStr, " = " );
if ( nInputs == 0 )
{
if ( Type == BAC_BOX_CF )
Vec_StrPrintStr( vStr, "1\'b0" );
else if ( Type == BAC_BOX_CT )
Vec_StrPrintStr( vStr, "1\'b1" );
else if ( Type == BAC_BOX_CX )
Vec_StrPrintStr( vStr, "1\'bx" );
else if ( Type == BAC_BOX_CZ )
Vec_StrPrintStr( vStr, "1\'bz" );
else assert( 0 );
}
else if ( nInputs == 1 )
{
if ( Type == BAC_BOX_INV )
Vec_StrPrintStr( vStr, "~" );
else assert( Type == BAC_BOX_BUF );
Bac_ManWriteSig( p, iObj - 1 );
}
else if ( nInputs == 2 )
{
if ( Type == BAC_BOX_NAND || Type == BAC_BOX_NOR || Type == BAC_BOX_XNOR || Type == BAC_BOX_SHARPL )
Vec_StrPrintStr( vStr, "~" );
Bac_ManWriteSig( p, iObj - 1 );
if ( Type == BAC_BOX_AND || Type == BAC_BOX_SHARPL )
Vec_StrPrintStr( vStr, " & " );
else if ( Type == BAC_BOX_SHARP || Type == BAC_BOX_NOR )
Vec_StrPrintStr( vStr, " & ~" );
else if ( Type == BAC_BOX_OR )
Vec_StrPrintStr( vStr, " | " );
else if ( Type == BAC_BOX_NAND )
Vec_StrPrintStr( vStr, " | ~" );
else if ( Type == BAC_BOX_XOR || Type == BAC_BOX_XNOR )
Vec_StrPrintStr( vStr, " ^ " );
else assert( 0 );
Bac_ManWriteSig( p, iObj - 2 );
}
Vec_StrPrintStr( vStr, ";\n" );
}
void Bac_ManWriteVerilogBoxes( Bac_Ntk_t * p, int fUseAssign )
{
Vec_Str_t * vStr = p->pDesign->vOut;
int iObj, k, i, o, StartPos;
Bac_NtkForEachBox( p, iObj ) // .subckt/.gate/box (formal/actual binding)
{
// skip constants
if ( Bac_ObjIsConst(p, iObj) )
continue;
// write mapped
if ( Bac_ObjIsGate(p, iObj) )
{
Bac_ManWriteGate( p, iObj );
continue;
}
// write primitives as assign-statements
if ( !Bac_ObjIsBoxUser(p, iObj) && fUseAssign )
{
Bac_ManWriteAssign( p, iObj );
continue;
}
// write header
StartPos = Vec_StrSize(vStr);
if ( Bac_ObjIsBoxUser(p, iObj) )
{
int Value, Beg, End, Range;
Bac_Ntk_t * pModel = Bac_BoxNtk( p, iObj );
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, Bac_NtkName(pModel) );
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" );
Vec_StrPrintStr( vStr, " (" );
// write arguments
i = o = 0;
assert( Bac_NtkInfoNum(pModel) );
Vec_IntForEachEntryTriple( &pModel->vInfo, Value, Beg, End, k )
{
int NameId = Abc_Lit2Var2( Value );
int Type = Abc_Lit2Att2( Value );
Vec_StrPrintStr( vStr, k ? ", " : "" );
if ( Vec_StrSize(vStr) > StartPos + 70 )
{
StartPos = Vec_StrSize(vStr);
Vec_StrPrintStr( vStr, "\n " );
}
Vec_StrPrintStr( vStr, "." );
Vec_StrPrintStr( vStr, Bac_NtkStr(p, NameId) );
Vec_StrPrintStr( vStr, "(" );
Range = Bac_InfoRange( Beg, End );
assert( Range > 0 );
if ( Type == 1 )
Bac_ManWriteConcat( p, Bac_BoxBi(p, iObj, i), Range ), i += Range;
else if ( Type == 2 )
Bac_ManWriteConcat( p, Bac_BoxBo(p, iObj, o), Range ), o += Range;
else assert( 0 );
Vec_StrPrintStr( vStr, ")" );
}
assert( i == Bac_BoxBiNum(p, iObj) );
assert( o == Bac_BoxBoNum(p, iObj) );
}
else
{
int iTerm, k, Range, iSig = 0;
Vec_Int_t * vBits = Bac_BoxCollectRanges( p, iObj );
char * pName = Bac_NtkGenerateName( p, Bac_ObjType(p, iObj), vBits );
char * pSymbs = Bac_ManPrimSymb( p->pDesign, Bac_ObjType(p, iObj) );
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, pName );
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, Bac_ObjName(p, iObj) ? Bac_ObjNameStr(p, iObj) : "" );
Vec_StrPrintStr( vStr, " (" );
// write inputs
Bac_BoxForEachBiMain( p, iObj, iTerm, k )
{
Range = Vec_IntEntry( vBits, iSig );
Vec_StrPrintStr( vStr, iSig ? ", " : "" );
if ( Vec_StrSize(vStr) > StartPos + 70 )
{
StartPos = Vec_StrSize(vStr);
Vec_StrPrintStr( vStr, "\n " );
}
Vec_StrPrintStr( vStr, "." );
Vec_StrPush( vStr, pSymbs[iSig] );
Vec_StrPrintStr( vStr, "(" );
Bac_ManWriteConcat( p, iTerm, Range );
Vec_StrPrintStr( vStr, ")" );
iSig++;
}
Bac_BoxForEachBoMain( p, iObj, iTerm, k )
{
Range = Vec_IntEntry( vBits, iSig );
Vec_StrPrintStr( vStr, iSig ? ", " : "" );
if ( Vec_StrSize(vStr) > StartPos + 70 )
{
StartPos = Vec_StrSize(vStr);
Vec_StrPrintStr( vStr, "\n " );
}
Vec_StrPrintStr( vStr, "." );
Vec_StrPush( vStr, pSymbs[iSig] );
Vec_StrPrintStr( vStr, "(" );
Bac_ManWriteConcat( p, iTerm, Range );
Vec_StrPrintStr( vStr, ")" );
iSig++;
}
assert( iSig == Vec_IntSize(vBits) );
}
Vec_StrPrintStr( vStr, ");\n" );
}
}
void Bac_ManWriteVerilogNtk( Bac_Ntk_t * p, int fUseAssign )
{
char * pKeyword[4] = { "wire ", "input ", "output ", "inout " };
Vec_Str_t * vStr = p->pDesign->vOut;
int k, iObj, iTerm, Value, Beg, End, Length, fHaveWires, StartPos;
// assert( Bac_NtkInfoNum(p) );
assert( Vec_IntSize(&p->vFanin) == Bac_NtkObjNum(p) );
// Bac_NtkPrint( p );
// write header
Vec_StrPrintStr( vStr, "module " );
Vec_StrPrintStr( vStr, Bac_NtkName(p) );
Vec_StrPrintStr( vStr, " (\n " );
StartPos = Vec_StrSize(vStr);
Vec_IntForEachEntryTriple( &p->vInfo, Value, Beg, End, k )
if ( Abc_Lit2Att2(Value) != 0 )
{
Vec_StrPrintStr( vStr, k ? ", " : "" );
if ( Vec_StrSize(vStr) > StartPos + 70 )
{
StartPos = Vec_StrSize(vStr);
Vec_StrPrintStr( vStr, "\n " );
}
Bac_ManWriteVar( p, Abc_Lit2Var2(Value) );
}
Vec_StrPrintStr( vStr, "\n );\n" );
// write inputs/outputs
Vec_IntForEachEntryTriple( &p->vInfo, Value, Beg, End, k )
if ( Abc_Lit2Att2(Value) != 0 )
{
Vec_StrPrintStr( vStr, " " );
Vec_StrPrintStr( vStr, pKeyword[Abc_Lit2Att2(Value)] );
if ( Beg >= 0 )
Bac_ManWriteRange( p, Beg, End );
Bac_ManWriteVar( p, Abc_Lit2Var2(Value) );
Vec_StrPrintStr( vStr, ";\n" );
}
Vec_StrPrintStr( vStr, "\n" );
// write word-level wires
Bac_NtkForEachBox( p, iObj )
if ( !Bac_ObjIsConst(p, iObj) )
Bac_BoxForEachBo( p, iObj, iTerm, k )
if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_WORD || Bac_ObjNameType(p, iTerm) == BAC_NAME_INFO )
{
Vec_StrPrintStr( vStr, " wire " );
Bac_ManWriteRange( p, Bac_ManFindRealIndex(p, iTerm), Bac_ManFindRealIndex(p, iTerm + Bac_ObjGetRange(p, iTerm) - 1) );
Bac_ManWriteVar( p, Bac_ManFindRealNameId(p, iTerm) );
Vec_StrPrintStr( vStr, ";\n" );
}
// check if there are any wires left
fHaveWires = 0;
Bac_NtkForEachBox( p, iObj )
if ( !Bac_ObjIsConst(p, iObj) )
Bac_BoxForEachBo( p, iObj, iTerm, k )
if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_BIN )
{ fHaveWires = 1; iObj = Bac_NtkObjNum(p); break; }
// write bit-level wires
if ( fHaveWires )
{
Length = 7;
Vec_StrPrintStr( vStr, "\n wire " );
Bac_NtkForEachBox( p, iObj )
if ( !Bac_ObjIsConst(p, iObj) )
Bac_BoxForEachBo( p, iObj, iTerm, k )
if ( Bac_ObjNameType(p, iTerm) == BAC_NAME_BIN )
{
if ( Length > 72 )
Vec_StrPrintStr( vStr, ";\n wire " ), Length = 7;
if ( Length > 7 )
Vec_StrPrintStr( vStr, ", " );
Vec_StrPrintStr( vStr, Bac_ObjNameStr(p, iTerm) );
Length += strlen(Bac_ObjNameStr(p, iTerm));
}
Vec_StrPrintStr( vStr, ";\n" );
}
Vec_StrPrintStr( vStr, "\n" );
// write objects
Bac_ManWriteVerilogBoxes( p, fUseAssign );
Vec_StrPrintStr( vStr, "endmodule\n\n" );
}
void Bac_ManWriteVerilog( char * pFileName, Bac_Man_t * p, int fUseAssign )
{
Bac_Ntk_t * pNtk; int i;
// check the library
if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() )
{
printf( "Genlib library used in the mapped design is not longer a current library.\n" );
return;
}
// derive the stream
p->vOut = Vec_StrAlloc( 10000 );
p->vOut2 = Vec_StrAlloc( 1000 );
Vec_StrPrintStr( p->vOut, "// Design \"" );
Vec_StrPrintStr( p->vOut, Bac_ManName(p) );
Vec_StrPrintStr( p->vOut, "\" written via CBA package in ABC on " );
Vec_StrPrintStr( p->vOut, Extra_TimeStamp() );
Vec_StrPrintStr( p->vOut, "\n\n" );
Bac_ManAssignInternWordNames( p );
Bac_ManForEachNtk( p, pNtk, i )
Bac_ManWriteVerilogNtk( pNtk, fUseAssign );
// dump into file
if ( p->vOut && Vec_StrSize(p->vOut) > 0 )
{
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
printf( "Cannot open file \"%s\" for writing.\n", pFileName );
else
{
fwrite( Vec_StrArray(p->vOut), 1, Vec_StrSize(p->vOut), pFile );
fclose( pFile );
}
}
Vec_StrFreeP( &p->vOut );
Vec_StrFreeP( &p->vOut2 );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

15
src/base/bac/module.make Normal file
View File

@ -0,0 +1,15 @@
SRC += src/base/bac/bacBlast.c \
src/base/bac/bacBac.c \
src/base/bac/bacCom.c \
src/base/bac/bacLib.c \
src/base/bac/bacNtk.c \
src/base/bac/bacPrsBuild.c \
src/base/bac/bacPrsTrans.c \
src/base/bac/bacPtr.c \
src/base/bac/bacPtrAbc.c \
src/base/bac/bacReadBlif.c \
src/base/bac/bacReadSmt.c \
src/base/bac/bacReadVer.c \
src/base/bac/bacWriteBlif.c \
src/base/bac/bacWriteSmt.c \
src/base/bac/bacWriteVer.c

52
src/base/cba/cba.c Normal file
View File

@ -0,0 +1,52 @@
/**CFile****************************************************************
FileName [cba.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis []
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - July 21, 2015.]
Revision [$Id: cba.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cba.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

1024
src/base/cba/cba.h Normal file

File diff suppressed because it is too large Load Diff

1069
src/base/cba/cbaBlast.c Normal file

File diff suppressed because it is too large Load Diff

58
src/base/cba/cbaCba.c Normal file
View File

@ -0,0 +1,58 @@
/**CFile****************************************************************
FileName [cbaCba.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Reading binary representation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - July 21, 2015.]
Revision [$Id: cbaCba.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cba.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cba_Man_t * Cba_ManReadCba( char * pFileName )
{
return NULL;
}
void Cba_ManWriteCba( char * pFileName, Cba_Man_t * p )
{
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

731
src/base/cba/cbaCom.c Normal file
View File

@ -0,0 +1,731 @@
/**CFile****************************************************************
FileName [cbaCom.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Command handlers.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: cbaCom.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cba.h"
#include "proof/cec/cec.h"
#include "base/main/mainInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Cba_CommandRead ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Cba_CommandWrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Cba_CommandPs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Cba_CommandPut ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Cba_CommandGet ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Cba_CommandClp ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Cba_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Cba_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Cba_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv );
static inline Cba_Man_t * Cba_AbcGetMan( Abc_Frame_t * pAbc ) { return (Cba_Man_t *)pAbc->pAbcCba; }
static inline void Cba_AbcFreeMan( Abc_Frame_t * pAbc ) { if ( pAbc->pAbcCba ) Cba_ManFree(Cba_AbcGetMan(pAbc)); }
static inline void Cba_AbcUpdateMan( Abc_Frame_t * pAbc, Cba_Man_t * p ) { Cba_AbcFreeMan(pAbc); pAbc->pAbcCba = p; }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Cba_Init( Abc_Frame_t * pAbc )
{
Cmd_CommandAdd( pAbc, "New word level", ":read", Cba_CommandRead, 0 );
Cmd_CommandAdd( pAbc, "New word level", ":write", Cba_CommandWrite, 0 );
Cmd_CommandAdd( pAbc, "New word level", ":ps", Cba_CommandPs, 0 );
Cmd_CommandAdd( pAbc, "New word level", ":put", Cba_CommandPut, 0 );
Cmd_CommandAdd( pAbc, "New word level", ":get", Cba_CommandGet, 0 );
Cmd_CommandAdd( pAbc, "New word level", ":clp", Cba_CommandClp, 0 );
Cmd_CommandAdd( pAbc, "New word level", ":blast", Cba_CommandBlast, 0 );
Cmd_CommandAdd( pAbc, "New word level", ":cec", Cba_CommandCec, 0 );
Cmd_CommandAdd( pAbc, "New word level", ":test", Cba_CommandTest, 0 );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
void Cba_End( Abc_Frame_t * pAbc )
{
Cba_AbcFreeMan( pAbc );
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandRead( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pFile;
Cba_Man_t * p = NULL;
char * pFileName = NULL;
int c, fTest = 0, fDfs = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "tdvh" ) ) != EOF )
{
switch ( c )
{
case 't':
fTest ^= 1;
break;
case 'd':
fDfs ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( argc != globalUtilOptind + 1 )
{
printf( "Cba_CommandRead(): Input file name should be given on the command line.\n" );
return 0;
}
// get the file name
pFileName = argv[globalUtilOptind];
if ( (pFile = fopen( pFileName, "r" )) == NULL )
{
Abc_Print( 1, "Cannot open input file \"%s\". ", pFileName );
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", ".smt", ".cba", NULL )) )
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
Abc_Print( 1, "\n" );
return 0;
}
fclose( pFile );
if ( fTest )
{
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
Prs_ManReadBlifTest( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
Prs_ManReadVerilogTest( pFileName );
else
{
printf( "Unrecognized input file extension.\n" );
return 0;
}
return 0;
}
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
p = Cba_ManReadBlif( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
p = Cba_ManReadVerilog( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) )
p = Cba_ManReadCba( pFileName );
else
{
printf( "Unrecognized input file extension.\n" );
return 0;
}
if ( fDfs )
{
Cba_Man_t * pTemp;
p = Cba_ManDup( pTemp = p, Cba_NtkCollectDfs );
Cba_ManFree( pTemp );
}
Cba_AbcUpdateMan( pAbc, p );
return 0;
usage:
Abc_Print( -2, "usage: :read [-tdvh] <file_name>\n" );
Abc_Print( -2, "\t reads hierarchical design\n" );
Abc_Print( -2, "\t-t : toggle testing the parser [default = %s]\n", fTest? "yes": "no" );
Abc_Print( -2, "\t-d : toggle computing DFS ordering [default = %s]\n", fDfs? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandWrite( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
char * pFileName = NULL;
int fInclineCats = 0;
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "cvh" ) ) != EOF )
{
switch ( c )
{
case 'c':
fInclineCats ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Cba_CommandWrite(): There is no current design.\n" );
return 0;
}
if ( argc == globalUtilOptind + 1 )
pFileName = argv[globalUtilOptind];
else if ( argc == globalUtilOptind && p )
{
pFileName = Extra_FileNameGenericAppend( Cba_ManSpec(p) ? Cba_ManSpec(p) : Cba_ManName(p), "_out.v" );
printf( "Generated output file name \"%s\".\n", pFileName );
}
else
{
printf( "Output file name should be given on the command line.\n" );
return 0;
}
// perform writing
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
Cba_ManWriteBlif( pFileName, p );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
Cba_ManWriteVerilog( pFileName, p, fInclineCats );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) )
Cba_ManWriteCba( pFileName, p );
else
{
printf( "Unrecognized output file extension.\n" );
return 0;
}
return 0;
usage:
Abc_Print( -2, "usage: :write [-cvh]\n" );
Abc_Print( -2, "\t writes the design into a file in BLIF or Verilog\n" );
Abc_Print( -2, "\t-c : toggle inlining input concatenations [default = %s]\n", fInclineCats? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandPs( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
int nModules = 0;
int fShowMulti = 0;
int fShowAdder = 0;
int fDistrib = 0;
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "Mmadvh" ) ) != EOF )
{
switch ( c )
{
case 'M':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" );
goto usage;
}
nModules = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nModules < 0 )
goto usage;
break;
case 'm':
fShowMulti ^= 1;
break;
case 'a':
fShowAdder ^= 1;
break;
case 'd':
fDistrib ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Cba_CommandPs(): There is no current design.\n" );
return 0;
}
if ( nModules )
{
Cba_ManPrintStats( p, nModules, fVerbose );
return 0;
}
Cba_NtkPrintStatsFull( Cba_ManRoot(p), fDistrib, fVerbose );
if ( fShowMulti )
Cba_NtkPrintNodes( Cba_ManRoot(p), CBA_BOX_MUL );
if ( fShowAdder )
Cba_NtkPrintNodes( Cba_ManRoot(p), CBA_BOX_ADD );
return 0;
usage:
Abc_Print( -2, "usage: :ps [-M num] [-madvh]\n" );
Abc_Print( -2, "\t prints statistics\n" );
Abc_Print( -2, "\t-M num : the number of first modules to report [default = %d]\n", nModules );
Abc_Print( -2, "\t-m : toggle printing multipliers [default = %s]\n", fShowMulti? "yes": "no" );
Abc_Print( -2, "\t-a : toggle printing adders [default = %s]\n", fShowAdder? "yes": "no" );
Abc_Print( -2, "\t-d : toggle printing distrubition [default = %s]\n", fDistrib? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandPut( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
Gia_Man_t * pGia = NULL;
int c, fBarBufs = 1, fSeq = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "bsvh" ) ) != EOF )
{
switch ( c )
{
case 'b':
fBarBufs ^= 1;
break;
case 's':
fSeq ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Cba_CommandPut(): There is no current design.\n" );
return 0;
}
pGia = Cba_ManBlast( p, fBarBufs, fSeq, fVerbose );
if ( pGia == NULL )
{
Abc_Print( 1, "Cba_CommandPut(): Conversion to AIG has failed.\n" );
return 0;
}
Abc_FrameUpdateGia( pAbc, pGia );
return 0;
usage:
Abc_Print( -2, "usage: :put [-bsvh]\n" );
Abc_Print( -2, "\t extracts AIG from the hierarchical design\n" );
Abc_Print( -2, "\t-b : toggle using barrier buffers [default = %s]\n", fBarBufs? "yes": "no" );
Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandGet( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Cba_Man_t * pNew = NULL, * p = Cba_AbcGetMan(pAbc);
int c, fMapped = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "mvh" ) ) != EOF )
{
switch ( c )
{
case 'm':
fMapped ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Cba_CommandGet(): There is no current design.\n" );
return 0;
}
if ( fMapped )
{
if ( pAbc->pNtkCur == NULL )
{
Abc_Print( 1, "Cba_CommandGet(): There is no current mapped design.\n" );
return 0;
}
pNew = Cba_ManInsertAbc( p, pAbc->pNtkCur );
}
else
{
if ( pAbc->pGia == NULL )
{
Abc_Print( 1, "Cba_CommandGet(): There is no current AIG.\n" );
return 0;
}
pNew = Cba_ManInsertGia( p, pAbc->pGia );
}
Cba_AbcUpdateMan( pAbc, pNew );
return 0;
usage:
Abc_Print( -2, "usage: :get [-mvh]\n" );
Abc_Print( -2, "\t extracts AIG or mapped network into the hierarchical design\n" );
Abc_Print( -2, "\t-m : toggle using mapped network from main-space [default = %s]\n", fMapped? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandClp( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Cba_Man_t * pNew = NULL, * p = Cba_AbcGetMan(pAbc);
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Cba_CommandGet(): There is no current design.\n" );
return 0;
}
pNew = Cba_ManCollapse( p );
Cba_AbcUpdateMan( pAbc, pNew );
return 0;
usage:
Abc_Print( -2, "usage: :clp [-vh]\n" );
Abc_Print( -2, "\t collapses the current hierarchical design\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandBlast( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Gia_Man_t * pNew = NULL;
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
int c, fSeq = 0, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF )
{
switch ( c )
{
case 's':
fSeq ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Cba_CommandBlast(): There is no current design.\n" );
return 0;
}
pNew = Cba_ManBlast( p, 0, fSeq, fVerbose );
if ( pNew == NULL )
{
Abc_Print( 1, "Cba_CommandBlast(): Bit-blasting has failed.\n" );
return 0;
}
Abc_FrameUpdateGia( pAbc, pNew );
return 0;
usage:
Abc_Print( -2, "usage: :blast [-svh]\n" );
Abc_Print( -2, "\t performs bit-blasting of the word-level design\n" );
Abc_Print( -2, "\t-s : toggle blasting sequential elements [default = %s]\n", fSeq? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Cba_Man_t * p = Cba_AbcGetMan(pAbc), * pTemp;
Gia_Man_t * pFirst, * pSecond, * pMiter;
Cec_ParCec_t ParsCec, * pPars = &ParsCec;
char * pFileName, * pStr, ** pArgvNew;
int c, nArgcNew, fDumpMiter = 0;
FILE * pFile;
Cec_ManCecSetDefaultParams( pPars );
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
pPars->fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Cba_CommandCec(): There is no current design.\n" );
return 0;
}
pArgvNew = argv + globalUtilOptind;
nArgcNew = argc - globalUtilOptind;
if ( nArgcNew != 1 )
{
if ( p->pSpec == NULL )
{
Abc_Print( -1, "File name is not given on the command line.\n" );
return 1;
}
pFileName = p->pSpec;
}
else
pFileName = pArgvNew[0];
// fix the wrong symbol
for ( pStr = pFileName; *pStr; pStr++ )
if ( *pStr == '>' )
*pStr = '\\';
if ( (pFile = fopen( pFileName, "r" )) == NULL )
{
Abc_Print( -1, "Cannot open input file \"%s\". ", pFileName );
if ( (pFileName = Extra_FileGetSimilarName( pFileName, ".v", ".blif", NULL, NULL, NULL )) )
Abc_Print( 1, "Did you mean \"%s\"?", pFileName );
Abc_Print( 1, "\n" );
return 1;
}
fclose( pFile );
// extract AIG from the current design
pFirst = Cba_ManBlast( p, 0, 0, 0 );
if ( pFirst == NULL )
{
Abc_Print( -1, "Extracting AIG from the current design has failed.\n" );
return 0;
}
// extract AIG from the second design
if ( !strcmp( Extra_FileNameExtension(pFileName), "blif" ) )
pTemp = Cba_ManReadBlif( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
pTemp = Cba_ManReadVerilog( pFileName );
else if ( !strcmp( Extra_FileNameExtension(pFileName), "cba" ) )
pTemp = Cba_ManReadCba( pFileName );
else assert( 0 );
pSecond = Cba_ManBlast( pTemp, 0, 0, 0 );
Cba_ManFree( pTemp );
if ( pSecond == NULL )
{
Gia_ManStop( pFirst );
Abc_Print( -1, "Extracting AIG from the original design has failed.\n" );
return 0;
}
// compute the miter
pMiter = Gia_ManMiter( pFirst, pSecond, 0, 1, 0, 0, pPars->fVerbose );
if ( pMiter )
{
if ( fDumpMiter )
{
Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" );
Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 );
}
pAbc->Status = Cec_ManVerify( pMiter, pPars );
//Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb );
Gia_ManStop( pMiter );
}
Gia_ManStop( pFirst );
Gia_ManStop( pSecond );
return 0;
usage:
Abc_Print( -2, "usage: :cec [-vh]\n" );
Abc_Print( -2, "\t combinational equivalence checking\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
******************************************************************************/
int Cba_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
{
Cba_Man_t * p = Cba_AbcGetMan(pAbc);
int c, fVerbose = 0;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( p == NULL )
{
Abc_Print( 1, "Cba_CommandTest(): There is no current design.\n" );
return 0;
}
return 0;
usage:
Abc_Print( -2, "usage: :test [-vh]\n" );
Abc_Print( -2, "\t experiments with word-level networks\n" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

1183
src/base/cba/cbaNtk.c Normal file

File diff suppressed because it is too large Load Diff

520
src/base/cba/cbaPrs.h Normal file
View File

@ -0,0 +1,520 @@
/**CFile****************************************************************
FileName [cbaPrs.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Parser declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: cbaPrs.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef ABC__base__prs__prs_h
#define ABC__base__prs__prs_h
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include "aig/gia/gia.h"
#include "misc/util/utilNam.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_HEADER_START
// Verilog keywords
typedef enum {
PRS_VER_NONE = 0, // 0: unused
PRS_VER_INPUT, // 1: input
PRS_VER_OUTPUT, // 2: output
PRS_VER_INOUT, // 3: inout
PRS_VER_WIRE, // 4: wire
PRS_VER_REG, // 5: reg
PRS_VER_MODULE, // 6: module
PRS_VER_ASSIGN, // 7: assign
PRS_VER_ALWAYS, // 8: always
PRS_VER_FUNCTION, // 9: function
PRS_VER_DEFPARAM, // 10: defparam
PRS_VER_BEGIN, // 11: begin
PRS_VER_END, // 12: end
PRS_VER_CASE, // 13: case
PRS_VER_ENDCASE, // 14: endcase
PRS_VER_SIGNED, // 15: signed
PRS_VER_ENDMODULE, // 16: endmodule
PRS_VER_UNKNOWN // 17: unknown
} Cba_VerType_t;
// parser name types
typedef enum {
CBA_PRS_NAME = 0, // 0: name/variable
CBA_PRS_SLICE, // 1: slice
CBA_PRS_CONST, // 2: constant
CBA_PRS_CONCAT, // 3: concatentation
} Prs_ManType_t;
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
// network
typedef struct Prs_Ntk_t_ Prs_Ntk_t;
struct Prs_Ntk_t_
{
// general info
int iModuleName;
unsigned fMapped : 1;
unsigned fSlices : 1;
unsigned fHasC0s : 1;
unsigned fHasC1s : 1;
unsigned fHasCXs : 1;
unsigned fHasCZs : 1;
Abc_Nam_t * pStrs;
Abc_Nam_t * pFuns;
Hash_IntMan_t * vHash;
// interface
Vec_Int_t vOrder; // order of signals
// signal names
Vec_Int_t vInouts; // inouts
Vec_Int_t vInputs; // inputs
Vec_Int_t vOutputs; // outputs
Vec_Int_t vWires; // wires
// signal ranges
Vec_Int_t vInoutsR; // inouts
Vec_Int_t vInputsR; // inputs
Vec_Int_t vOutputsR; // outputs
Vec_Int_t vWiresR; // wires
// slices/concatenations/objects
Vec_Int_t vSlices; // NameId + RangeId
Vec_Int_t vConcats; // array of NameId/SliceId/ConstId
Vec_Int_t vBoxes; // ModuleId + InstId + array of pairs {FormNameId, ActSignalId(NameId/SliceId/ConstId/ConcatId)}
Vec_Int_t vObjs; // box handles
};
// parser
typedef struct Prs_Man_t_ Prs_Man_t;
struct Prs_Man_t_
{
// input data
char * pName; // file name
char * pBuffer; // file contents
char * pLimit; // end of file
char * pCur; // current position
Abc_Nam_t * pStrs; // string manager
Abc_Nam_t * pFuns; // cover manager
Hash_IntMan_t * vHash; // variable ranges
Prs_Ntk_t * pNtk; // current network
Vec_Ptr_t * vNtks; // input networks
// temporary data
Vec_Str_t vCover; // one SOP cover
Vec_Int_t vTemp; // array of tokens
Vec_Int_t vTemp2; // array of tokens
Vec_Int_t vTemp3; // array of tokens
Vec_Int_t vTemp4; // array of tokens
// statistics
Vec_Int_t vKnown;
Vec_Int_t vFailed;
Vec_Int_t vSucceeded;
// error handling
int nOpens; // open port counter
int fUsingTemp2; // vTemp2 is in use
int FuncNameId; // temp value
int FuncRangeId; // temp value
char ErrorStr[1000]; // error
};
static inline Prs_Ntk_t * Prs_ManNtk( Vec_Ptr_t * vPrs, int i ) { return i >= 0 && i < Vec_PtrSize(vPrs) ? (Prs_Ntk_t *)Vec_PtrEntry(vPrs, i) : NULL; }
static inline Prs_Ntk_t * Prs_ManRoot( Vec_Ptr_t * vPrs ) { return Prs_ManNtk(vPrs, 0); }
static inline Abc_Nam_t * Prs_ManNameMan( Vec_Ptr_t * vPrs ) { return Prs_ManRoot(vPrs)->pStrs; }
static inline Abc_Nam_t * Prs_ManFuncMan( Vec_Ptr_t * vPrs ) { return Prs_ManRoot(vPrs)->pFuns; }
static inline int Prs_NtkId( Prs_Ntk_t * p ) { return p->iModuleName; }
static inline int Prs_NtkPioNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vInouts); }
static inline int Prs_NtkPiNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vInputs); }
static inline int Prs_NtkPoNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vOutputs); }
static inline int Prs_NtkBoxNum( Prs_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); }
static inline int Prs_NtkObjNum( Prs_Ntk_t * p ) { return Prs_NtkPioNum(p) + Prs_NtkPiNum(p) + Prs_NtkPoNum(p) + Prs_NtkBoxNum(p); }
static inline char * Prs_NtkStr( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pStrs, h); }
static inline char * Prs_NtkSop( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pFuns, h); }
static inline char * Prs_NtkConst( Prs_Ntk_t * p, int h ) { return Abc_NamStr(p->pFuns, h); }
static inline char * Prs_NtkName( Prs_Ntk_t * p ) { return Prs_NtkStr(p, Prs_NtkId(p)); }
static inline int Prs_NtkSigName( Prs_Ntk_t * p, int i ) { if (!p->fSlices) return i; assert(Abc_Lit2Att2(i) == CBA_PRS_NAME); return Abc_Lit2Var2(i); }
static inline int Ptr_NtkRangeSize( Prs_Ntk_t * p, int h ) { int l = Hash_IntObjData0(p->vHash, h), r = Hash_IntObjData1(p->vHash, h); return 1 + (l > r ? l-r : r-l); }
static inline int Prs_SliceName( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h); }
static inline int Prs_SliceRange( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vSlices, h+1); }
static inline int Prs_CatSize( Prs_Ntk_t * p, int h ) { return Vec_IntEntry(&p->vConcats, h); }
static inline int * Prs_CatArray( Prs_Ntk_t * p, int h ) { return Vec_IntEntryP(&p->vConcats, h+1); }
static inline Vec_Int_t * Prs_CatSignals( Prs_Ntk_t * p, int h ) { static Vec_Int_t V; V.nSize = V.nCap = Prs_CatSize(p, h); V.pArray = Prs_CatArray(p, h); return &V; }
static inline int Prs_BoxHand( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vObjs, i); }
static inline int Prs_BoxSize( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i))-2; }
static inline int Prs_BoxIONum( Prs_Ntk_t * p, int i ) { return Prs_BoxSize(p, i) / 2; }
static inline int Prs_BoxNtk( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+1); }
static inline void Prs_BoxSetNtk( Prs_Ntk_t * p, int i, int m ) { Vec_IntWriteEntry(&p->vBoxes, Prs_BoxHand(p, i)+1, m); }
static inline int Prs_BoxName( Prs_Ntk_t * p, int i ) { return Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+2); }
static inline int Prs_BoxIsNode( Prs_Ntk_t * p, int i ) { return!Vec_IntEntry(&p->vBoxes, Prs_BoxHand(p, i)+3); } // no formal names
static inline int * Prs_BoxArray( Prs_Ntk_t * p, int i ) { return Vec_IntEntryP(&p->vBoxes, Prs_BoxHand(p, i)+3); }
static inline Vec_Int_t * Prs_BoxSignals( Prs_Ntk_t * p, int i ) { static Vec_Int_t V; V.nSize = V.nCap = Prs_BoxSize(p, i); V.pArray = Prs_BoxArray(p, i); return &V; }
#define Prs_ManForEachNameVec( vVec, p, pName, i ) \
for ( i = 0; (i < Vec_IntSize(vVec)) && ((pName) = Abc_NamStr(p->pStrs, Vec_IntEntry(vVec,i))); i++ )
#define Prs_NtkForEachPio( p, NameId, i ) \
for ( i = 0; i < Prs_NtkPioNum(p) && ((NameId) = Vec_IntEntry(&p->vInouts, i)); i++ )
#define Prs_NtkForEachPi( p, NameId, i ) \
for ( i = 0; i < Prs_NtkPiNum(p) && ((NameId) = Vec_IntEntry(&p->vInputs, i)); i++ )
#define Prs_NtkForEachPo( p, NameId, i ) \
for ( i = 0; i < Prs_NtkPoNum(p) && ((NameId) = Vec_IntEntry(&p->vOutputs, i)); i++ )
#define Prs_NtkForEachBox( p, vVec, i ) \
for ( i = 0; i < Prs_NtkBoxNum(p) && ((vVec) = Prs_BoxSignals(p, i)); i++ )
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
// create error message
static inline int Prs_ManErrorSet( Prs_Man_t * p, char * pError, int Value )
{
assert( !p->ErrorStr[0] );
sprintf( p->ErrorStr, "%s", pError );
return Value;
}
// clear error message
static inline void Prs_ManErrorClear( Prs_Man_t * p )
{
p->ErrorStr[0] = '\0';
}
// print error message
static inline int Prs_ManErrorPrint( Prs_Man_t * p )
{
char * pThis; int iLine = 0;
if ( !p->ErrorStr[0] ) return 1;
for ( pThis = p->pBuffer; pThis < p->pCur; pThis++ )
iLine += (int)(*pThis == '\n');
printf( "Line %d: %s\n", iLine, p->ErrorStr );
return 0;
}
// parsing network
static inline void Prs_ManInitializeNtk( Prs_Man_t * p, int iName, int fSlices )
{
assert( p->pNtk == NULL );
p->pNtk = ABC_CALLOC( Prs_Ntk_t, 1 );
p->pNtk->iModuleName = iName;
p->pNtk->fSlices = fSlices;
p->pNtk->pStrs = Abc_NamRef( p->pStrs );
p->pNtk->pFuns = Abc_NamRef( p->pFuns );
p->pNtk->vHash = Hash_IntManRef( p->vHash );
Vec_PtrPush( p->vNtks, p->pNtk );
}
static inline void Prs_ManFinalizeNtk( Prs_Man_t * p )
{
assert( p->pNtk != NULL );
p->pNtk = NULL;
}
static inline int Prs_ManNewStrId( Prs_Man_t * p, const char * format, ... )
{
Abc_Nam_t * pStrs = p->pStrs;
Vec_Str_t * vBuf = Abc_NamBuffer( pStrs );
int nAdded, nSize = 1000;
va_list args; va_start( args, format );
Vec_StrGrow( vBuf, Vec_StrSize(vBuf) + nSize );
nAdded = vsnprintf( Vec_StrLimit(vBuf), nSize, format, args );
if ( nAdded > nSize )
{
Vec_StrGrow( vBuf, Vec_StrSize(vBuf) + nAdded + nSize );
nSize = vsnprintf( Vec_StrLimit(vBuf), nAdded, format, args );
assert( nSize == nAdded );
}
va_end( args );
return Abc_NamStrFindOrAddLim( pStrs, Vec_StrLimit(vBuf), Vec_StrLimit(vBuf) + nAdded, NULL );
}
// parsing slice/concatentation/box
static inline int Prs_NtkAddSlice( Prs_Ntk_t * p, int Name, int Range )
{
int Value = Vec_IntSize(&p->vSlices);
Vec_IntPushTwo( &p->vSlices, Name, Range );
return Value;
}
static inline int Prs_NtkAddConcat( Prs_Ntk_t * p, Vec_Int_t * vTemp )
{
int Value;
if ( !(Vec_IntSize(&p->vConcats) & 1) )
Vec_IntPush(&p->vConcats, -1);
Value = Vec_IntSize(&p->vConcats);
assert( Value & 1 );
Vec_IntPush( &p->vConcats, Vec_IntSize(vTemp) );
Vec_IntAppend( &p->vConcats, vTemp );
return Value;
}
static inline void Prs_NtkAddBox( Prs_Ntk_t * p, int ModName, int InstName, Vec_Int_t * vTemp )
{
int Value;
assert( Vec_IntSize(vTemp) % 2 == 0 );
if ( !(Vec_IntSize(&p->vBoxes) & 1) )
Vec_IntPush(&p->vBoxes, -1);
Value = Vec_IntSize(&p->vBoxes);
assert( Value & 1 );
Vec_IntPush( &p->vObjs, Value );
// create entry
Vec_IntPush( &p->vBoxes, Vec_IntSize(vTemp)+2 );
Vec_IntPush( &p->vBoxes, ModName );
Vec_IntPush( &p->vBoxes, InstName );
Vec_IntAppend( &p->vBoxes, vTemp );
}
static inline char * Prs_ManLoadFile( char * pFileName, char ** ppLimit )
{
char * pBuffer;
int nFileSize, RetValue;
FILE * pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
printf( "Cannot open input file.\n" );
return NULL;
}
// get the file size, in bytes
fseek( pFile, 0, SEEK_END );
nFileSize = ftell( pFile );
// move the file current reading position to the beginning
rewind( pFile );
// load the contents of the file into memory
pBuffer = ABC_ALLOC( char, nFileSize + 16 );
pBuffer[0] = '\n';
RetValue = fread( pBuffer+1, nFileSize, 1, pFile );
fclose( pFile );
// terminate the string with '\0'
pBuffer[nFileSize + 1] = '\n';
pBuffer[nFileSize + 2] = '\0';
*ppLimit = pBuffer + nFileSize + 3;
return pBuffer;
}
static inline Prs_Man_t * Prs_ManAlloc( char * pFileName )
{
Prs_Man_t * p;
p = ABC_CALLOC( Prs_Man_t, 1 );
if ( pFileName )
{
char * pBuffer, * pLimit;
pBuffer = Prs_ManLoadFile( pFileName, &pLimit );
if ( pBuffer == NULL )
return NULL;
p->pName = pFileName;
p->pBuffer = pBuffer;
p->pLimit = pLimit;
p->pCur = pBuffer;
}
p->pStrs = Abc_NamStart( 1000, 24 );
p->pFuns = Abc_NamStart( 100, 24 );
p->vHash = Hash_IntManStart( 1000 );
p->vNtks = Vec_PtrAlloc( 100 );
return p;
}
static inline void Prs_NtkFree( Prs_Ntk_t * p )
{
if ( p->pStrs ) Abc_NamDeref( p->pStrs );
if ( p->pFuns ) Abc_NamDeref( p->pFuns );
if ( p->vHash ) Hash_IntManDeref( p->vHash );
Vec_IntErase( &p->vOrder );
Vec_IntErase( &p->vInouts );
Vec_IntErase( &p->vInputs );
Vec_IntErase( &p->vOutputs );
Vec_IntErase( &p->vWires );
Vec_IntErase( &p->vInoutsR );
Vec_IntErase( &p->vInputsR );
Vec_IntErase( &p->vOutputsR );
Vec_IntErase( &p->vWiresR );
Vec_IntErase( &p->vSlices );
Vec_IntErase( &p->vConcats );
Vec_IntErase( &p->vBoxes );
Vec_IntErase( &p->vObjs );
ABC_FREE( p );
}
static inline void Prs_ManVecFree( Vec_Ptr_t * vPrs )
{
Prs_Ntk_t * pNtk; int i;
Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i )
Prs_NtkFree( pNtk );
Vec_PtrFree( vPrs );
}
static inline void Prs_ManFree( Prs_Man_t * p )
{
if ( p->pStrs ) Abc_NamDeref( p->pStrs );
if ( p->pFuns ) Abc_NamDeref( p->pFuns );
if ( p->vHash ) Hash_IntManDeref( p->vHash );
if ( p->vNtks ) Prs_ManVecFree( p->vNtks );
// temporary
Vec_StrErase( &p->vCover );
Vec_IntErase( &p->vTemp );
Vec_IntErase( &p->vTemp2 );
Vec_IntErase( &p->vTemp3 );
Vec_IntErase( &p->vTemp4 );
Vec_IntErase( &p->vKnown );
Vec_IntErase( &p->vFailed );
Vec_IntErase( &p->vSucceeded );
ABC_FREE( p->pBuffer );
ABC_FREE( p );
}
static inline int Prs_NtkMemory( Prs_Ntk_t * p )
{
int nMem = sizeof(Prs_Ntk_t);
nMem += Vec_IntMemory( &p->vOrder );
nMem += Vec_IntMemory( &p->vInouts );
nMem += Vec_IntMemory( &p->vInputs );
nMem += Vec_IntMemory( &p->vOutputs );
nMem += Vec_IntMemory( &p->vWires );
nMem += Vec_IntMemory( &p->vInoutsR );
nMem += Vec_IntMemory( &p->vInputsR );
nMem += Vec_IntMemory( &p->vOutputsR );
nMem += Vec_IntMemory( &p->vWiresR );
nMem += Vec_IntMemory( &p->vSlices );
nMem += Vec_IntMemory( &p->vBoxes );
nMem += Vec_IntMemory( &p->vConcats );
return nMem;
}
static inline int Prs_ManMemory( Vec_Ptr_t * vPrs )
{
Prs_Ntk_t * pNtk; int i;
int nMem = Vec_PtrMemory(vPrs);
Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i )
nMem += Prs_NtkMemory( pNtk );
nMem += Abc_NamMemUsed(Prs_ManNameMan(vPrs));
return nMem;
}
/**Function*************************************************************
Synopsis [Other APIs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Cba_ObjType_t Ptr_SopToType( char * pSop )
{
if ( !strcmp(pSop, " 0\n") ) return CBA_BOX_CF;
if ( !strcmp(pSop, " 1\n") ) return CBA_BOX_CT;
if ( !strcmp(pSop, "1 1\n") ) return CBA_BOX_BUF;
if ( !strcmp(pSop, "0 1\n") ) return CBA_BOX_INV;
if ( !strcmp(pSop, "11 1\n") ) return CBA_BOX_AND;
if ( !strcmp(pSop, "00 1\n") ) return CBA_BOX_NOR;
if ( !strcmp(pSop, "00 0\n") ) return CBA_BOX_OR;
if ( !strcmp(pSop, "-1 1\n1- 1\n") ) return CBA_BOX_OR;
if ( !strcmp(pSop, "1- 1\n-1 1\n") ) return CBA_BOX_OR;
if ( !strcmp(pSop, "01 1\n10 1\n") ) return CBA_BOX_XOR;
if ( !strcmp(pSop, "10 1\n01 1\n") ) return CBA_BOX_XOR;
if ( !strcmp(pSop, "11 1\n00 1\n") ) return CBA_BOX_XNOR;
if ( !strcmp(pSop, "00 1\n11 1\n") ) return CBA_BOX_XNOR;
if ( !strcmp(pSop, "10 1\n") ) return CBA_BOX_SHARP;
if ( !strcmp(pSop, "01 1\n") ) return CBA_BOX_SHARPL;
assert( 0 );
return CBA_OBJ_NONE;
}
static inline char * Ptr_SopToTypeName( char * pSop )
{
if ( !strcmp(pSop, " 0\n") ) return "CBA_BOX_C0";
if ( !strcmp(pSop, " 1\n") ) return "CBA_BOX_C1";
if ( !strcmp(pSop, "1 1\n") ) return "CBA_BOX_BUF";
if ( !strcmp(pSop, "0 1\n") ) return "CBA_BOX_INV";
if ( !strcmp(pSop, "11 1\n") ) return "CBA_BOX_AND";
if ( !strcmp(pSop, "00 1\n") ) return "CBA_BOX_NOR";
if ( !strcmp(pSop, "00 0\n") ) return "CBA_BOX_OR";
if ( !strcmp(pSop, "-1 1\n1- 1\n") ) return "CBA_BOX_OR";
if ( !strcmp(pSop, "1- 1\n-1 1\n") ) return "CBA_BOX_OR";
if ( !strcmp(pSop, "01 1\n10 1\n") ) return "CBA_BOX_XOR";
if ( !strcmp(pSop, "10 1\n01 1\n") ) return "CBA_BOX_XOR";
if ( !strcmp(pSop, "11 1\n00 1\n") ) return "CBA_BOX_XNOR";
if ( !strcmp(pSop, "00 1\n11 1\n") ) return "CBA_BOX_XNOR";
if ( !strcmp(pSop, "10 1\n") ) return "CBA_BOX_SHARP";
if ( !strcmp(pSop, "01 1\n") ) return "CBA_BOX_SHARPL";
assert( 0 );
return NULL;
}
static inline char * Ptr_TypeToName( Cba_ObjType_t Type )
{
if ( Type == CBA_BOX_CF ) return "const0";
if ( Type == CBA_BOX_CT ) return "const1";
if ( Type == CBA_BOX_CX ) return "constX";
if ( Type == CBA_BOX_CZ ) return "constZ";
if ( Type == CBA_BOX_BUF ) return "buf";
if ( Type == CBA_BOX_INV ) return "not";
if ( Type == CBA_BOX_AND ) return "and";
if ( Type == CBA_BOX_NAND ) return "nand";
if ( Type == CBA_BOX_OR ) return "or";
if ( Type == CBA_BOX_NOR ) return "nor";
if ( Type == CBA_BOX_XOR ) return "xor";
if ( Type == CBA_BOX_XNOR ) return "xnor";
if ( Type == CBA_BOX_MUX ) return "mux";
if ( Type == CBA_BOX_MAJ ) return "maj";
if ( Type == CBA_BOX_SHARP ) return "sharp";
if ( Type == CBA_BOX_SHARPL) return "sharpl";
if ( Type == CBA_BOX_TRI) return "bufifl";
assert( 0 );
return "???";
}
static inline char * Ptr_TypeToSop( Cba_ObjType_t Type )
{
if ( Type == CBA_BOX_CF ) return " 0\n";
if ( Type == CBA_BOX_CT ) return " 1\n";
if ( Type == CBA_BOX_CX ) return " 0\n";
if ( Type == CBA_BOX_CZ ) return " 0\n";
if ( Type == CBA_BOX_BUF ) return "1 1\n";
if ( Type == CBA_BOX_INV ) return "0 1\n";
if ( Type == CBA_BOX_AND ) return "11 1\n";
if ( Type == CBA_BOX_NAND ) return "11 0\n";
if ( Type == CBA_BOX_OR ) return "00 0\n";
if ( Type == CBA_BOX_NOR ) return "00 1\n";
if ( Type == CBA_BOX_XOR ) return "01 1\n10 1\n";
if ( Type == CBA_BOX_XNOR ) return "00 1\n11 1\n";
if ( Type == CBA_BOX_SHARP ) return "10 1\n";
if ( Type == CBA_BOX_SHARPL) return "01 1\n";
if ( Type == CBA_BOX_MUX ) return "11- 1\n0-1 1\n";
if ( Type == CBA_BOX_MAJ ) return "11- 1\n1-1 1\n-11 1\n";
assert( 0 );
return "???";
}
////////////////////////////////////////////////////////////////////////
/// ITERATORS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== cbaReadVer.c ========================================================*/
extern void Prs_NtkAddVerilogDirectives( Prs_Man_t * p );
ABC_NAMESPACE_HEADER_END
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

646
src/base/cba/cbaReadBlif.c Normal file
View File

@ -0,0 +1,646 @@
/**CFile****************************************************************
FileName [cbaReadBlif.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [BLIF parser.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: cbaReadBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cba.h"
#include "cbaPrs.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// BLIF keywords
typedef enum {
PRS_BLIF_NONE = 0, // 0: unused
PRS_BLIF_MODEL, // 1: .model
PRS_BLIF_INOUTS, // 2: .inouts
PRS_BLIF_INPUTS, // 3: .inputs
PRS_BLIF_OUTPUTS, // 4: .outputs
PRS_BLIF_NAMES, // 5: .names
PRS_BLIF_SUBCKT, // 6: .subckt
PRS_BLIF_GATE, // 7: .gate
PRS_BLIF_LATCH, // 8: .latch
PRS_BLIF_SHORT, // 9: .short
PRS_BLIF_END, // 10: .end
PRS_BLIF_UNKNOWN // 11: unknown
} Cba_BlifType_t;
static const char * s_BlifTypes[PRS_BLIF_UNKNOWN+1] = {
NULL, // 0: unused
".model", // 1: .model
".inouts", // 2: .inputs
".inputs", // 3: .inputs
".outputs", // 4: .outputs
".names", // 5: .names
".subckt", // 6: .subckt
".gate", // 7: .gate
".latch", // 8: .latch
".short", // 9: .short
".end", // 10: .end
NULL // 11: unknown
};
static inline void Prs_NtkAddBlifDirectives( Prs_Man_t * p )
{
int i;
for ( i = 1; s_BlifTypes[i]; i++ )
Abc_NamStrFindOrAdd( p->pStrs, (char *)s_BlifTypes[i], NULL );
assert( Abc_NamObjNumMax(p->pStrs) == i );
}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Reading characters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Prs_CharIsSpace( char c ) { return c == ' ' || c == '\t' || c == '\r'; }
static inline int Prs_CharIsStop( char c ) { return c == '#' || c == '\\' || c == '\n' || c == '='; }
static inline int Prs_CharIsLit( char c ) { return c == '0' || c == '1' || c == '-'; }
static inline int Prs_ManIsSpace( Prs_Man_t * p ) { return Prs_CharIsSpace(*p->pCur); }
static inline int Prs_ManIsStop( Prs_Man_t * p ) { return Prs_CharIsStop(*p->pCur); }
static inline int Prs_ManIsLit( Prs_Man_t * p ) { return Prs_CharIsLit(*p->pCur); }
static inline int Prs_ManIsChar( Prs_Man_t * p, char c ) { return *p->pCur == c; }
static inline int Prs_ManIsChar2( Prs_Man_t * p, char c ) { return *p->pCur++ == c; }
static inline void Prs_ManSkip( Prs_Man_t * p ) { p->pCur++; }
static inline char Prs_ManSkip2( Prs_Man_t * p ) { return *p->pCur++; }
/**Function*************************************************************
Synopsis [Reading names.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Prs_ManSkipToChar( Prs_Man_t * p, char c )
{
while ( !Prs_ManIsChar(p, c) )
Prs_ManSkip(p);
}
static inline void Prs_ManSkipSpaces( Prs_Man_t * p )
{
while ( 1 )
{
while ( Prs_ManIsSpace(p) )
Prs_ManSkip(p);
if ( Prs_ManIsChar(p, '\\') )
{
Prs_ManSkipToChar( p, '\n' );
Prs_ManSkip(p);
continue;
}
if ( Prs_ManIsChar(p, '#') )
Prs_ManSkipToChar( p, '\n' );
break;
}
assert( !Prs_ManIsSpace(p) );
}
static inline int Prs_ManReadName( Prs_Man_t * p )
{
char * pStart;
Prs_ManSkipSpaces( p );
if ( Prs_ManIsChar(p, '\n') )
return 0;
pStart = p->pCur;
while ( !Prs_ManIsSpace(p) && !Prs_ManIsStop(p) )
Prs_ManSkip(p);
if ( pStart == p->pCur )
return 0;
return Abc_NamStrFindOrAddLim( p->pStrs, pStart, p->pCur, NULL );
}
static inline int Prs_ManReadList( Prs_Man_t * p, Vec_Int_t * vOrder, int Type )
{
int iToken;
Vec_IntClear( &p->vTemp );
while ( (iToken = Prs_ManReadName(p)) )
{
Vec_IntPush( &p->vTemp, iToken );
Vec_IntPush( vOrder, Abc_Var2Lit2(iToken, Type) );
}
if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Signal list is empty.", 1);
return 0;
}
static inline int Prs_ManReadList2( Prs_Man_t * p )
{
int iToken;
Vec_IntClear( &p->vTemp );
while ( (iToken = Prs_ManReadName(p)) )
Vec_IntPushTwo( &p->vTemp, 0, iToken );
if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Signal list is empty.", 1);
return 0;
}
static inline int Prs_ManReadList3( Prs_Man_t * p )
{
Vec_IntClear( &p->vTemp );
while ( !Prs_ManIsChar(p, '\n') )
{
int iToken = Prs_ManReadName(p);
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read formal name.", 1);
Vec_IntPush( &p->vTemp, iToken );
Prs_ManSkipSpaces( p );
if ( !Prs_ManIsChar2(p, '=') ) return Prs_ManErrorSet(p, "Cannot find symbol \"=\".", 1);
iToken = Prs_ManReadName(p);
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read actual name.", 1);
Vec_IntPush( &p->vTemp, iToken );
Prs_ManSkipSpaces( p );
}
if ( Vec_IntSize(&p->vTemp) == 0 ) return Prs_ManErrorSet(p, "Cannot read a list of formal/actual names.", 1);
if ( Vec_IntSize(&p->vTemp) % 2 ) return Prs_ManErrorSet(p, "The number of formal/actual names is not even.", 1);
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Prs_ManReadCube( Prs_Man_t * p )
{
assert( Prs_ManIsLit(p) );
while ( Prs_ManIsLit(p) )
Vec_StrPush( &p->vCover, Prs_ManSkip2(p) );
Prs_ManSkipSpaces( p );
if ( Prs_ManIsChar(p, '\n') )
{
if ( Vec_StrSize(&p->vCover) != 1 ) return Prs_ManErrorSet(p, "Cannot read cube.", 1);
// fix single literal cube by adding space
Vec_StrPush( &p->vCover, Vec_StrEntry(&p->vCover,0) );
Vec_StrWriteEntry( &p->vCover, 0, ' ' );
Vec_StrPush( &p->vCover, '\n' );
return 0;
}
if ( !Prs_ManIsLit(p) ) return Prs_ManErrorSet(p, "Cannot read output literal.", 1);
Vec_StrPush( &p->vCover, ' ' );
Vec_StrPush( &p->vCover, Prs_ManSkip2(p) );
Vec_StrPush( &p->vCover, '\n' );
Prs_ManSkipSpaces( p );
if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Cannot read end of cube.", 1);
return 0;
}
static inline void Prs_ManSaveCover( Prs_Man_t * p )
{
int iToken;
if ( Vec_StrSize(&p->vCover) == 0 )
p->pNtk->fHasC0s = 1;
else if ( Vec_StrSize(&p->vCover) == 2 )
{
if ( Vec_StrEntryLast(&p->vCover) == '0' )
p->pNtk->fHasC0s = 1;
else if ( Vec_StrEntryLast(&p->vCover) == '1' )
p->pNtk->fHasC1s = 1;
else assert( 0 );
}
assert( Vec_StrSize(&p->vCover) > 0 );
Vec_StrPush( &p->vCover, '\0' );
// iToken = Ptr_SopToType( Vec_StrArray(&p->vCover) );
iToken = Abc_NamStrFindOrAdd( p->pFuns, Vec_StrArray(&p->vCover), NULL );
Vec_StrClear( &p->vCover );
// set the cover to the module of this box
assert( Prs_BoxNtk(p->pNtk, Prs_NtkBoxNum(p->pNtk)-1) == 1 ); // default const 0
Prs_BoxSetNtk( p->pNtk, Prs_NtkBoxNum(p->pNtk)-1, iToken );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Prs_ManReadInouts( Prs_Man_t * p )
{
if ( Prs_ManReadList(p, &p->pNtk->vOrder, 3) ) return 1;
Vec_IntAppend( &p->pNtk->vInouts, &p->vTemp );
return 0;
}
static inline int Prs_ManReadInputs( Prs_Man_t * p )
{
if ( Prs_ManReadList(p, &p->pNtk->vOrder, 1) ) return 1;
Vec_IntAppend( &p->pNtk->vInputs, &p->vTemp );
return 0;
}
static inline int Prs_ManReadOutputs( Prs_Man_t * p )
{
if ( Prs_ManReadList(p, &p->pNtk->vOrder, 2) ) return 1;
Vec_IntAppend( &p->pNtk->vOutputs, &p->vTemp );
return 0;
}
static inline int Prs_ManReadNode( Prs_Man_t * p )
{
if ( Prs_ManReadList2(p) ) return 1;
// save results
Prs_NtkAddBox( p->pNtk, 1, 0, &p->vTemp ); // default const 0 function
return 0;
}
static inline int Prs_ManReadBox( Prs_Man_t * p, int fGate )
{
int iToken = Prs_ManReadName(p);
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read model name.", 1);
if ( Prs_ManReadList3(p) ) return 1;
// save results
Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
if ( fGate ) p->pNtk->fMapped = 1;
return 0;
}
static inline int Prs_ManReadLatch( Prs_Man_t * p )
{
int iToken = Prs_ManReadName(p);
Vec_IntClear( &p->vTemp );
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read latch input.", 1);
Vec_IntWriteEntry( &p->vTemp, 1, iToken );
iToken = Prs_ManReadName(p);
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read latch output.", 1);
Vec_IntWriteEntry( &p->vTemp, 0, iToken );
Prs_ManSkipSpaces( p );
if ( Prs_ManIsChar(p, '0') )
iToken = 0;
else if ( Prs_ManIsChar(p, '1') )
iToken = 1;
else
iToken = 2;
Prs_ManSkipToChar( p, '\n' );
// save results
Prs_NtkAddBox( p->pNtk, -1, iToken, &p->vTemp ); // -1 stands for latch
return 0;
}
static inline int Prs_ManReadShort( Prs_Man_t * p )
{
int iToken = Prs_ManReadName(p);
Vec_IntClear( &p->vTemp );
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read .short input.", 1);
Vec_IntWriteEntry( &p->vTemp, 1, iToken );
iToken = Prs_ManReadName(p);
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read .short output.", 1);
Vec_IntWriteEntry( &p->vTemp, 0, iToken );
Prs_ManSkipSpaces( p );
if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .short line.", 1);
// save results
iToken = Abc_NamStrFindOrAdd( p->pStrs, "1 1\n", NULL );
Prs_NtkAddBox( p->pNtk, iToken, 0, &p->vTemp );
return 0;
}
static inline int Prs_ManReadModel( Prs_Man_t * p )
{
int iToken;
if ( p->pNtk != NULL ) return Prs_ManErrorSet(p, "Parsing previous model is unfinished.", 1);
iToken = Prs_ManReadName(p);
if ( iToken == 0 ) return Prs_ManErrorSet(p, "Cannot read model name.", 1);
Prs_ManInitializeNtk( p, iToken, 0 );
Prs_ManSkipSpaces( p );
if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .model line.", 1);
return 0;
}
static inline int Prs_ManReadEnd( Prs_Man_t * p )
{
if ( p->pNtk == 0 ) return Prs_ManErrorSet(p, "Directive .end without .model.", 1);
//printf( "Saving model \"%s\".\n", Abc_NamStr(p->pStrs, p->iModuleName) );
Prs_ManFinalizeNtk( p );
Prs_ManSkipSpaces( p );
if ( !Prs_ManIsChar(p, '\n') ) return Prs_ManErrorSet(p, "Trailing symbols on .end line.", 1);
return 0;
}
static inline int Prs_ManReadDirective( Prs_Man_t * p )
{
int iToken;
if ( !Prs_ManIsChar(p, '.') )
return Prs_ManReadCube( p );
if ( Vec_StrSize(&p->vCover) > 0 ) // SOP was specified for the previous node
Prs_ManSaveCover( p );
iToken = Prs_ManReadName( p );
if ( iToken == PRS_BLIF_MODEL )
return Prs_ManReadModel( p );
if ( iToken == PRS_BLIF_INOUTS )
return Prs_ManReadInouts( p );
if ( iToken == PRS_BLIF_INPUTS )
return Prs_ManReadInputs( p );
if ( iToken == PRS_BLIF_OUTPUTS )
return Prs_ManReadOutputs( p );
if ( iToken == PRS_BLIF_NAMES )
return Prs_ManReadNode( p );
if ( iToken == PRS_BLIF_SUBCKT )
return Prs_ManReadBox( p, 0 );
if ( iToken == PRS_BLIF_GATE )
return Prs_ManReadBox( p, 1 );
if ( iToken == PRS_BLIF_LATCH )
return Prs_ManReadLatch( p );
if ( iToken == PRS_BLIF_SHORT )
return Prs_ManReadShort( p );
if ( iToken == PRS_BLIF_END )
return Prs_ManReadEnd( p );
printf( "Cannot read directive \"%s\".\n", Abc_NamStr(p->pStrs, iToken) );
return 1;
}
static inline int Prs_ManReadLines( Prs_Man_t * p )
{
while ( p->pCur[1] != '\0' )
{
assert( Prs_ManIsChar(p, '\n') );
Prs_ManSkip(p);
Prs_ManSkipSpaces( p );
if ( Prs_ManIsChar(p, '\n') )
continue;
if ( Prs_ManReadDirective(p) )
return 1;
}
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Prs_ManReadBlif( char * pFileName )
{
Vec_Ptr_t * vPrs = NULL;
Prs_Man_t * p = Prs_ManAlloc( pFileName );
if ( p == NULL )
return NULL;
Abc_NamStrFindOrAdd( p->pFuns, " 0\n", NULL );
Abc_NamStrFindOrAdd( p->pFuns, " 1\n", NULL );
Prs_NtkAddBlifDirectives( p );
Prs_ManReadLines( p );
if ( Prs_ManErrorPrint(p) )
ABC_SWAP( Vec_Ptr_t *, vPrs, p->vNtks );
Prs_ManFree( p );
return vPrs;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Prs_ManReadBlifTest( char * pFileName )
{
abctime clk = Abc_Clock();
Vec_Ptr_t * vPrs = Prs_ManReadBlif( pFileName );
if ( !vPrs ) return;
printf( "Finished reading %d networks. ", Vec_PtrSize(vPrs) );
printf( "NameIDs = %d. ", Abc_NamObjNumMax(Prs_ManNameMan(vPrs)) );
printf( "Memory = %.2f MB. ", 1.0*Prs_ManMemory(vPrs)/(1<<20) );
Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
// Abc_NamPrint( p->pStrs );
Prs_ManWriteBlif( Extra_FileNameGenericAppend(pFileName, "_out.blif"), vPrs );
Prs_ManVecFree( vPrs );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Prs_CreateBlifFindFon( Cba_Ntk_t * p, int NameId )
{
int iFon = Cba_NtkGetMap( p, NameId );
if ( iFon )
return iFon;
printf( "Network \"%s\": Signal \"%s\" is not driven.\n", Cba_NtkName(p), Cba_NtkStr(p, NameId) );
return 0;
}
void Prs_CreateBlifPio( Cba_Ntk_t * p, Prs_Ntk_t * pNtk )
{
int i, NameId, iObj, iFon;
Cba_NtkCleanObjFuncs( p );
Cba_NtkCleanObjNames( p );
Cba_NtkCleanFonNames( p );
// create inputs
Prs_NtkForEachPi( pNtk, NameId, i )
{
iObj = Cba_ObjAlloc( p, CBA_OBJ_PI, 0, 1 );
Cba_ObjSetName( p, iObj, NameId );
iFon = Cba_ObjFon0(p, iObj);
Cba_FonSetName( p, iFon, NameId );
Cba_NtkSetMap( p, NameId, iFon );
Vec_IntPush( &p->vOrder, iObj );
}
// create outputs
Prs_NtkForEachPo( pNtk, NameId, i )
{
iObj = Cba_ObjAlloc( p, CBA_OBJ_PO, 1, 0 );
Cba_ObjSetName( p, iObj, NameId );
Vec_IntPush( &p->vOrder, iObj );
}
}
int Prs_CreateBlifNtk( Cba_Ntk_t * p, Prs_Ntk_t * pNtk )
{
Vec_Int_t * vBox;
int i, k, iObj, iTerm, iFon, FormId, ActId;
// map inputs
Cba_NtkCleanMap( p );
Cba_NtkForEachPi( p, iObj, i )
Cba_NtkSetMap( p, Cba_ObjName(p, iObj), Cba_ObjFon0(p, iObj) );
// create objects
Prs_NtkForEachBox( pNtk, vBox, i )
{
int FuncId = Prs_BoxNtk(pNtk, i);
assert( Prs_BoxIONum(pNtk, i) > 0 );
assert( Vec_IntSize(vBox) % 2 == 0 );
if ( FuncId == -1 ) // latch
{
iObj = Cba_ObjAlloc( p, CBA_BOX_DFFRS, 4, 1 );
Cba_NtkSetMap( p, Vec_IntEntry(vBox, 3), Cba_ObjFon0(p, iObj) ); // latch output
Cba_ObjSetFunc( p, iObj, Prs_BoxName(pNtk, i)+1 ); // init + 1
}
else if ( Prs_BoxIsNode(pNtk, i) ) // node
{
iObj = Cba_ObjAlloc( p, CBA_BOX_NODE, Prs_BoxIONum(pNtk, i)-1, 1 );
Cba_FonSetName( p, Cba_ObjFon0(p, iObj), Vec_IntEntryLast(vBox) ); // node output
Cba_NtkSetMap( p, Vec_IntEntryLast(vBox), Cba_ObjFon0(p, iObj) );
Cba_ObjSetFunc( p, iObj, FuncId );
}
else // box
{
Cba_Ntk_t * pBox = Cba_ManNtkFind( p->pDesign, Prs_NtkStr(pNtk, FuncId) );
iObj = Cba_ObjAlloc( p, CBA_OBJ_BOX, Cba_NtkPiNum(pBox), Cba_NtkPoNum(pBox) );
Cba_ObjSetFunc( p, iObj, Cba_NtkId(pBox) );
// mark PO objects
Cba_NtkCleanMap2( p );
Cba_NtkForEachPo( pBox, iTerm, k )
Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 );
// map box fons
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
if ( Cba_NtkGetMap2(p, FormId) )
{
iFon = Cba_ObjFon(p, iObj, Cba_NtkGetMap2(p, FormId)-1);
Cba_FonSetName( p, iFon, ActId );
Cba_NtkSetMap( p, ActId, iFon );
}
}
}
// connect objects
Prs_NtkForEachBox( pNtk, vBox, i )
{
iObj = Cba_NtkPiNum(p) + Cba_NtkPoNum(p) + i + 1;
if ( Prs_BoxNtk(pNtk, i) == -1 ) // latch
{
assert( Cba_ObjType(p, iObj) == CBA_BOX_DFFRS );
iFon = Prs_CreateBlifFindFon( p, Vec_IntEntry(vBox, 1) ); // latch input
if ( iFon )
Cba_ObjSetFinFon( p, iObj, 0, iFon );
}
else if ( Prs_BoxIsNode(pNtk, i) ) // node
{
assert( Cba_ObjType(p, iObj) == CBA_BOX_NODE );
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
{
if ( k == 2 * Cba_ObjFinNum(p, iObj) ) // stop at node output
break;
iFon = Prs_CreateBlifFindFon( p, ActId );
if ( iFon )
Cba_ObjSetFinFon( p, iObj, k/2, iFon );
}
}
else // box
{
// mark PI objects
Cba_Ntk_t * pBox = Cba_ObjNtk(p, iObj);
assert( Cba_NtkPiNum(pBox) == Cba_ObjFinNum(p, iObj) );
assert( Cba_NtkPoNum(pBox) == Cba_ObjFonNum(p, iObj) );
Cba_NtkCleanMap2( p );
Cba_NtkForEachPi( pBox, iTerm, k )
Cba_NtkSetMap2( p, Cba_ObjName(pBox, iTerm), k+1 );
// connect box fins
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
if ( Cba_NtkGetMap2(p, FormId) )
{
iFon = Prs_CreateBlifFindFon( p, ActId );
if ( iFon )
Cba_ObjSetFinFon( p, iObj, Cba_NtkGetMap2(p, FormId)-1, iFon );
}
}
}
// connect outputs
Cba_NtkForEachPo( p, iObj, i )
{
iFon = Prs_CreateBlifFindFon( p, Cba_ObjName(p, iObj) );
if ( iFon )
Cba_ObjSetFinFon( p, iObj, 0, iFon );
}
return 0;
}
Cba_Man_t * Prs_ManBuildCbaBlif( char * pFileName, Vec_Ptr_t * vDes )
{
Prs_Ntk_t * pPrsNtk; int i, fError = 0;
Prs_Ntk_t * pPrsRoot = Prs_ManRoot(vDes);
// start the manager
Abc_Nam_t * pStrs = Abc_NamRef(pPrsRoot->pStrs);
Abc_Nam_t * pFuns = Abc_NamRef(pPrsRoot->pFuns);
Abc_Nam_t * pMods = Abc_NamStart( 100, 24 );
Cba_Man_t * p = Cba_ManAlloc( pFileName, Vec_PtrSize(vDes), pStrs, pFuns, pMods, NULL );
// initialize networks
Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i )
{
Cba_Ntk_t * pNtk = Cba_NtkAlloc( p, Prs_NtkId(pPrsNtk), Prs_NtkPiNum(pPrsNtk), Prs_NtkPoNum(pPrsNtk), Prs_NtkObjNum(pPrsNtk), 100, 100 );
Prs_CreateBlifPio( pNtk, pPrsNtk );
Cba_NtkAdd( p, pNtk );
}
// create networks
Vec_PtrForEachEntry( Prs_Ntk_t *, vDes, pPrsNtk, i )
{
printf( "Elaboration module \"%s\"...\n", Prs_NtkName(pPrsNtk) );
fError = Prs_CreateBlifNtk( Cba_ManNtk(p, i+1), pPrsNtk );
if ( fError )
break;
}
if ( fError )
printf( "Quitting because of errors.\n" );
else
Cba_ManPrepareSeq( p );
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cba_Man_t * Cba_ManReadBlif( char * pFileName )
{
Cba_Man_t * p = NULL;
Vec_Ptr_t * vDes = Prs_ManReadBlif( pFileName );
if ( vDes && Vec_PtrSize(vDes) )
p = Prs_ManBuildCbaBlif( pFileName, vDes );
if ( vDes )
Prs_ManVecFree( vDes );
return p;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

2182
src/base/cba/cbaReadVer.c Normal file

File diff suppressed because it is too large Load Diff

169
src/base/cba/cbaTypes.h Normal file
View File

@ -0,0 +1,169 @@
/**CFile****************************************************************
FileName [cbaTypes.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - July 21, 2015.]
Revision [$Id: cbaTypes.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef ABC__base__cba__cba__types_h
#define ABC__base__cba__cba__types_h
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_HEADER_START
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
// network objects
typedef enum {
CBA_OBJ_NONE = 0, // 00: unused
CBA_OBJ_PI, // 01: input
CBA_OBJ_PO, // 02: output
CBA_OBJ_BOX, // 03: box
CBA_BOX_CF, // 04:
CBA_BOX_CT, // 05:
CBA_BOX_CX, // 06:
CBA_BOX_CZ, // 07:
CBA_BOX_BUF, // 08:
CBA_BOX_INV, // 09:
CBA_BOX_AND, // 10:
CBA_BOX_NAND, // 11:
CBA_BOX_OR, // 12:
CBA_BOX_NOR, // 13:
CBA_BOX_XOR, // 14:
CBA_BOX_XNOR, // 15:
CBA_BOX_SHARP, // 16:
CBA_BOX_SHARPL, // 17:
CBA_BOX_MUX, // 18:
CBA_BOX_MAJ, // 19:
CBA_BOX_ABC, // 20:
CBA_BOX_BA, // 21:
CBA_BOX_BO, // 22:
CBA_BOX_BX, // 23:
CBA_BOX_BN, // 24:
CBA_BOX_BAO, // 25:
CBA_BOX_BOA, // 26:
CBA_BOX_RAND, // 27:
CBA_BOX_RNAND, // 28:
CBA_BOX_ROR, // 29:
CBA_BOX_RNOR, // 30:
CBA_BOX_RXOR, // 31:
CBA_BOX_RXNOR, // 32:
CBA_BOX_LNOT, // 33
CBA_BOX_LAND, // 34:
CBA_BOX_LNAND, // 35:
CBA_BOX_LOR, // 36:
CBA_BOX_LNOR, // 37:
CBA_BOX_LXOR, // 38:
CBA_BOX_LXNOR, // 39:
CBA_BOX_NMUX, // 40:
CBA_BOX_SEL, // 41:
CBA_BOX_PSEL, // 42:
CBA_BOX_ENC, // 43:
CBA_BOX_PENC, // 44:
CBA_BOX_DEC, // 45:
CBA_BOX_EDEC, // 46:
CBA_BOX_ADD, // 47:
CBA_BOX_SUB, // 48:
CBA_BOX_MUL, // 49:
CBA_BOX_SMUL, // 50:
CBA_BOX_DIV, // 51:
CBA_BOX_MOD, // 52:
CBA_BOX_REM, // 53:
CBA_BOX_POW, // 54:
CBA_BOX_MIN, // 55:
CBA_BOX_SQRT, // 56:
CBA_BOX_ABS, // 57:
CBA_BOX_SLTHAN, // 58:
CBA_BOX_LTHAN, // 59:
CBA_BOX_LETHAN, // 60:
CBA_BOX_METHAN, // 61:
CBA_BOX_MTHAN, // 62:
CBA_BOX_EQU, // 63:
CBA_BOX_NEQU, // 64:
CBA_BOX_SHIL, // 65:
CBA_BOX_SHIR, // 66:
CBA_BOX_SHILA, // 67:
CBA_BOX_SHIRA, // 68:
CBA_BOX_ROTL, // 69:
CBA_BOX_ROTR, // 70:
CBA_BOX_NODE, // 71:
CBA_BOX_LUT, // 72:
CBA_BOX_GATE, // 73:
CBA_BOX_TABLE, // 74:
CBA_BOX_TRI, // 75:
CBA_BOX_RAM, // 76:
CBA_BOX_RAMR, // 77:
CBA_BOX_RAMW, // 78:
CBA_BOX_RAMWC, // 79:
CBA_BOX_RAML, // 80:
CBA_BOX_RAMS, // 81:
CBA_BOX_RAMBOX, // 82:
CBA_BOX_LATCH, // 83:
CBA_BOX_LATCHRS, // 84:
CBA_BOX_DFF, // 85:
CBA_BOX_DFFCPL, // 86:
CBA_BOX_DFFRS, // 87:
CBA_BOX_SLICE, // 88:
CBA_BOX_CONCAT, // 89:
CBA_BOX_LAST // 90
} Cba_ObjType_t;
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// ITERATORS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_HEADER_END
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

218
src/base/cba/cbaWriteBlif.c Normal file
View File

@ -0,0 +1,218 @@
/**CFile****************************************************************
FileName [cbaWriteBlif.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Hierarchical word-level netlist.]
Synopsis [Verilog parser.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - November 29, 2014.]
Revision [$Id: cbaWriteBlif.c,v 1.00 2014/11/29 00:00:00 alanmi Exp $]
***********************************************************************/
#include "cba.h"
#include "cbaPrs.h"
#include "map/mio/mio.h"
#include "base/main/main.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Writing parser state into a file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static void Prs_ManWriteBlifArray( FILE * pFile, Prs_Ntk_t * p, Vec_Int_t * vFanins )
{
int i, NameId;
Vec_IntForEachEntry( vFanins, NameId, i )
fprintf( pFile, " %s", Prs_NtkStr(p, NameId) );
fprintf( pFile, "\n" );
}
static void Prs_ManWriteBlifLines( FILE * pFile, Prs_Ntk_t * p )
{
Vec_Int_t * vBox;
int i, k, FormId, ActId;
Prs_NtkForEachBox( p, vBox, i )
{
int NtkId = Prs_BoxNtk(p, i);
assert( Prs_BoxIONum(p, i) > 0 );
assert( Vec_IntSize(vBox) % 2 == 0 );
if ( NtkId == -1 ) // latch
{
fprintf( pFile, ".latch" );
fprintf( pFile, " %s", Prs_NtkStr(p, Vec_IntEntry(vBox, 1)) );
fprintf( pFile, " %s", Prs_NtkStr(p, Vec_IntEntry(vBox, 3)) );
fprintf( pFile, " %c\n", '0' + Prs_BoxName(p, i) );
}
else if ( Prs_BoxIsNode(p, i) ) // node
{
fprintf( pFile, ".names" );
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
fprintf( pFile, " %s", Prs_NtkStr(p, ActId) );
fprintf( pFile, "\n%s", Prs_NtkSop(p, NtkId) );
}
else // box
{
fprintf( pFile, ".subckt" );
fprintf( pFile, " %s", Prs_NtkStr(p, NtkId) );
Vec_IntForEachEntryDouble( vBox, FormId, ActId, k )
fprintf( pFile, " %s=%s", Prs_NtkStr(p, FormId), Prs_NtkStr(p, ActId) );
fprintf( pFile, "\n" );
}
}
}
static void Prs_ManWriteBlifNtk( FILE * pFile, Prs_Ntk_t * p )
{
// write header
fprintf( pFile, ".model %s\n", Prs_NtkStr(p, p->iModuleName) );
if ( Vec_IntSize(&p->vInouts) )
fprintf( pFile, ".inouts" );
if ( Vec_IntSize(&p->vInouts) )
Prs_ManWriteBlifArray( pFile, p, &p->vInouts );
fprintf( pFile, ".inputs" );
Prs_ManWriteBlifArray( pFile, p, &p->vInputs );
fprintf( pFile, ".outputs" );
Prs_ManWriteBlifArray( pFile, p, &p->vOutputs );
// write objects
Prs_ManWriteBlifLines( pFile, p );
fprintf( pFile, ".end\n\n" );
}
void Prs_ManWriteBlif( char * pFileName, Vec_Ptr_t * vPrs )
{
Prs_Ntk_t * pNtk = Prs_ManRoot(vPrs);
FILE * pFile = fopen( pFileName, "wb" ); int i;
if ( pFile == NULL )
{
printf( "Cannot open output file \"%s\".\n", pFileName );
return;
}
fprintf( pFile, "# Design \"%s\" written by ABC on %s\n\n", Prs_NtkStr(pNtk, pNtk->iModuleName), Extra_TimeStamp() );
Vec_PtrForEachEntry( Prs_Ntk_t *, vPrs, pNtk, i )
Prs_ManWriteBlifNtk( pFile, pNtk );
fclose( pFile );
}
/**Function*************************************************************
Synopsis [Write elaborated design.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Cba_ManWriteBlifLines( FILE * pFile, Cba_Ntk_t * p )
{
int k, iObj, iFin, iFon;
Cba_NtkForEachBox( p, iObj )
{
if ( Cba_ObjIsBoxUser(p, iObj) )
{
Cba_Ntk_t * pNtk = Cba_ObjNtk( p, iObj );
fprintf( pFile, ".subckt" );
fprintf( pFile, " %s", Cba_NtkName(pNtk) );
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k )
fprintf( pFile, " %s=%s", Cba_ObjNameStr(pNtk, Cba_NtkPi(pNtk, k)), Cba_FonNameStr(p, iFon) );
Cba_ObjForEachFon( p, iObj, iFon, k )
fprintf( pFile, " %s=%s", Cba_ObjNameStr(pNtk, Cba_NtkPo(pNtk, k)), Cba_FonNameStr(p, iFon) );
fprintf( pFile, "\n" );
}
else if ( Cba_ObjIsGate(p, iObj) )
{
char * pGateName = Abc_NamStr(p->pDesign->pMods, Cba_ObjNtkId( p, iObj ));
Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen();
Mio_Gate_t * pGate = Mio_LibraryReadGateByName( pLib, pGateName, NULL );
fprintf( pFile, ".gate %s", pGateName );
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k )
fprintf( pFile, " %s=%s", Mio_GateReadPinName(pGate, k), Cba_FonNameStr(p, iFon) );
Cba_ObjForEachFon( p, iObj, iFon, k )
fprintf( pFile, " %s=%s", Mio_GateReadOutName(pGate), Cba_FonNameStr(p, iFon) );
fprintf( pFile, "\n" );
}
else
{
fprintf( pFile, ".names" );
Cba_ObjForEachFinFon( p, iObj, iFin, iFon, k )
fprintf( pFile, " %s", Cba_FonNameStr(p, iFon) );
fprintf( pFile, " %s", Cba_FonNameStr(p, Cba_ObjFon0(p, iObj)) );
fprintf( pFile, "\n%s", Cba_NtkSop(p, Cba_ObjFunc(p, iObj)) );
}
}
}
void Cba_ManWriteBlifArray( FILE * pFile, Cba_Ntk_t * p, Vec_Int_t * vObjs )
{
int iObj, i;
Vec_IntForEachEntry( vObjs, iObj, i )
fprintf( pFile, " %s", Cba_ObjNameStr(p, iObj) );
fprintf( pFile, "\n" );
}
void Cba_ManWriteBlifNtk( FILE * pFile, Cba_Ntk_t * p )
{
// write header
fprintf( pFile, ".model %s\n", Cba_NtkName(p) );
fprintf( pFile, ".inputs" );
Cba_ManWriteBlifArray( pFile, p, &p->vInputs );
fprintf( pFile, ".outputs" );
Cba_ManWriteBlifArray( pFile, p, &p->vOutputs );
// write objects
Cba_ManWriteBlifLines( pFile, p );
fprintf( pFile, ".end\n\n" );
}
void Cba_ManWriteBlif( char * pFileName, Cba_Man_t * p )
{
FILE * pFile;
Cba_Ntk_t * pNtk;
int i;
// check the library
if ( p->pMioLib && p->pMioLib != Abc_FrameReadLibGen() )
{
printf( "Genlib library used in the mapped design is not longer a current library.\n" );
return;
}
pFile = fopen( pFileName, "wb" );
if ( pFile == NULL )
{
printf( "Cannot open output file \"%s\".\n", pFileName );
return;
}
fprintf( pFile, "# Design \"%s\" written via CBA package in ABC on %s\n\n", Cba_ManName(p), Extra_TimeStamp() );
// Cba_ManAssignInternWordNames( p );
Cba_ManForEachNtk( p, pNtk, i )
Cba_ManWriteBlifNtk( pFile, pNtk );
fclose( pFile );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END

1016
src/base/cba/cbaWriteVer.c Normal file

File diff suppressed because it is too large Load Diff

8
src/base/cba/module.make Normal file
View File

@ -0,0 +1,8 @@
SRC += src/base/cba/cbaBlast.c \
src/base/cba/cbaCba.c \
src/base/cba/cbaCom.c \
src/base/cba/cbaNtk.c \
src/base/cba/cbaReadBlif.c \
src/base/cba/cbaReadVer.c \
src/base/cba/cbaWriteBlif.c \
src/base/cba/cbaWriteVer.c

View File

@ -53,8 +53,10 @@ extern void Wlc_Init( Abc_Frame_t * pAbc );
extern void Wlc_End( Abc_Frame_t * pAbc ); extern void Wlc_End( Abc_Frame_t * pAbc );
extern void Wln_Init( Abc_Frame_t * pAbc ); extern void Wln_Init( Abc_Frame_t * pAbc );
extern void Wln_End( Abc_Frame_t * pAbc ); extern void Wln_End( Abc_Frame_t * pAbc );
extern void Sn_Init( Abc_Frame_t * pAbc ); extern void Bac_Init( Abc_Frame_t * pAbc );
extern void Sn_End( Abc_Frame_t * pAbc ); extern void Bac_End( Abc_Frame_t * pAbc );
extern void Cba_Init( Abc_Frame_t * pAbc );
extern void Cba_End( Abc_Frame_t * pAbc );
extern void Pla_Init( Abc_Frame_t * pAbc ); extern void Pla_Init( Abc_Frame_t * pAbc );
extern void Pla_End( Abc_Frame_t * pAbc ); extern void Pla_End( Abc_Frame_t * pAbc );
extern void Sim_Init( Abc_Frame_t * pAbc ); extern void Sim_Init( Abc_Frame_t * pAbc );
@ -121,7 +123,8 @@ void Abc_FrameInit( Abc_Frame_t * pAbc )
Emap_Init( pAbc ); Emap_Init( pAbc );
Wlc_Init( pAbc ); Wlc_Init( pAbc );
Wln_Init( pAbc ); Wln_Init( pAbc );
Sn_Init( pAbc ); Bac_Init( pAbc );
Cba_Init( pAbc );
Pla_Init( pAbc ); Pla_Init( pAbc );
Test_Init( pAbc ); Test_Init( pAbc );
Ufar_Init( pAbc ); Ufar_Init( pAbc );
@ -163,7 +166,8 @@ void Abc_FrameEnd( Abc_Frame_t * pAbc )
Scl_End( pAbc ); Scl_End( pAbc );
Wlc_End( pAbc ); Wlc_End( pAbc );
Wln_End( pAbc ); Wln_End( pAbc );
Sn_End( pAbc ); Bac_End( pAbc );
Cba_End( pAbc );
Pla_End( pAbc ); Pla_End( pAbc );
Test_End( pAbc ); Test_End( pAbc );
Glucose_End( pAbc ); Glucose_End( pAbc );
@ -176,3 +180,4 @@ void Abc_FrameEnd( Abc_Frame_t * pAbc )
ABC_NAMESPACE_IMPL_END ABC_NAMESPACE_IMPL_END

View File

@ -149,7 +149,8 @@ struct Abc_Frame_t_
void * pAbcWlc; void * pAbcWlc;
Vec_Int_t * pAbcWlcInv; Vec_Int_t * pAbcWlcInv;
void * pAbcRtl; void * pAbcRtl;
void * pAbcSn; void * pAbcBac;
void * pAbcCba;
void * pAbcPla; void * pAbcPla;
Abc_Nam_t * pJsonStrs; Abc_Nam_t * pJsonStrs;
Vec_Wec_t * vJsonObjs; Vec_Wec_t * vJsonObjs;

View File

@ -1 +0,0 @@
SRC += src/base/sn/snCom.c

View File

@ -1,253 +0,0 @@
# Simple Netlist in ABC
This directory contains the Slang-independent Simple Netlist (SN) representation and algorithms.
The external `sn_slang` executable parses and elaborates Verilog/SystemVerilog using Mike Popoloski's excellent
[slang SystemVerilog compiler](https://github.com/MikePopoloski/slang) and writes a binary `.sn` design. ABC does
not link slang or require its C++20 dependencies.
The frontend architecture benefited from [yosys-slang](https://github.com/povik/yosys-slang), developed by
Martin Povišer. It has been both an inspiration and a helpful practical guideline for working from slang's
elaborated model, particularly for lvalue analysis, procedural state, timing patterns, memory eligibility, resolved
nets, and diagnostics. The SN representation and lowering are independently developed, with warm thanks to Martin
for his work and advice.
ABC holds the SN design and the `&`-space GIA as independent representations. Commands move data between them only
when explicitly requested:
| Command | Reads | Writes |
| --- | --- | --- |
| `@slang`, `@read` | HDL or `.sn` | Current SN design |
| `@map_*`, `@opt_mux`, `@collapse` | SN | New SN design revision |
| `@blast` | SN | Current `&`-space GIA plus a saved boundary |
| `&...` commands | GIA | GIA |
| `@put` | GIA plus saved boundary | Module selected by the preceding `@blast` |
| `@write` | SN | `.sn` or Verilog |
`@status` reports both representations, the monotonically increasing SN revision, and whether the saved boundary is
compatible with the current SN design and GIA. In particular, reading or transforming SN does not clear or update an
old `&`-space network; it makes that network unavailable for `@put` until another combinational `@blast` records a
matching boundary.
## Commands
The commands appear under `New word level commands` in ABC's `help` output.
```text
set snslang /path/to/sn_slang
@slang -M top rtl1.sv rtl2.sv
@status
@check
@ps -v
@map_mem -v
@check
@map_dsp -v
@check
@map_add -v
@check
@opt_mux -v
@check
@blast -M top -c -v
&resyn3
&if -m -K 6
&ps
@status
@put -v
@check
@collapse -v
@check
@write mapped_logic.v
@write mapped_logic.sn
```
`@slang` uses `sn_slang` from `PATH` unless the `snslang` setting overrides it. It accepts `-M` for the top module,
repeatable `-D NAME` or `-D NAME=value` preprocessor definitions, `-F` for one additional source file, and any number
of positional source files. For example, `-D WIDTH=8 -D SIGNED=1` defines two macros. `-T` is not used because ABC
conventionally reserves it for a time limit. `-v` prints the external command and frontend timing. A module declared
inside SystemVerilog `` `celldefine`` / `` `endcelldefine``, or marked by a nonzero `black_box` or `syn_black_box`
module attribute, is imported as an opaque technology primitive with its elaborated PI/PO interface; its simulation
body is not lowered. For example, both `` `celldefine`` around a module definition and
`(* syn_black_box = 1 *) module macro (...);` create an opaque leaf. An explicit zero or false attribute does not.
The declaration is still required: slang must know every port's name, direction, width, and signedness, so an
undefined-module inst remains an error. Undefined-module patterns and include-directory options remain unsupported.
`@read` and `@write` provide binary persistence. `@write` selects SN or Verilog output from the `.sn`, `.v`, or
`.sv` extension. `@read -M module` selects the top stored in a multi-top design; otherwise the last top is used.
Before installing external binary data, `@read` validates the encoding and runs the same non-aborting structural and
semantic checks as `@check`. A failed `@write` removes its incomplete output file. Every design installed in ABC is
topologically ordered. The current writer emits binary format version 6; the reader also accepts version 5 and treats
its modules as ordinary non-black-box modules because that format predates module flags.
`@status` prints the current design and top names, SN revision, selected technology, hierarchy form, last extraction
mode/module/revision, saved boundary hash, current GIA dimensions, and `@put` compatibility. A new `@read` or `@slang`
design starts at revision 1. Each transformation that installs a replacement SN design, and each successful `@put`,
advances the revision; `&` commands do not. An optimization that finds no profitable rewrite leaves the design and its
revision unchanged.
`@blast` gives every GIA input and output a unique ordered name containing the retained SN signal name, bit index, and
interface index. It also hashes the selected module identity and all saved boundary occurrences, primitives, registers,
loops, and input/output endpoint records. Before insertion, `@put` verifies the SN revision, module ID and name,
boundary hash, GIA dimensions, and ordered GIA-name signature. It rejects a GIA whose interface was reordered, renamed,
or stripped of names, even if its input and output counts still match. The GIA must also remain combinational, with zero
registers. Normal interface-preserving `&` synthesis commands retain the names and remain compatible.
MiniAIG has only an edge-triggered register convention. Therefore `@blast` and `@map_lut` explicitly reject any
level-sensitive `SN_REG_LATCH` reachable from the selected module until a semantics-preserving latch flow is available.
`@check` performs a non-aborting consistency audit of the complete SN design. It validates core and type-specific
attribute vectors, fanin storage, object IDs, widths, names, constants, topology, state pairing, memory-port ownership,
instance/FAN ordering, hierarchy recursion, LUTs, gates, and mapped primitive interfaces. `@check -v` adds one summary
line per module. Memory, DSP, and carry mapping commands run the same checker transactionally before and after each
transformation, so an invalid result is diagnosed and rejected without replacing the current design.
`@ps` prints compact statistics for every module definition by default. `@ps -M module` prints the selected module
instead and uses it as the root for optional hierarchy and detailed reports. `@ps -v` adds the selected hierarchy and
keeps opaque definitions annotated with `[blackbox]`. Like `%ps -d`, `@ps -d` prints occurrences by object type and
output/input width signature. It also reports every reachable black-box type, its instance-occurrence multiplicity,
PI/PO port and bit counts, and totals for abstract AIG inputs and outputs. Counts cover the elaborated hierarchy rooted
at the selected module (or the current design top when `-M` is absent), including repeated insts. Hierarchical totals
are accumulated over the module DAG rather than by recursively revisiting every inst, so statistics remain practical
for deeply repeated hierarchy. Memory is reported as used/allocated storage with rounded K, M, or G suffixes.
`@map_mem`, `@map_dsp`, and `@map_add` map into the initial AMD/Xilinx UltraScale+ technology description.
Transformations are transactional and keep the original user-visible top-module name. `@map_add` replaces word-level
addition and subtraction of at least three bits by chains of behavioral `__sn_CARRY4` primitive insts. Propagate,
operand inversion, extension, and final slicing remain ordinary SN logic for subsequent LUT mapping. Run DSP mapping
before carry mapping so future DSP preadder and postadder recognition is not hidden. `@collapse` flattens user hierarchy
while retaining mapped hard-block leaf instances.
Opaque `SN_MODULE_BLACKBOX` insts are preserved by hierarchy collapse even when ordinary user hierarchy is flattened.
During `@blast`, each opaque output is an additional GIA input and each opaque input is an additional GIA output, in
natural port and LSB-first bit order. A black-box `SN_PO` has `SN_INVALID_ID` as its sole fanin, explicitly recording
that its value has no SN implementation; no zero-valued placeholder is created. `@write` emits the preserved interface
as a port-only `(* blackbox *)` module. Internally an opaque module contains only its declared `SN_PI` and `SN_PO`
objects; an `inout` is a same-named PI/PO pair. Its body and descendants are absent from SN. `@check` permits the
invalid PO fanin only for this boundary representation, and `@ps -v` / `@ps -d` expose the retained black boxes and
their reachable occurrence counts.
`SN_CAST` is a one-fanin operator whose object width and signedness define the result type. It does not permute bits.
An equal-width cast only changes the signedness annotation; widening sign-extends a signed result and zero-extends an
unsigned result; narrowing discards high bits and retains the LSB-first low-order portion. `sn_slang` adds casts for
explicit and implicit slang conversions, `$signed` / `$unsigned`, dynamic selected-value normalization, packed-value
updates, and final normalization of `SN_MUX` data branches to the mux result width. Memory, DSP, and carry mapping may
also introduce casts while adapting word-level values to primitive interfaces. The Verilog writer uses `$signed` or
`$unsigned` on a result-width wire, and the bit-blaster implements the same extension or truncation directly.
`@opt_mux` restructures register mux cones by collecting root-to-terminal paths, grouping structurally identical
LSB-first word values, and ORing the corresponding path conditions. A register-output terminal is converted into an
explicit enable when the path controls are provably exclusive. The pass currently recognizes ordinary `SN_MUX`
trees and packed `SN_PMUX` alternatives; separately created casts, slices, repetitions, concatenations, and constants
are compared structurally. Rewritten modules are restored at their stable hierarchy IDs and retain every register
pair so that the canonical transition interface remains unchanged. The default profitability filter requires at
least 4-bit data, six paths, two eliminated paths, and a path-to-distinct-terminal ratio of at least 2:1. This avoids
increasing logic for narrow control muxes while retaining the intended wide datapath transformations.
`@blast` traverses hierarchy directly without first allocating a flat SN module. Sequential extraction is the
default; `-c` selects combinational extraction. `-t` emits the same effective next-state functions as a purely
combinational transition AIG for equivalence checking.
`-M module` selects the module to
extract; the default is the current SN top. ABC records the selected module and the exact LSB-first boundary mapping,
then installs the resulting GIA as the current `&` network. The user may apply any `&`-space combinational synthesis
and mapping commands that preserve the number and order of combinational inputs and outputs. Nothing requires the
logic to be put back into SN: omitting `@put` leaves the SN design unchanged.
Adders use a Brent-Kung parallel-prefix network by default. `@blast -r` selects ripple-carry adders instead. This
choice also applies to adder networks used while blasting subtraction and other arithmetic operators; `-b` separately
selects Booth rather than the direct-unsigned/Baugh-Wooley multiplier. Signed and unsigned relational operators use
a balanced, delay-oriented comparator by default; `@blast -d` toggles to the minimum-node topology implemented by ABC's
`&gencomp`. Equality comparison remains balanced in both modes. Ripple adders and multiplier compressor trees share
the seven-node full-adder construction from `Wlc_BlastFullAdder()`. Direct unsigned, signed Baugh-Wooley, and radix-4
Booth partial products use the delay-aware, level-ordered matrix reduction adapted from `Wlc_BlastReduceMatrix()`,
followed by the selected Brent-Kung or ripple final adder. The radix-4 Booth recoding, signed correction, rectangular
operand handling, and unsigned zero extension follow `Wlc_BlastBooth()`. Binary mux trees use `Mini_AigMuxMulti()`,
while AND/OR reductions and equality aggregation use balanced `Mini_AigAndMulti()` trees over copied temporary
literals. One-hot priority muxes use a balanced sum-of-products tree; their result for a multi-hot select remains
intentionally undefined. Variable shifts instantiate only the useful barrel stages and combine all higher shift bits
into one balanced overshift condition.
Unnamed constants are interned by width, signedness, and packed value within each module. Concatenations whose inputs
are all constant are folded into one packed `SN_CONST`, including tables wider than the per-object fanin-count limit.
When such a constant drives an `SN_BMUX`, blasting reads one output-bit column at a time and simplifies constant and
equal mux branches before creating MiniAIG nodes; it never materializes the complete packed table as an integer-literal
array. The Verilog writer splits very large constants into bounded-size hexadecimal concatenation chunks.
In combinational mode (`@blast -c`), flop outputs become additional inputs, while raw data and synchronous control
inputs become separate outputs for later stitching; clock and asynchronous controls remain outside this boundary.
Mapped RAM/DSP and CARRY4 outputs and inputs are likewise exposed as additional cloud endpoints. `@put` checks the saved
interface and reconnects registers and mapped primitive instances. With the default sequential `@blast`, the AIG
transition functions elaborate synchronous reset, set, and enable controls in SN priority order; clock and asynchronous
controls remain outside the transition relation. Sequential-AIG insertion is deliberately rejected for now.
`@map_lut` applies this combinational extraction and reconstruction module by module while preserving the natural SN
hierarchy. Child instances, registers, and mapped RAM/DSP/CARRY4 instances are partition boundaries, matching the broad
structure of Yosys's per-module ABC flow. `@map_lut -S "&resyn3; &if -m -K 6"` supplies an inline per-partition ABC
script; `-F script.abc` sources it from a file. The default is the same `&resyn3; &if -m -K 6` sequence. Every script
must preserve CI/CO order and leave a LUT-mapped GIA. Generic-memory modules left unsupported by `@map_mem` remain
unchanged and are reported as skipped partitions. Mapped nodes wider than the physical SN LUT6 primitive are
decomposed deterministically by Shannon expansion. The pass maps a duplicate design and commits it only after every
reachable non-primitive module succeeds. `-P num` runs the independent partition jobs concurrently using `num - 1`
pthread workers and one coordinating process. `-P 1` uses the current ABC process directly, so its last partition
becomes the current `&`-space GIA; use `-P 2` or more when the preexisting `&`-space network must remain untouched.
SN pthread support is compiled out on Windows, where `-P 1` remains fully supported and larger values are rejected.
`@map_lut -E prefix` stops at the same partition boundary, writes each nontrivial job as
`prefix_<module-id>_<module-name>.aig` with a `.txt` interface-statistics sidecar, and does not run synthesis or modify
the SN design. This mode cannot be combined with `-S` or `-F`, currently requires `-P 1`, and is intended for
developing or benchmarking an external per-partition synthesis flow.
Generated clock and asynchronous-control cones remain outside the mapped cloud and are copied with per-occurrence
memoization when registers are reconnected.
The transition AIG orders state bits canonically by depth-first natural instance type ID, natural `SN_REG_OUT` type
ID within each occurrence, and LSB-first bit index. Both hierarchy duplication and mux sharing preserve these IDs.
Consequently, the transition AIGs made before and after `@opt_mux` have identical CI/CO order and can be compared
directly with `&cec before.aig after.aig`. For large, structurally different cones, explicitly constructing the miter
is often much faster: `&r before.aig; &miter after.aig; &cec -m`. Transition-AIG insertion through `@put` is
deliberately rejected.
`@put` replaces only the module selected by the preceding `@blast`. Its module ID, name, and port interface remain
stable, so parent instances and every other module in an uncollapsed hierarchical design are preserved. The current
GIA determines the reconstructed representation:
- An unmapped GIA becomes explicit one-bit `SN_BIT_AND` and `SN_BIT_NOT` objects.
- A LUT-mapped GIA becomes `SN_LUT` objects with truth tables transferred through MiniLUT.
- A cell-mapped GIA becomes `SN_GATE` objects annotated with current genlib gate IDs and cell names through ABC's
mini-mapping format. Insertion requires the current genlib to contain every referenced gate.
For example, `@blast -c; &resyn3; &if -m -K 6; @put` implements the former canned LUT-mapping flow without hiding
the ABC script. `@blast -c; &dc2; @put` reinserts an optimized unmapped AIG, while
`read_genlib library.genlib; @blast -c; &nf; @put` reinserts standard cells. The Verilog writer emits LUT and gate
instances as well as ordinary SN logic.
Mapped RAM/DSP/CARRY4 instances are reconstructed as technology leaf instances. SN loop-breaker pairs connect their
output ports while the new flat module is built and are placed into a legal order by the final topological reorder.
Temporary primitive-output loop pairs are pruned after reconnection unless an actual feedback dependency remains, so
acyclic datapaths do not gain artificial loop-breakers. Explicit loop boundaries extracted from the original SN module
are reconstructed unchanged; they are not currently re-proved unnecessary after `&`-space optimization. Generic
unmapped memory endpoints are recorded and abstracted by `@blast`, but `@put` currently rejects them because the
boundary does not yet retain enough per-memory-port ownership data. This check prevents silent loss or misconnection
of stateful memories.
## Source files
The package uses ABC-style filenames:
```text
sn.h core representation, hierarchy, serialization, and Verilog writer
snCheck.h non-aborting design, module, hierarchy, and technology-interface consistency checker
snTech.h target technology descriptions
snMapMem.h memory mapping support
snMapDsp.h DSP mapping support
snMapAdd.h CARRY4 mapping support
snMapTech.h combined hierarchy mapping
snMapLut.h natural-hierarchy LUT-mapping harness
snPth.h bounded pthread worker harness
snBlast.h direct hierarchical MiniAIG construction
snMux.h register mux-path sharing and restructuring
snBoundary.h saved boundary and combinational register reconnection
snMiniAig.h unmapped MiniAIG reconstruction
snMiniLut.h MiniLUT analysis and SN_LUT reconstruction
snMiniGate.h mini-mapping and SN_GATE reconstruction
snCom.c ABC manager ownership and command handlers
```
The external frontend must compile against this directory through a configured include path. Representation changes
are made here first and must update the binary-format version when serialization compatibility changes.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,874 +0,0 @@
/**CFile****************************************************************
FileName [snBoundary.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Reconstruction and reconnection of extracted combinational boundaries.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snBoundary.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef ABC__base__sn__snBoundary_h
#define ABC__base__sn__snBoundary_h
#include "snBlast.h"
ABC_NAMESPACE_HEADER_START
typedef struct sn_boundary_regs_t
{
sn_design_t* design;
const sn_blast_boundary_t* boundary;
sn_module_t* result;
sn_obj_id_t* top_inputs;
sn_obj_pair_t* pairs;
sn_obj_pair_t* loops;
sn_obj_pair_t* primitive_pairs;
uint32_t* primitive_offsets;
sn_obj_id_t** external_copies;
struct sn_boundary_link_t* links;
size_t link_cap;
} sn_boundary_regs_t;
typedef struct sn_boundary_link_t
{
uint64_t key;
uint32_t primitive;
uint32_t child;
uint32_t reg;
uint32_t loop;
} sn_boundary_link_t;
typedef struct sn_boundary_external_frame_t
{
sn_blast_hier_ref_t ref;
sn_blast_hier_ref_t dependency;
sn_obj_id_t result;
uint32_t next_fanin;
uint8_t phase;
} sn_boundary_external_frame_t;
enum
{
SN_BOUNDARY_EXTERNAL_START,
SN_BOUNDARY_EXTERNAL_ALIAS,
SN_BOUNDARY_EXTERNAL_OPERATOR
};
static inline uint64_t sn_boundary_link_key(uint32_t occurrence, sn_obj_id_t object)
{
return ((uint64_t)occurrence << 32) | object;
}
static inline size_t sn_boundary_link_hash(uint64_t key, size_t mask)
{
key ^= key >> 33;
key *= UINT64_C(0xff51afd7ed558ccd);
key ^= key >> 33;
return (size_t)key & mask;
}
static inline sn_boundary_link_t* sn_boundary_link_find(sn_boundary_regs_t* regs, uint32_t occurrence,
sn_obj_id_t object, bool create)
{
if (!regs->link_cap)
return NULL;
uint64_t key = sn_boundary_link_key(occurrence, object);
size_t slot = sn_boundary_link_hash(key, regs->link_cap - 1);
while (regs->links[slot].key != UINT64_MAX && regs->links[slot].key != key)
slot = (slot + 1) & (regs->link_cap - 1);
if (regs->links[slot].key == UINT64_MAX)
{
if (!create)
return NULL;
regs->links[slot].key = key;
}
return &regs->links[slot];
}
static inline sn_obj_id_t* sn_boundary_external_copies(sn_boundary_regs_t* regs, sn_blast_hier_ref_t ref,
const sn_module_t** returned_module)
{
const sn_blast_occurrence_t* occurrence =
&sn_vec_at(sn_blast_occurrence_t, &regs->boundary->occurrences, ref.occurrence);
const sn_module_t* module = sn_design_get_module_const(regs->design, occurrence->module);
sn_obj_id_t* copies = regs->external_copies[ref.occurrence];
assert(ref.object < module->obj_types.size);
if (!copies)
{
copies = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * module->obj_types.size);
assert(copies);
for (size_t i = 0; i < module->obj_types.size; i++)
copies[i] = SN_INVALID_ID;
regs->external_copies[ref.occurrence] = copies;
}
if (returned_module)
*returned_module = module;
return copies;
}
static inline sn_obj_id_t sn_boundary_pack_bits(sn_module_t* module, const sn_obj_id_t* bits, uint32_t width,
const char* name)
{
assert(module && bits && width);
return width == 1 ? bits[0] : sn_module_add_operator(module, SN_CONCAT, width, false, width, bits, name);
}
static inline sn_blast_hier_ref_t sn_boundary_parent_ref(const sn_design_t* design,
const sn_blast_boundary_t* boundary,
sn_blast_hier_ref_t ref)
{
const sn_blast_occurrence_t* occurrence;
const sn_module_t* module;
const sn_module_t* parent;
sn_obj_id_t parent_fanin;
assert(ref.occurrence < boundary->occurrences.size);
occurrence = &sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, ref.occurrence);
module = sn_design_get_module_const(design, occurrence->module);
assert(sn_obj_type(module, ref.object) == SN_PI && occurrence->parent_occurrence != SN_INVALID_ID);
parent = sn_design_get_module_const(
design, sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, occurrence->parent_occurrence).module);
parent_fanin = sn_obj_fanin(parent, occurrence->parent_inst, sn_obj_type_id(module, ref.object));
ref.occurrence = occurrence->parent_occurrence;
ref.object = parent_fanin;
return ref;
}
// Resolves clocks, asynchronous controls, and initialization constants that @blast intentionally leaves outside the
// combinational cloud. Hierarchical PI bindings are followed to the root. Generated combinational control cones are
// copied and memoized per hierarchy occurrence; an explicit DFS stack avoids overflowing the C stack on deep control
// cones. The link table resolves inst, primitive, register, and loop endpoints in expected constant time.
static inline sn_obj_id_t sn_boundary_resolve_external(sn_boundary_regs_t* regs, sn_blast_hier_ref_t ref)
{
sn_blast_hier_ref_t root = ref;
sn_vec_t stack;
sn_vec_init(&stack);
sn_boundary_external_frame_t* initial = sn_vec_push(sn_boundary_external_frame_t, &stack);
memset(initial, 0, sizeof(*initial));
initial->ref = ref;
while (stack.size)
{
sn_boundary_external_frame_t* frame =
&sn_vec_at(sn_boundary_external_frame_t, &stack, stack.size - 1);
ref = frame->ref;
const sn_blast_occurrence_t* occurrence =
&sn_vec_at(sn_blast_occurrence_t, &regs->boundary->occurrences, ref.occurrence);
const sn_module_t* module;
sn_obj_id_t* copies = sn_boundary_external_copies(regs, ref, &module);
if (frame->phase == SN_BOUNDARY_EXTERNAL_ALIAS)
{
const sn_module_t* dependency_module;
sn_obj_id_t* dependency_copies =
sn_boundary_external_copies(regs, frame->dependency, &dependency_module);
(void)dependency_module;
assert(dependency_copies[frame->dependency.object] != SN_INVALID_ID);
copies[ref.object] = dependency_copies[frame->dependency.object];
stack.size--;
continue;
}
if (frame->phase == SN_BOUNDARY_EXTERNAL_OPERATOR)
{
uint32_t count = sn_obj_fanin_count(module, ref.object);
if (frame->next_fanin == count)
{
stack.size--;
continue;
}
uint32_t index = frame->next_fanin;
sn_obj_id_t old_fanin = sn_obj_fanin(module, ref.object, index);
if (old_fanin == SN_INVALID_ID)
{
sn_obj_connect(regs->result, frame->result, index, SN_INVALID_ID);
frame->next_fanin++;
continue;
}
sn_blast_hier_ref_t dependency = {ref.occurrence, old_fanin, 0};
sn_obj_id_t* dependency_copies = sn_boundary_external_copies(regs, dependency, NULL);
if (dependency_copies[old_fanin] != SN_INVALID_ID)
{
sn_obj_connect(regs->result, frame->result, index, dependency_copies[old_fanin]);
frame->next_fanin++;
continue;
}
sn_boundary_external_frame_t* child = sn_vec_push(sn_boundary_external_frame_t, &stack);
memset(child, 0, sizeof(*child));
child->ref = dependency;
continue;
}
if (copies[ref.object] != SN_INVALID_ID)
{
stack.size--;
continue;
}
sn_obj_type_t type = sn_obj_type(module, ref.object);
if (type == SN_PI && occurrence->parent_occurrence != SN_INVALID_ID)
{
frame->phase = SN_BOUNDARY_EXTERNAL_ALIAS;
frame->dependency = sn_boundary_parent_ref(regs->design, regs->boundary, ref);
sn_obj_id_t* dependency_copies = sn_boundary_external_copies(regs, frame->dependency, NULL);
if (dependency_copies[frame->dependency.object] == SN_INVALID_ID)
{
sn_boundary_external_frame_t* child = sn_vec_push(sn_boundary_external_frame_t, &stack);
memset(child, 0, sizeof(*child));
child->ref = frame->dependency;
}
continue;
}
if (type == SN_PI)
{
assert(ref.occurrence == 0 && regs->top_inputs[ref.object] != SN_INVALID_ID);
copies[ref.object] = regs->top_inputs[ref.object];
stack.size--;
continue;
}
if (type == SN_INST || type == SN_FAN)
{
sn_obj_id_t inst = type == SN_INST ? ref.object : sn_fan_inst_id(module, ref.object);
uint32_t output = type == SN_INST ? 0 : sn_fan_output_index(module, ref.object);
sn_boundary_link_t* link = sn_boundary_link_find(regs, ref.occurrence, inst, false);
assert(link);
if (link->primitive != SN_INVALID_ID)
{
const sn_blast_primitive_t* primitive =
&sn_vec_at(sn_blast_primitive_t, &regs->boundary->primitives, link->primitive);
assert(output < sn_design_module_output_count(regs->design, primitive->module));
(void)primitive;
copies[ref.object] = regs->primitive_pairs[regs->primitive_offsets[link->primitive] + output].out;
stack.size--;
continue;
}
if (link->child != SN_INVALID_ID)
{
const sn_blast_occurrence_t* child_occurrence =
&sn_vec_at(sn_blast_occurrence_t, &regs->boundary->occurrences, link->child);
const sn_module_t* child = sn_design_get_module_const(regs->design, child_occurrence->module);
assert(output < child->type_objects[SN_PO].size);
sn_obj_id_t child_po = sn_vec_at(sn_obj_id_t, &child->type_objects[SN_PO], output);
sn_obj_id_t child_fanin = sn_obj_fanin(child, child_po, 0);
assert(child_fanin != SN_INVALID_ID);
frame->phase = SN_BOUNDARY_EXTERNAL_ALIAS;
frame->dependency.occurrence = link->child;
frame->dependency.object = child_fanin;
frame->dependency.bit = 0;
sn_obj_id_t* dependency_copies = sn_boundary_external_copies(regs, frame->dependency, NULL);
if (dependency_copies[child_fanin] == SN_INVALID_ID)
{
sn_boundary_external_frame_t* child_frame =
sn_vec_push(sn_boundary_external_frame_t, &stack);
memset(child_frame, 0, sizeof(*child_frame));
child_frame->ref = frame->dependency;
}
continue;
}
assert(false);
}
if (type == SN_CONST0 || type == SN_CONST1 || type == SN_CONST)
{
uint32_t width = sn_obj_width(module, ref.object);
uint32_t* words = (uint32_t*)calloc(sn_const_word_count(width), sizeof(uint32_t));
assert(words);
for (uint32_t bit = 0; bit < width; bit++)
words[bit >> 5] |= (uint32_t)sn_const_bit(module, ref.object, bit) << (bit & 31);
const char* name = sn_obj_name_id(module, ref.object) == SN_INVALID_ID
? NULL
: sn_obj_name(module, ref.object);
sn_obj_id_t result = sn_module_add_const(regs->result, width, sn_obj_is_signed(module, ref.object), words,
name);
free(words);
copies[ref.object] = result;
stack.size--;
continue;
}
if (type == SN_REG_OUT)
{
sn_boundary_link_t* link = sn_boundary_link_find(regs, ref.occurrence, ref.object, false);
assert(link && link->reg != SN_INVALID_ID);
copies[ref.object] = regs->pairs[link->reg].out;
stack.size--;
continue;
}
if (type == SN_LOOP_OUT)
{
sn_boundary_link_t* link = sn_boundary_link_find(regs, ref.occurrence, ref.object, false);
assert(link && link->loop != SN_INVALID_ID);
copies[ref.object] = regs->loops[link->loop].out;
stack.size--;
continue;
}
assert(type == SN_BUF || (type >= SN_POS && type <= SN_GATE));
frame->result = sn_module_dup_obj_skeleton(regs->result, module, ref.object);
copies[ref.object] = frame->result;
sn_module_dup_obj_metadata(regs->result, sn_obj_type_id(regs->result, frame->result), module, ref.object);
frame->phase = SN_BOUNDARY_EXTERNAL_OPERATOR;
frame->next_fanin = 0;
}
sn_obj_id_t* root_copies = sn_boundary_external_copies(regs, root, NULL);
assert(root_copies[root.object] != SN_INVALID_ID);
sn_obj_id_t result = root_copies[root.object];
sn_vec_destroy(&stack);
return result;
}
static inline void sn_boundary_regs_init(sn_boundary_regs_t* regs, sn_design_t* design,
const sn_blast_boundary_t* boundary, sn_module_t* result,
sn_obj_id_t* top_inputs)
{
assert(regs && design && boundary && result && top_inputs);
regs->design = design;
regs->boundary = boundary;
regs->result = result;
regs->top_inputs = top_inputs;
regs->external_copies = boundary->occurrences.size
? (sn_obj_id_t**)calloc(boundary->occurrences.size, sizeof(sn_obj_id_t*))
: NULL;
assert(regs->external_copies || boundary->occurrences.size == 0);
regs->links = NULL;
regs->link_cap = 0;
regs->primitive_offsets = boundary->primitives.size
? (uint32_t*)malloc(sizeof(uint32_t) * (boundary->primitives.size + 1))
: NULL;
assert(regs->primitive_offsets || boundary->primitives.size == 0);
uint32_t primitive_output_count = 0;
for (size_t i = 0; i < boundary->primitives.size; i++)
{
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &boundary->primitives, i);
regs->primitive_offsets[i] = primitive_output_count;
primitive_output_count += sn_design_module_output_count(design, entry->module);
}
if (boundary->primitives.size)
regs->primitive_offsets[boundary->primitives.size] = primitive_output_count;
regs->primitive_pairs = primitive_output_count
? (sn_obj_pair_t*)malloc(sizeof(sn_obj_pair_t) * primitive_output_count)
: NULL;
assert(regs->primitive_pairs || primitive_output_count == 0);
for (size_t i = 0; i < boundary->primitives.size; i++)
{
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &boundary->primitives, i);
const sn_blast_occurrence_t* occurrence =
&sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, entry->occurrence);
const sn_module_t* module = sn_design_get_module_const(design, occurrence->module);
const sn_module_t* child = sn_design_get_module_const(design, entry->module);
for (size_t output = 0; output < child->type_objects[SN_PO].size; output++)
{
sn_obj_id_t old_output = child->type_objects[SN_PO].size == 1
? entry->inst
: sn_inst_output(module, entry->inst, (uint32_t)output);
const char* output_name = sn_obj_name_id(module, old_output) == SN_INVALID_ID
? NULL
: sn_obj_name(module, old_output);
regs->primitive_pairs[regs->primitive_offsets[i] + output] =
sn_module_add_loop_pair(result, sn_obj_width(module, old_output),
sn_obj_is_signed(module, old_output), output_name, "primitive_boundary_input");
}
}
regs->pairs = boundary->registers.size
? (sn_obj_pair_t*)malloc(sizeof(sn_obj_pair_t) * boundary->registers.size)
: NULL;
assert(regs->pairs || boundary->registers.size == 0);
for (size_t i = 0; i < boundary->registers.size; i++)
{
const sn_blast_register_t* entry = &sn_vec_at(sn_blast_register_t, &boundary->registers, i);
const sn_blast_occurrence_t* occurrence =
&sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, entry->occurrence);
const sn_module_t* module = sn_design_get_module_const(design, occurrence->module);
sn_obj_id_t old_out = entry->reg_out;
sn_obj_id_t old_in = sn_obj_pair_in(module, old_out);
const char* out_name = sn_obj_name_id(module, old_out) == SN_INVALID_ID ? NULL : sn_obj_name(module, old_out);
const char* in_name = sn_obj_name_id(module, old_in) == SN_INVALID_ID ? NULL : sn_obj_name(module, old_in);
regs->pairs[i] = sn_module_add_reg_pair(result, entry->width, sn_obj_is_signed(module, old_out),
out_name, in_name, SN_INVALID_ID);
sn_reg_set_flags(result, regs->pairs[i].out, sn_obj_reg_flags(module, old_out));
}
regs->loops = boundary->loops.size ? (sn_obj_pair_t*)malloc(sizeof(sn_obj_pair_t) * boundary->loops.size) : NULL;
assert(regs->loops || boundary->loops.size == 0);
for (size_t i = 0; i < boundary->loops.size; i++)
{
const sn_blast_loop_t* entry = &sn_vec_at(sn_blast_loop_t, &boundary->loops, i);
const sn_blast_occurrence_t* occurrence =
&sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, entry->occurrence);
const sn_module_t* module = sn_design_get_module_const(design, occurrence->module);
sn_obj_id_t old_in = sn_obj_pair_in(module, entry->loop_out);
const char* out_name = sn_obj_name_id(module, entry->loop_out) == SN_INVALID_ID
? NULL
: sn_obj_name(module, entry->loop_out);
const char* in_name = sn_obj_name_id(module, old_in) == SN_INVALID_ID ? NULL : sn_obj_name(module, old_in);
regs->loops[i] = sn_module_add_loop_pair(result, entry->width,
sn_obj_is_signed(module, entry->loop_out), out_name, in_name);
}
size_t link_count = boundary->primitives.size + boundary->registers.size + boundary->loops.size;
if (boundary->occurrences.size)
link_count += boundary->occurrences.size - 1;
if (link_count)
{
regs->link_cap = 2;
while (regs->link_cap < 2 * link_count)
regs->link_cap <<= 1;
regs->links = (sn_boundary_link_t*)malloc(regs->link_cap * sizeof(sn_boundary_link_t));
assert(regs->links);
for (size_t i = 0; i < regs->link_cap; i++)
{
regs->links[i].key = UINT64_MAX;
regs->links[i].primitive = SN_INVALID_ID;
regs->links[i].child = SN_INVALID_ID;
regs->links[i].reg = SN_INVALID_ID;
regs->links[i].loop = SN_INVALID_ID;
}
for (size_t i = 0; i < boundary->primitives.size; i++)
{
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &boundary->primitives, i);
sn_boundary_link_find(regs, entry->occurrence, entry->inst, true)->primitive = (uint32_t)i;
}
for (size_t i = 1; i < boundary->occurrences.size; i++)
{
const sn_blast_occurrence_t* entry = &sn_vec_at(sn_blast_occurrence_t, &boundary->occurrences, i);
sn_boundary_link_find(regs, entry->parent_occurrence, entry->parent_inst, true)->child = (uint32_t)i;
}
for (size_t i = 0; i < boundary->registers.size; i++)
{
const sn_blast_register_t* entry = &sn_vec_at(sn_blast_register_t, &boundary->registers, i);
sn_boundary_link_find(regs, entry->occurrence, entry->reg_out, true)->reg = (uint32_t)i;
}
for (size_t i = 0; i < boundary->loops.size; i++)
{
const sn_blast_loop_t* entry = &sn_vec_at(sn_blast_loop_t, &boundary->loops, i);
sn_boundary_link_find(regs, entry->occurrence, entry->loop_out, true)->loop = (uint32_t)i;
}
}
}
static inline sn_obj_id_t sn_boundary_primitive_output_bit(sn_boundary_regs_t* regs, uint32_t owner,
uint32_t port, uint32_t bit)
{
assert(owner < regs->boundary->primitives.size);
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &regs->boundary->primitives, owner);
assert(port < sn_design_module_output_count(regs->design, entry->module));
(void)entry;
sn_obj_id_t output = regs->primitive_pairs[regs->primitive_offsets[owner] + port].out;
assert(bit < sn_obj_width(regs->result, output));
return sn_module_add_slice(regs->result, output, (int32_t)bit, (int32_t)bit, "primitive_output_bit");
}
static inline sn_obj_id_t sn_boundary_reg_output_bit(sn_boundary_regs_t* regs, uint32_t owner, uint32_t bit)
{
assert(owner < regs->boundary->registers.size);
assert(bit < sn_obj_width(regs->result, regs->pairs[owner].out));
return sn_module_add_slice(regs->result, regs->pairs[owner].out, (int32_t)bit, (int32_t)bit, "reg_q_bit");
}
static inline sn_obj_id_t sn_boundary_loop_output_bit(sn_boundary_regs_t* regs, uint32_t owner, uint32_t bit)
{
assert(owner < regs->boundary->loops.size);
assert(bit < sn_obj_width(regs->result, regs->loops[owner].out));
return sn_module_add_slice(regs->result, regs->loops[owner].out, (int32_t)bit, (int32_t)bit, "loop_q_bit");
}
static inline sn_obj_id_t sn_boundary_co_word(sn_boundary_regs_t* regs, const sn_obj_id_t* co_drivers,
uint32_t begin, sn_blast_boundary_kind_t kind, uint32_t owner,
uint32_t port, uint32_t width)
{
assert(begin <= regs->boundary->cos.size && width <= regs->boundary->cos.size - begin);
for (uint32_t bit = 0; bit < width; bit++)
{
sn_blast_boundary_bit_t endpoint =
sn_vec_at(sn_blast_boundary_bit_t, &regs->boundary->cos, begin + bit);
assert(endpoint.kind == kind && endpoint.owner == owner &&
(port == SN_INVALID_ID || endpoint.port == port) && endpoint.signal.bit == bit);
}
return sn_boundary_pack_bits(regs->result, co_drivers + begin, width, "boundary_word");
}
typedef struct sn_boundary_dfs_frame_t
{
sn_obj_id_t object;
uint32_t next_fanout;
} sn_boundary_dfs_frame_t;
// Marks tentative primitive-output substitutions that create combinational feedback. All temporary pair outputs
// have already been replaced by the corresponding primitive outputs. One iterative Kosaraju traversal identifies
// the resulting strongly connected components; a substituted edge whose endpoints share a component must retain
// its loop pair. This replaces one complete cone walk per primitive output by linear whole-module graph work.
static inline void sn_boundary_mark_feedback_pairs(sn_module_t* module, const sn_obj_id_t* actual_to_pair,
uint8_t* keep)
{
size_t object_count = module->obj_types.size;
uint8_t* visited = (uint8_t*)calloc(object_count, sizeof(uint8_t));
uint32_t* components = object_count ? (uint32_t*)malloc(object_count * sizeof(uint32_t)) : NULL;
sn_vec_t order, stack;
assert(visited && (components || object_count == 0));
sn_vec_init(&order);
sn_vec_init(&stack);
sn_vec_reserve(sn_obj_id_t, &order, object_count);
sn_module_build_fanouts(module);
for (sn_obj_id_t start = 0; start < object_count; start++)
{
if (visited[start])
continue;
visited[start] = 1;
sn_boundary_dfs_frame_t* first = sn_vec_push(sn_boundary_dfs_frame_t, &stack);
first->object = start;
first->next_fanout = 0;
while (stack.size)
{
sn_boundary_dfs_frame_t* frame =
&sn_vec_at(sn_boundary_dfs_frame_t, &stack, stack.size - 1);
uint32_t count = sn_obj_fanout_count(module, frame->object);
if (frame->next_fanout < count)
{
sn_obj_id_t fanout = sn_obj_fanout(module, frame->object, frame->next_fanout++);
if (!visited[fanout])
{
visited[fanout] = 1;
sn_boundary_dfs_frame_t* child = sn_vec_push(sn_boundary_dfs_frame_t, &stack);
child->object = fanout;
child->next_fanout = 0;
}
continue;
}
*sn_vec_push(sn_obj_id_t, &order) = frame->object;
stack.size--;
}
}
for (sn_obj_id_t object = 0; object < object_count; object++)
components[object] = UINT32_MAX;
uint32_t component_count = 0;
for (size_t i = order.size; i-- > 0;)
{
sn_obj_id_t start = sn_vec_at(sn_obj_id_t, &order, i);
if (components[start] != UINT32_MAX)
continue;
components[start] = component_count;
*sn_vec_push(sn_obj_id_t, &stack) = start;
while (stack.size)
{
sn_obj_id_t object = sn_vec_at(sn_obj_id_t, &stack, --stack.size);
for (uint32_t k = 0; k < sn_obj_fanin_count(module, object); k++)
{
sn_obj_id_t fanin = sn_obj_fanin(module, object, k);
if (fanin != SN_INVALID_ID && components[fanin] == UINT32_MAX)
{
components[fanin] = component_count;
*sn_vec_push(sn_obj_id_t, &stack) = fanin;
}
}
}
component_count++;
}
for (sn_obj_id_t object = 0; object < object_count; object++)
for (uint32_t i = 0; i < sn_obj_fanin_count(module, object); i++)
{
sn_obj_id_t actual = sn_obj_fanin(module, object, i);
sn_obj_id_t pair_out = actual == SN_INVALID_ID ? SN_INVALID_ID : actual_to_pair[actual];
if (pair_out != SN_INVALID_ID && components[actual] == components[object])
keep[pair_out] = 1;
}
sn_module_invalidate_fanouts(module);
sn_vec_destroy(&order);
sn_vec_destroy(&stack);
free(components);
free(visited);
}
// Duplicates a module in topological order while omitting an explicitly unreferenced set of objects. This is used
// to remove temporary primitive-output loop pairs after their consumers have been redirected to the real outputs.
static inline sn_module_id_t sn_boundary_dup_filtered_topo(sn_design_t* design, sn_module_id_t source_id,
const uint8_t* remove, const char* name)
{
sn_module_t* source = sn_design_get_module(design, source_id);
size_t object_count = source->obj_types.size;
uint8_t* marks = (uint8_t*)calloc(object_count, sizeof(uint8_t));
sn_vec_t order;
assert(marks);
sn_vec_init(&order);
sn_vec_reserve(sn_obj_id_t, &order, object_count);
for (sn_obj_id_t object = 0; object < object_count; object++)
if (remove[object])
marks[object] = SN_TOPO_DONE;
for (size_t i = 0; i < source->type_objects[SN_PI].size; i++)
{
sn_obj_id_t object = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PI], i);
assert(!remove[object]);
marks[object] = SN_TOPO_DONE;
*sn_vec_push(sn_obj_id_t, &order) = object;
}
for (sn_obj_id_t object = 0; object < object_count; object++)
if (!remove[object] && sn_obj_type_is_pair_out(sn_obj_type(source, object)))
{
marks[object] = SN_TOPO_DONE;
*sn_vec_push(sn_obj_id_t, &order) = object;
}
sn_topo_context_t context = {source, &order, marks};
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
{
sn_obj_id_t output = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
for (uint32_t j = 0; j < sn_obj_fanin_count(source, output); j++)
{
sn_obj_id_t fanin = sn_obj_fanin(source, output, j);
if (fanin != SN_INVALID_ID)
sn_module_topo_visit(&context, fanin);
}
}
for (sn_obj_id_t object = 0; object < object_count; object++)
{
sn_obj_type_t type = sn_obj_type(source, object);
if (type != SN_PI && type != SN_PO && marks[object] == SN_TOPO_UNSEEN)
sn_module_topo_visit(&context, object);
}
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
{
sn_obj_id_t output = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
marks[output] = SN_TOPO_DONE;
*sn_vec_push(sn_obj_id_t, &order) = output;
}
sn_module_id_t target_id = sn_design_add_module(design, name);
sn_module_t* target = sn_design_get_module(design, target_id);
sn_vec_resize(sn_obj_id_t, &source->copy_ids, object_count);
for (sn_obj_id_t object = 0; object < object_count; object++)
sn_vec_at(sn_obj_id_t, &source->copy_ids, object) = SN_INVALID_ID;
for (size_t i = 0; i < order.size; i++)
{
sn_obj_id_t old_object = sn_vec_at(sn_obj_id_t, &order, i);
sn_vec_at(sn_obj_id_t, &source->copy_ids, old_object) =
sn_module_dup_obj_skeleton(target, source, old_object);
}
sn_module_clean_rebuild_pair_ids(target, source, SN_REG_OUT, SN_REG_IN);
sn_module_clean_rebuild_pair_ids(target, source, SN_MEM_OUT, SN_MEM_IN);
sn_module_clean_rebuild_pair_ids(target, source, SN_LOOP_OUT, SN_LOOP_IN);
for (size_t i = 0; i < order.size; i++)
{
sn_obj_id_t old_object = sn_vec_at(sn_obj_id_t, &order, i);
sn_obj_id_t new_object = sn_vec_at(sn_obj_id_t, &source->copy_ids, old_object);
sn_obj_type_t type = sn_obj_type(source, old_object);
sn_module_dup_obj_metadata(target, sn_obj_type_id(target, new_object), source, old_object);
if (type == SN_FAN)
sn_vec_at(sn_obj_id_t, &target->fan_insts, sn_obj_type_id(target, new_object)) =
sn_vec_at(sn_obj_id_t, &source->copy_ids, sn_fan_inst_id(source, old_object));
for (uint32_t j = 0; j < sn_obj_fanin_count(source, old_object); j++)
{
sn_obj_id_t old_fanin = sn_obj_fanin(source, old_object, j);
sn_obj_id_t new_fanin = old_fanin == SN_INVALID_ID
? SN_INVALID_ID
: sn_vec_at(sn_obj_id_t, &source->copy_ids, old_fanin);
assert(new_fanin != SN_INVALID_ID || old_fanin == SN_INVALID_ID);
sn_obj_connect(target, new_object, j, new_fanin);
}
}
source->copy_module = target_id;
sn_vec_destroy(&order);
free(marks);
assert(sn_module_is_topo(target));
return target_id;
}
static inline void sn_boundary_prune_primitive_pairs(sn_boundary_regs_t* regs)
{
sn_module_t* source = regs->result;
size_t object_count = source->obj_types.size;
uint8_t* remove = (uint8_t*)calloc(object_count, sizeof(uint8_t));
uint8_t* keep = (uint8_t*)calloc(object_count, sizeof(uint8_t));
sn_obj_id_t* replacement = object_count ? (sn_obj_id_t*)malloc(object_count * sizeof(sn_obj_id_t)) : NULL;
sn_obj_id_t* actual_to_pair = object_count ? (sn_obj_id_t*)malloc(object_count * sizeof(sn_obj_id_t)) : NULL;
size_t remove_count = 0;
assert(remove && keep && (replacement || object_count == 0) && (actual_to_pair || object_count == 0));
for (sn_obj_id_t object = 0; object < object_count; object++)
replacement[object] = actual_to_pair[object] = SN_INVALID_ID;
for (size_t i = 0; i < regs->boundary->primitives.size; i++)
{
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &regs->boundary->primitives, i);
uint32_t output_count = sn_design_module_output_count(regs->design, entry->module);
for (uint32_t output = 0; output < output_count; output++)
{
sn_obj_pair_t pair = regs->primitive_pairs[regs->primitive_offsets[i] + output];
sn_obj_id_t actual = sn_obj_fanin(source, pair.in, 0);
assert(replacement[pair.out] == SN_INVALID_ID && actual_to_pair[actual] == SN_INVALID_ID);
replacement[pair.out] = actual;
actual_to_pair[actual] = pair.out;
}
}
for (size_t i = 0; i < source->fanins.size; i++)
{
sn_obj_id_t fanin = sn_vec_at(sn_obj_id_t, &source->fanins, i);
if (fanin != SN_INVALID_ID && replacement[fanin] != SN_INVALID_ID)
sn_vec_at(sn_obj_id_t, &source->fanins, i) = replacement[fanin];
}
sn_module_invalidate_fanouts(source);
sn_boundary_mark_feedback_pairs(source, actual_to_pair, keep);
for (sn_obj_id_t object = 0; object < object_count; object++)
for (uint32_t i = 0; i < sn_obj_fanin_count(source, object); i++)
{
sn_obj_id_t actual = sn_obj_fanin(source, object, i);
sn_obj_id_t pair_out = actual == SN_INVALID_ID ? SN_INVALID_ID : actual_to_pair[actual];
if (pair_out != SN_INVALID_ID && keep[pair_out] && object != sn_obj_pair_in(source, pair_out))
sn_obj_connect(source, object, i, pair_out);
}
for (sn_obj_id_t pair_out = 0; pair_out < object_count; pair_out++)
if (replacement[pair_out] != SN_INVALID_ID && !keep[pair_out])
{
sn_obj_id_t actual = replacement[pair_out];
sn_obj_id_t pair_in = sn_obj_pair_in(source, pair_out);
if (sn_obj_type(source, actual) == SN_FAN && sn_obj_name_id(source, actual) == SN_INVALID_ID &&
sn_obj_name_id(source, pair_out) != SN_INVALID_ID)
sn_vec_at(sn_name_id_t, &source->name_ids, actual) = sn_obj_name_id(source, pair_out);
remove[pair_out] = remove[pair_in] = 1;
remove_count += 2;
}
sn_module_invalidate_fanouts(source);
if (remove_count)
{
char name[96];
uint32_t suffix = 0;
do
{
int length = snprintf(name, sizeof(name), "__sn_boundary_%u_%u", source->id, suffix++);
assert(length >= 0 && (size_t)length < sizeof(name) && suffix != 0);
} while (sn_name_find(&regs->design->names, name) != SN_INVALID_ID);
sn_module_id_t source_id = source->id;
sn_name_id_t source_name = source->name;
bool interface_locked = source->interface_locked;
sn_module_id_t filtered_id = sn_boundary_dup_filtered_topo(regs->design, source_id, remove, name);
sn_module_t* filtered = sn_design_get_module(regs->design, filtered_id);
sn_name_id_t temporary_name = filtered->name;
sn_design_invalidate_copies_to_module(regs->design, source_id);
sn_module_destroy(source);
free(source);
filtered->id = source_id;
filtered->name = source_name;
filtered->interface_locked = interface_locked;
sn_vec_at(sn_module_t*, &regs->design->modules, source_id) = filtered;
regs->design->modules.size--;
sn_name_remove_last(&regs->design->names, temporary_name);
regs->result = filtered;
}
free(actual_to_pair);
free(replacement);
free(keep);
free(remove);
}
static inline void sn_boundary_regs_finish(sn_boundary_regs_t* regs, const sn_obj_id_t* co_drivers)
{
for (size_t i = 0; i < regs->boundary->primitives.size; i++)
{
const sn_blast_primitive_t* entry = &sn_vec_at(sn_blast_primitive_t, &regs->boundary->primitives, i);
const sn_blast_occurrence_t* occurrence =
&sn_vec_at(sn_blast_occurrence_t, &regs->boundary->occurrences, entry->occurrence);
const sn_module_t* module = sn_design_get_module_const(regs->design, occurrence->module);
const sn_module_t* child = sn_design_get_module_const(regs->design, entry->module);
uint32_t input_count = (uint32_t)child->type_objects[SN_PI].size;
sn_obj_id_t* inputs = input_count ? (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * input_count) : NULL;
assert(inputs || input_count == 0);
uint32_t co_begin = entry->co_begin;
for (uint32_t input = 0; input < input_count; input++)
{
sn_obj_id_t port = sn_vec_at(sn_obj_id_t, &child->type_objects[SN_PI], input);
uint32_t width = sn_obj_width(child, port);
inputs[input] = sn_boundary_co_word(regs, co_drivers, co_begin, SN_BLAST_BOUNDARY_PRIMITIVE_INPUT,
(uint32_t)i, input, width);
co_begin += width;
}
assert(co_begin == entry->co_begin + entry->co_count);
const char* inst_name = sn_obj_name_id(module, entry->inst) == SN_INVALID_ID
? NULL
: sn_obj_name(module, entry->inst);
sn_obj_id_t inst = sn_module_add_inst(regs->result, entry->module, input_count, inputs, inst_name, NULL);
free(inputs);
for (uint32_t output = 0; output < child->type_objects[SN_PO].size; output++)
{
sn_obj_pair_t pair = regs->primitive_pairs[regs->primitive_offsets[i] + output];
sn_obj_connect(regs->result, pair.in, 0, sn_inst_output(regs->result, inst, output));
}
}
for (size_t i = 0; i < regs->boundary->loops.size; i++)
{
const sn_blast_loop_t* entry = &sn_vec_at(sn_blast_loop_t, &regs->boundary->loops, i);
sn_obj_id_t data = sn_boundary_co_word(regs, co_drivers, entry->co_begin, SN_BLAST_BOUNDARY_LOOP_INPUT,
(uint32_t)i, SN_INVALID_ID, entry->width);
sn_obj_connect(regs->result, regs->loops[i].in, 0, data);
}
for (size_t i = 0; i < regs->boundary->registers.size; i++)
{
const sn_blast_register_t* entry = &sn_vec_at(sn_blast_register_t, &regs->boundary->registers, i);
const sn_blast_occurrence_t* occurrence =
&sn_vec_at(sn_blast_occurrence_t, &regs->boundary->occurrences, entry->occurrence);
const sn_module_t* module = sn_design_get_module_const(regs->design, occurrence->module);
sn_obj_id_t old_out = entry->reg_out;
sn_obj_pair_t pair = regs->pairs[i];
sn_obj_id_t old_clock = sn_obj_fanin(module, old_out, SN_REG_CLOCK);
if (old_clock != SN_INVALID_ID)
{
sn_blast_hier_ref_t ref = {entry->occurrence, old_clock, 0};
sn_reg_set_fanin(regs->result, pair.out, SN_REG_CLOCK, sn_boundary_resolve_external(regs, ref));
}
const uint32_t slots[] = {SN_REG_ENABLE, SN_REG_SET, SN_REG_RESET, SN_REG_RESET_VALUE};
for (size_t k = 0; k < sizeof(slots) / sizeof(slots[0]); k++)
{
uint32_t slot = slots[k];
sn_obj_id_t old_fanin = sn_obj_fanin(module, old_out, slot);
if (old_fanin == SN_INVALID_ID)
continue;
bool in_cloud = sn_blast_reg_control_is_comb_output(module, old_out, slot);
sn_obj_id_t fanin;
if (in_cloud)
{
assert(entry->control_co_begin[slot] != SN_INVALID_ID);
fanin = sn_boundary_co_word(regs, co_drivers, entry->control_co_begin[slot],
SN_BLAST_BOUNDARY_REG_CONTROL, (uint32_t)i, slot,
sn_obj_width(module, old_fanin));
}
else
{
sn_blast_hier_ref_t ref = {entry->occurrence, old_fanin, 0};
fanin = sn_boundary_resolve_external(regs, ref);
}
sn_reg_set_fanin(regs->result, pair.out, (sn_reg_fanin_t)slot, fanin);
}
for (uint32_t slot = SN_REG_INIT_DATA; slot <= SN_REG_INIT_MASK; slot++)
{
sn_obj_id_t old_fanin = sn_obj_fanin(module, old_out, slot);
if (old_fanin != SN_INVALID_ID)
{
sn_blast_hier_ref_t ref = {entry->occurrence, old_fanin, 0};
sn_reg_set_fanin(regs->result, pair.out, (sn_reg_fanin_t)slot,
sn_boundary_resolve_external(regs, ref));
}
}
sn_obj_id_t data = sn_boundary_co_word(regs, co_drivers, entry->co_begin, SN_BLAST_BOUNDARY_REG_INPUT,
(uint32_t)i, SN_INVALID_ID, entry->width);
sn_obj_connect(regs->result, pair.in, 0, data);
}
sn_boundary_prune_primitive_pairs(regs);
free(regs->pairs);
free(regs->loops);
free(regs->primitive_pairs);
free(regs->primitive_offsets);
free(regs->links);
for (size_t i = 0; i < regs->boundary->occurrences.size; i++)
free(regs->external_copies[i]);
free(regs->external_copies);
regs->pairs = NULL;
regs->loops = NULL;
regs->primitive_pairs = NULL;
regs->primitive_offsets = NULL;
regs->external_copies = NULL;
regs->links = NULL;
regs->link_cap = 0;
}
ABC_NAMESPACE_HEADER_END
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,167 +0,0 @@
/**CFile****************************************************************
FileName [snMapAdd.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Mapping word-level adders and subtractors into FPGA carry primitives.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snMapAdd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef SN_MAP_ADD_H
#define SN_MAP_ADD_H
// Maps word-level addition and subtraction into preserved FPGA carry-chain
// primitive insts. The surrounding propagate/invert logic remains ordinary SN
// logic and can subsequently be mapped into LUTs.
#include "sn.h"
#include "snTech.h"
ABC_NAMESPACE_HEADER_START
typedef struct sn_add_map_options_t
{
uint32_t min_width;
bool map_add;
bool map_sub;
bool preserve_names;
} sn_add_map_options_t;
static inline sn_add_map_options_t sn_add_map_default_options(void)
{
sn_add_map_options_t options = {0, true, true, true};
return options;
}
static inline bool sn_add_tech_supports(const sn_carry_tech_t* tech, const sn_add_map_options_t* options,
sn_obj_type_t type, uint32_t width)
{
assert(tech && options);
uint32_t min_width = options->min_width ? options->min_width : tech->min_op_width;
return width >= min_width && ((type == SN_ADD && options->map_add) || (type == SN_SUB && options->map_sub));
}
static inline sn_obj_id_t sn_add_slice_bit(sn_module_t* module, sn_obj_id_t value, uint32_t bit)
{
assert(bit < sn_obj_width(module, value));
return sn_module_add_slice(module, value, (int32_t)bit, (int32_t)bit, NULL);
}
// The behavioral body is identical to the Xilinx CARRY4 simulation model. It
// permits standalone SN simulation and CEC while the __sn_ prefix marks the
// module as a hard primitive that hierarchy collapse and LUT mapping preserve.
static inline sn_module_id_t sn_add_carry_primitive_module(sn_design_t* design, const sn_carry_tech_t* tech)
{
assert(design && tech && tech->width == 4);
char name[64];
int length = snprintf(name, sizeof(name), "__sn_%s", tech->name);
assert(length >= 0 && (size_t)length < sizeof(name));
sn_module_id_t existing = sn_design_find_module(design, name);
if (existing != SN_INVALID_ID)
return existing;
sn_module_id_t id = sn_design_add_module(design, name);
sn_module_t* module = sn_design_get_module(design, id);
sn_obj_id_t ci = sn_module_add_pi(module, 1, false, "CI");
sn_obj_id_t cyinit = sn_module_add_pi(module, 1, false, "CYINIT");
sn_obj_id_t di = sn_module_add_pi(module, 4, false, "DI");
sn_obj_id_t s = sn_module_add_pi(module, 4, false, "S");
sn_obj_id_t init_fanins[2] = {ci, cyinit};
sn_obj_id_t carry = sn_module_add_operator(module, SN_BIT_OR, 1, false, 2, init_fanins, NULL);
sn_obj_id_t o_bits[4], co_bits[4];
for (uint32_t bit = 0; bit < 4; bit++)
{
sn_obj_id_t s_bit = sn_add_slice_bit(module, s, bit);
sn_obj_id_t di_bit = sn_add_slice_bit(module, di, bit);
sn_obj_id_t xor_fanins[2] = {s_bit, carry};
o_bits[bit] = sn_module_add_operator(module, SN_BIT_XOR, 1, false, 2, xor_fanins, NULL);
co_bits[bit] = sn_module_add_mux(module, s_bit, carry, di_bit, NULL);
carry = co_bits[bit];
}
sn_obj_id_t o = sn_module_add_concat(module, 4, o_bits, NULL);
sn_obj_id_t co = sn_module_add_concat(module, 4, co_bits, NULL);
sn_module_add_po(module, 4, false, "O", o);
sn_module_add_po(module, 4, false, "CO", co);
assert(sn_module_is_topo(module));
return id;
}
static inline sn_obj_id_t sn_add_resize(sn_module_t* module, sn_obj_id_t value, uint32_t width, bool is_signed)
{
if (sn_obj_width(module, value) == width && sn_obj_is_signed(module, value) == is_signed)
return value;
return sn_module_add_operator(module, SN_CAST, width, is_signed, 1, &value, NULL);
}
static inline sn_obj_id_t sn_add_pad_chunk(sn_module_t* module, sn_obj_id_t value, uint32_t width)
{
assert(width && width <= 4 && sn_obj_width(module, value) == width);
if (width == 4)
return value;
sn_obj_id_t zero = sn_module_add_named_obj(module, SN_CONST0, 4 - width, false, 0, NULL);
sn_obj_id_t fanins[2] = {value, zero};
return sn_module_add_concat(module, 2, fanins, NULL);
}
// Implements A+B or A-B exactly as Yosys's Xilinx $alu mapping: DI=A,
// S=A^B (or A^~B), and subtraction starts the carry chain at one.
static inline sn_obj_id_t sn_add_map_carry_chain(sn_module_t* module, const sn_carry_tech_t* tech,
sn_obj_type_t type, sn_obj_id_t a, sn_obj_id_t b,
uint32_t result_width, bool result_signed, const char* name)
{
assert(module && tech && tech->width == 4 && (type == SN_ADD || type == SN_SUB));
assert(a < module->obj_types.size && b < module->obj_types.size && result_width);
bool signed_operands = sn_obj_is_signed(module, a) && sn_obj_is_signed(module, b);
a = sn_add_resize(module, a, result_width, signed_operands);
b = sn_add_resize(module, b, result_width, signed_operands);
if (type == SN_SUB)
b = sn_module_add_operator(module, SN_BIT_NOT, result_width, signed_operands, 1, &b, NULL);
sn_obj_id_t xor_fanins[2] = {a, b};
sn_obj_id_t propagate =
sn_module_add_operator(module, SN_BIT_XOR, result_width, false, 2, xor_fanins, NULL);
sn_obj_id_t zero = sn_module_add_named_obj(module, SN_CONST0, 1, false, 0, NULL);
sn_obj_id_t one = sn_module_add_named_obj(module, SN_CONST1, 1, false, 0, NULL);
sn_obj_id_t carry = zero;
sn_module_id_t primitive = sn_add_carry_primitive_module(module->design, tech);
uint32_t chunk_count = (result_width + 3) / 4;
sn_obj_id_t* chunks = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * chunk_count);
assert(chunks);
for (uint32_t chunk = 0; chunk < chunk_count; chunk++)
{
uint32_t offset = chunk * 4;
uint32_t width = result_width - offset < 4 ? result_width - offset : 4;
sn_obj_id_t di = sn_module_add_slice(module, a, (int32_t)(offset + width - 1), (int32_t)offset, NULL);
sn_obj_id_t s =
sn_module_add_slice(module, propagate, (int32_t)(offset + width - 1), (int32_t)offset, NULL);
di = sn_add_pad_chunk(module, di, width);
s = sn_add_pad_chunk(module, s, width);
sn_obj_id_t inputs[4] = {carry, chunk == 0 && type == SN_SUB ? one : zero, di, s};
const char* output_names[2] = {NULL, NULL};
sn_obj_id_t inst = sn_module_add_inst(module, primitive, 4, inputs, NULL, output_names);
chunks[chunk] = sn_inst_output(module, inst, 0);
sn_obj_id_t co = sn_inst_output(module, inst, 1);
carry = sn_add_slice_bit(module, co, 3);
}
sn_obj_id_t result = chunk_count == 1 ? chunks[0] : sn_module_add_concat(module, chunk_count, chunks, NULL);
free(chunks);
if (sn_obj_width(module, result) != result_width)
result = sn_module_add_slice(module, result, (int32_t)result_width - 1, 0, NULL);
if (sn_obj_is_signed(module, result) != result_signed)
result = sn_module_add_operator(module, SN_CAST, result_width, result_signed, 1, &result, name);
return result;
}
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,85 +0,0 @@
/**CFile****************************************************************
FileName [snMapDsp.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Mapping word-level multipliers into FPGA DSP primitives.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snMapDsp.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef SN_MAP_DSP_H
#define SN_MAP_DSP_H
#include "sn.h"
#include "snTech.h"
ABC_NAMESPACE_HEADER_START
typedef struct sn_dsp_map_options_t
{
bool allow_soft_fallback;
bool use_preadder;
bool use_postadder;
bool preserve_names;
bool balance_adders;
bool prune_unused_high_products;
uint32_t a_unsigned_chunk_width;
uint32_t b_unsigned_chunk_width;
uint32_t max_dsps_per_multiply;
} sn_dsp_map_options_t;
static inline sn_dsp_map_options_t sn_dsp_map_default_options(void)
{
sn_dsp_map_options_t options = {true, false, false, true, true, true, 0, 0, 0};
return options;
}
static inline bool sn_dsp_tech_supports_mul(const sn_dsp_tech_t* tech, uint32_t a_width, uint32_t b_width,
uint32_t result_width, bool a_signed, bool b_signed)
{
assert(tech);
if (!a_width || !b_width || !result_width || a_width > tech->a_width || b_width > tech->b_width ||
result_width > tech->p_width)
return false;
if (a_width < tech->min_a_width || b_width < tech->min_b_width || result_width < tech->min_p_width)
return false;
if (tech->signed_only && (!a_signed || !b_signed))
return false;
return true;
}
static inline sn_module_id_t sn_map_dsp_primitive_module(sn_design_t* design, const sn_dsp_tech_t* tech,
uint32_t a_width, uint32_t b_width, uint32_t y_width,
bool a_signed, bool b_signed)
{
char name[128];
int length = snprintf(name, sizeof(name), "__sn_%s_mul_%u_%u_%u_s%u%u", tech->name, a_width, b_width,
y_width, a_signed ? 1u : 0u, b_signed ? 1u : 0u);
assert(length >= 0 && (size_t)length < sizeof(name));
sn_module_id_t existing = sn_design_find_module(design, name);
if (existing != SN_INVALID_ID)
return existing;
sn_module_id_t id = sn_design_add_module(design, name);
sn_module_t* module = sn_design_get_module(design, id);
sn_obj_id_t a = sn_module_add_pi(module, a_width, a_signed, "A");
sn_obj_id_t b = sn_module_add_pi(module, b_width, b_signed, "B");
sn_obj_id_t fanins[] = {a, b};
sn_obj_id_t product = sn_module_add_operator(module, SN_MUL, y_width, a_signed || b_signed, 2, fanins, "P");
sn_module_add_po(module, y_width, a_signed || b_signed, "Y", product);
return id;
}
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,270 +0,0 @@
/**CFile****************************************************************
FileName [snMapLut.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Partitioned synthesis and LUT mapping of hierarchical SN designs.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snMapLut.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef SN_MAP_LUT_H
#define SN_MAP_LUT_H
// Natural-hierarchy LUT-mapping harness. Each reachable user module is extracted as one combinational MiniAIG while
// child instances, registers, and mapped hard blocks remain boundary terminals. A caller-supplied callback maps this
// partition and returns a MiniLUT. The harness reconstructs the module at its stable ID, preserving parent references.
#include "snBlast.h"
#include "snMiniLut.h"
#include "snPth.h"
ABC_NAMESPACE_HEADER_START
typedef Mini_Lut_t* (*sn_map_lut_partition_fn)(void* context, sn_module_id_t module, const char* name,
Mini_Aig_t* aig, const sn_blast_boundary_t* boundary);
typedef struct sn_map_lut_stats_t
{
uint32_t reachable_modules;
uint32_t mapped_modules;
uint32_t trivial_modules;
uint32_t primitive_modules;
uint32_t generic_memory_modules;
uint64_t input_ands;
uint64_t output_luts;
sn_module_id_t failed_module;
} sn_map_lut_stats_t;
typedef struct sn_map_lut_job_t
{
sn_module_id_t module;
sn_name_id_t name;
Mini_Aig_t* aig;
Mini_Lut_t* lut;
sn_blast_boundary_t boundary;
} sn_map_lut_job_t;
typedef struct sn_map_lut_runner_t
{
sn_design_t* design;
sn_map_lut_partition_fn function;
void* context;
} sn_map_lut_runner_t;
static inline void sn_map_lut_run_job(void* argument, void* job_argument)
{
sn_map_lut_runner_t* runner = (sn_map_lut_runner_t*)argument;
sn_map_lut_job_t* job = (sn_map_lut_job_t*)job_argument;
job->lut = runner->function(runner->context, job->module,
sn_name_get(&runner->design->names, job->name), job->aig, &job->boundary);
}
static inline bool sn_map_lut_boundary_has_generic_memories(const sn_blast_boundary_t* boundary)
{
for (size_t i = 0; i < boundary->cis.size; i++)
if (sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, i).kind == SN_BLAST_BOUNDARY_MEMORY_OUTPUT)
return true;
for (size_t i = 0; i < boundary->cos.size; i++)
if (sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, i).kind == SN_BLAST_BOUNDARY_MEMORY_INPUT)
return true;
return false;
}
static inline void sn_design_replace_appended_module(sn_design_t* design, sn_module_id_t module,
sn_name_id_t name, sn_module_id_t temporary)
{
sn_module_t* old_module;
sn_module_t* new_module;
bool interface_locked;
assert(design && module < design->modules.size);
old_module = sn_design_get_module(design, module);
assert(old_module->name == name);
assert(temporary + 1 == design->modules.size && temporary != module);
new_module = sn_design_get_module(design, temporary);
interface_locked = old_module->interface_locked;
sn_module_destroy(old_module);
free(old_module);
new_module->id = module;
new_module->name = name;
new_module->interface_locked = interface_locked;
sn_vec_at(sn_module_t*, &design->modules, module) = new_module;
design->modules.size--;
}
// Maps all user modules reachable from root. The callback borrows aig and boundary for the duration of the call and
// returns a newly allocated MiniLUT owned by this harness. A NULL result aborts the pass. Modules containing generic
// memories are skipped; map their memories into primitive instances first if their surrounding logic should be mapped.
// The operation is in-place, so a transactional client should invoke it on a duplicate design and install that design
// only after this API succeeds.
static inline bool sn_design_map_lut_hierarchy(sn_design_t* design, sn_module_id_t root,
sn_map_lut_partition_fn map_partition, void* context,
unsigned processes, bool extract_only,
sn_map_lut_stats_t* returned_stats)
{
sn_map_lut_stats_t stats = {0};
size_t module_count;
bool* reachable;
sn_vec_t pending;
sn_vec_t jobs;
stats.failed_module = SN_INVALID_ID;
assert(design && root < design->modules.size && map_partition && processes >= 1);
module_count = design->modules.size;
// Module replacement invalidates optional duplication maps that may have been cached by earlier mapping passes.
for (sn_module_id_t module_id = 0; module_id < module_count; module_id++)
{
sn_module_t* module = sn_design_get_module(design, module_id);
sn_vec_destroy(&module->copy_ids);
sn_vec_init(&module->copy_ids);
module->copy_module = SN_INVALID_ID;
}
reachable = (bool*)calloc(module_count, sizeof(bool));
assert(reachable);
sn_vec_init(&pending);
sn_vec_init(&jobs);
*sn_vec_push(sn_module_id_t, &pending) = root;
while (pending.size)
{
sn_module_id_t module_id = sn_vec_at(sn_module_id_t, &pending, --pending.size);
const sn_module_t* module;
if (reachable[module_id])
continue;
reachable[module_id] = true;
stats.reachable_modules++;
module = sn_design_get_module_const(design, module_id);
for (size_t i = 0; i < module->inst_modules.size; i++)
*sn_vec_push(sn_module_id_t, &pending) = sn_vec_at(sn_module_id_t, &module->inst_modules, i);
}
for (sn_module_id_t module_id = 0; module_id < module_count; module_id++)
{
const sn_module_t* module;
sn_name_id_t name_id;
sn_blast_options_t options;
sn_blast_boundary_t boundary;
Mini_Aig_t* aig;
if (!reachable[module_id])
continue;
module = sn_design_get_module_const(design, module_id);
if (sn_module_is_technology_primitive(module))
{
stats.primitive_modules++;
continue;
}
name_id = module->name;
options = sn_blast_default_options();
options.mode = SN_BLAST_COMB;
options.abstract_instances = true;
sn_blast_boundary_init(&boundary);
aig = sn_design_blast_hier_boundary_options(design, module_id, options, NULL, &boundary);
if (sn_map_lut_boundary_has_generic_memories(&boundary))
{
stats.generic_memory_modules++;
Mini_AigStop(aig);
sn_blast_boundary_destroy(&boundary);
continue;
}
if (Mini_AigAndNum(aig) == 0)
{
stats.trivial_modules++;
Mini_AigStop(aig);
sn_blast_boundary_destroy(&boundary);
continue;
}
stats.input_ands += (uint64_t)Mini_AigAndNum(aig);
if (processes == 1)
{
Mini_Lut_t* lut = map_partition(context, module_id, sn_name_get(&design->names, name_id), aig, &boundary);
Mini_AigStop(aig);
if (!lut)
{
stats.failed_module = module_id;
sn_blast_boundary_destroy(&boundary);
sn_vec_destroy(&pending);
sn_vec_destroy(&jobs);
free(reachable);
if (returned_stats)
*returned_stats = stats;
return false;
}
if (extract_only)
{
Mini_LutStop(lut);
sn_blast_boundary_destroy(&boundary);
stats.mapped_modules++;
continue;
}
sn_lut_stats_t lut_stats = sn_lut_analyze(lut, &boundary);
sn_module_id_t temporary = sn_design_add_lut_module(design, module_id, lut, &boundary,
"__sn_lut_partition");
Mini_LutStop(lut);
sn_blast_boundary_destroy(&boundary);
sn_design_replace_appended_module(design, module_id, name_id, temporary);
stats.mapped_modules++;
stats.output_luts += lut_stats.lut_count;
continue;
}
sn_map_lut_job_t* job = sn_vec_push(sn_map_lut_job_t, &jobs);
job->module = module_id;
job->name = name_id;
job->aig = aig;
job->lut = NULL;
job->boundary = boundary;
}
void** job_pointers = jobs.size ? (void**)malloc(sizeof(void*) * jobs.size) : NULL;
assert(job_pointers || jobs.size == 0);
for (size_t i = 0; i < jobs.size; i++)
job_pointers[i] = &sn_vec_at(sn_map_lut_job_t, &jobs, i);
sn_map_lut_runner_t runner = {design, map_partition, context};
sn_pth_process(job_pointers, jobs.size, processes, sn_map_lut_run_job, &runner);
free(job_pointers);
bool success = true;
for (size_t i = 0; i < jobs.size; i++)
if (!sn_vec_at(sn_map_lut_job_t, &jobs, i).lut)
{
stats.failed_module = sn_vec_at(sn_map_lut_job_t, &jobs, i).module;
success = false;
break;
}
if (success && !extract_only)
for (size_t i = 0; i < jobs.size; i++)
{
sn_map_lut_job_t* job = &sn_vec_at(sn_map_lut_job_t, &jobs, i);
sn_lut_stats_t lut_stats = sn_lut_analyze(job->lut, &job->boundary);
sn_module_id_t temporary = sn_design_add_lut_module(design, job->module, job->lut, &job->boundary,
"__sn_lut_partition");
sn_design_replace_appended_module(design, job->module, job->name, temporary);
stats.mapped_modules++;
stats.output_luts += lut_stats.lut_count;
}
else if (success)
stats.mapped_modules += (uint32_t)jobs.size;
for (size_t i = 0; i < jobs.size; i++)
{
sn_map_lut_job_t* job = &sn_vec_at(sn_map_lut_job_t, &jobs, i);
Mini_AigStop(job->aig);
if (job->lut)
Mini_LutStop(job->lut);
sn_blast_boundary_destroy(&job->boundary);
}
sn_vec_destroy(&pending);
sn_vec_destroy(&jobs);
free(reachable);
assert(!success || sn_design_is_topo(design));
if (returned_stats)
*returned_stats = stats;
return success;
}
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,101 +0,0 @@
/**CFile****************************************************************
FileName [snMapMem.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Mapping technology-independent memories into FPGA memory primitives.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snMapMem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef SN_MAP_MEM_H
#define SN_MAP_MEM_H
#include "sn.h"
#include "snTech.h"
ABC_NAMESPACE_HEADER_START
typedef enum sn_mem_split_order_t
{
SN_MEM_SPLIT_AUTO = 0,
SN_MEM_SPLIT_WIDTH_FIRST,
SN_MEM_SPLIT_DEPTH_FIRST
} sn_mem_split_order_t;
typedef struct sn_mem_map_options_t
{
bool allow_lutram_fallback;
bool allow_register_fallback;
bool preserve_names;
uint32_t min_memory_bits;
uint32_t max_primitives_per_memory;
sn_mem_split_order_t split_order;
} sn_mem_map_options_t;
static inline sn_mem_map_options_t sn_mem_map_default_options(void)
{
sn_mem_map_options_t options = {false, false, true, 0, 0, SN_MEM_SPLIT_AUTO};
return options;
}
// Returns true when a memory's dimensions and port protocol can be represented
// by one technology primitive. This conservative predicate is used before the
// rewriting pass; splitting, packing, and primitive-inst construction are
// the next mapper milestone.
static inline bool sn_mem_tech_supports(const sn_mem_tech_t* tech, uint32_t width, uint32_t depth,
sn_mem_port_mode_t port_mode)
{
assert(tech);
if (port_mode != tech->port_mode || !width || !depth || width > UINT32_MAX / depth)
return false;
if (width * depth > tech->cap_bits)
return false;
if (depth > (1u << tech->address_bits))
return false;
for (size_t i = 0; i < tech->width_count; i++)
if (tech->widths[i] == width)
return true;
return false;
}
// Creates a behavioral wrapper for one technology memory shape. Keeping the
// wrapper as an SN module makes the mapped result simulatable; a later Verilog
// technology writer can replace this module by RAMB/URAM cells.
static inline sn_module_id_t sn_map_mem_primitive_module(sn_design_t* design, const sn_mem_tech_t* tech,
uint32_t width, uint32_t depth)
{
char name[128];
int length = snprintf(name, sizeof(name), "__sn_%s_mem_%u_%u", tech->name, width, depth);
assert(length >= 0 && (size_t)length < sizeof(name));
sn_module_id_t existing = sn_design_find_module(design, name);
if (existing != SN_INVALID_ID)
return existing;
sn_module_id_t id = sn_design_add_module(design, name);
sn_module_t* module = sn_design_get_module(design, id);
sn_obj_id_t clock = sn_module_add_pi(module, 1, false, "clock");
sn_obj_id_t enable = sn_module_add_pi(module, 1, false, "enable");
sn_obj_id_t write_address = sn_module_add_pi(module, 32, false, "write_address");
sn_obj_id_t data = sn_module_add_pi(module, width, false, "write_data");
sn_obj_id_t read_address = sn_module_add_pi(module, 32, false, "read_address");
sn_obj_pair_t pair = sn_module_add_mem_pair(module, width, false, depth, "mem_out", "mem_in");
sn_module_add_mem_write(module, pair.in, clock, enable, data, write_address, "write");
sn_obj_id_t read = sn_module_add_mem_read(module, pair.out, SN_INVALID_ID, SN_INVALID_ID, read_address, "read");
sn_module_add_po(module, width, false, "read_data", read);
sn_design_reorder_module_topo(design, id);
return id;
}
ABC_NAMESPACE_HEADER_END
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,143 +0,0 @@
/**CFile****************************************************************
FileName [snMiniAig.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Reconstruction of SN logic from an unmapped MiniAIG network.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snMiniAig.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef ABC__base__sn__snMiniAig_h
#define ABC__base__sn__snMiniAig_h
#include "snMiniLut.h"
ABC_NAMESPACE_HEADER_START
static inline sn_obj_id_t sn_aig_lit_object(sn_module_t* module, Mini_Aig_t* aig, const sn_obj_id_t* objects, int lit)
{
int variable = Mini_AigLit2Var(lit);
assert(variable >= 0 && variable < Mini_AigNodeNum(aig));
sn_obj_id_t object = objects[variable];
assert(object != SN_INVALID_ID);
if (!Mini_AigLitIsCompl(lit))
return object;
if (variable == 0)
{
uint32_t one = 1;
return sn_module_add_const(module, 1, false, &one, "aig_const1");
}
return sn_module_add_operator(module, SN_BIT_NOT, 1, false, 1, &object, "aig_inv");
}
// Reconstructs an unmapped combinational MiniAIG as explicit one-bit SN_BIT_AND and SN_BIT_NOT objects. The MiniAIG
// CI/CO order is matched positionally against the boundary recorded by @blast. Register endpoints are reconnected by
// the shared boundary reconstruction stage; RAM/DSP endpoints are rejected by the command until they are supported.
static inline sn_module_id_t sn_design_add_aig_module(sn_design_t* design, sn_module_id_t source_top_id,
Mini_Aig_t* aig, const sn_blast_boundary_t* boundary,
const char* module_name)
{
assert(design && source_top_id < design->modules.size && aig && boundary && module_name);
assert(Mini_AigRegNum(aig) == 0);
assert((size_t)Mini_AigPiNum(aig) == boundary->cis.size);
assert((size_t)Mini_AigPoNum(aig) == boundary->cos.size);
const sn_module_t* source = sn_design_get_module_const(design, source_top_id);
sn_module_id_t result_id = sn_design_add_module(design, module_name);
sn_module_t* result = sn_design_get_module(design, result_id);
sn_obj_id_t* top_inputs = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * source->obj_types.size);
sn_obj_id_t* objects = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * Mini_AigNodeNum(aig));
sn_obj_id_t* drivers = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * boundary->cos.size);
sn_boundary_regs_t regs;
assert(top_inputs && objects && drivers);
for (size_t i = 0; i < source->obj_types.size; i++)
top_inputs[i] = SN_INVALID_ID;
for (int i = 0; i < Mini_AigNodeNum(aig); i++)
objects[i] = SN_INVALID_ID;
for (size_t i = 0; i < source->type_objects[SN_PI].size; i++)
{
sn_obj_id_t old_pi = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PI], i);
top_inputs[old_pi] = sn_module_add_pi(result, sn_obj_width(source, old_pi), sn_obj_is_signed(source, old_pi),
sn_obj_name(source, old_pi));
}
sn_boundary_regs_init(&regs, design, boundary, result, top_inputs);
uint32_t zero = 0;
objects[0] = sn_module_add_const(result, 1, false, &zero, "aig_const0");
uint32_t ci_index = 0;
int mini_object;
Mini_AigForEachPi(aig, mini_object)
{
sn_blast_boundary_bit_t bit = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, ci_index++);
if (bit.kind == SN_BLAST_BOUNDARY_TOP_PI)
{
assert(bit.signal.occurrence == 0 && top_inputs[bit.signal.object] != SN_INVALID_ID);
objects[mini_object] = sn_module_add_slice(result, top_inputs[bit.signal.object], (int32_t)bit.signal.bit,
(int32_t)bit.signal.bit, "aig_pi_bit");
}
else if (bit.kind == SN_BLAST_BOUNDARY_REG_OUTPUT)
objects[mini_object] = sn_boundary_reg_output_bit(&regs, bit.owner, bit.signal.bit);
else if (bit.kind == SN_BLAST_BOUNDARY_LOOP_OUTPUT)
objects[mini_object] = sn_boundary_loop_output_bit(&regs, bit.owner, bit.signal.bit);
else if (bit.kind == SN_BLAST_BOUNDARY_PRIMITIVE_OUTPUT)
objects[mini_object] = sn_boundary_primitive_output_bit(&regs, bit.owner, bit.port, bit.signal.bit);
else
assert(false);
}
assert(ci_index == boundary->cis.size);
Mini_AigForEachAnd(aig, mini_object)
{
sn_obj_id_t fanins[2] = {
sn_aig_lit_object(result, aig, objects, Mini_AigNodeFanin0(aig, mini_object)),
sn_aig_lit_object(result, aig, objects, Mini_AigNodeFanin1(aig, mini_object))};
objects[mini_object] = sn_module_add_operator(result, SN_BIT_AND, 1, false, 2, fanins, "aig_and");
}
uint32_t co_index = 0;
Mini_AigForEachPo(aig, mini_object)
drivers[co_index++] = sn_aig_lit_object(result, aig, objects, Mini_AigNodeFanin0(aig, mini_object));
assert(co_index <= boundary->cos.size);
co_index = 0;
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
{
sn_obj_id_t old_po = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
uint32_t width = sn_obj_width(source, old_po);
for (uint32_t bit = 0; bit < width; bit++)
{
sn_blast_boundary_bit_t endpoint = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, co_index + bit);
assert(endpoint.kind == SN_BLAST_BOUNDARY_TOP_PO && endpoint.port == i && endpoint.signal.bit == bit);
}
sn_obj_id_t driver = sn_lut_pack_bits(result, drivers + co_index, width, "aig_po_word");
sn_module_add_po(result, width, sn_obj_is_signed(source, old_po), sn_obj_name(source, old_po), driver);
co_index += width;
}
assert(co_index <= boundary->cos.size);
sn_boundary_regs_finish(&regs, drivers);
result = sn_design_get_module(design, result_id);
free(drivers);
free(objects);
free(top_inputs);
if (!sn_module_is_topo(result))
sn_design_reorder_module_topo(design, result_id);
assert(sn_module_is_topo(sn_design_get_module_const(design, result_id)));
return result_id;
}
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,215 +0,0 @@
/**CFile****************************************************************
FileName [snMiniGate.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Reconstruction of technology-mapped SN gates from mini-mapping data.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snMiniGate.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef ABC__base__sn__snMiniGate_h
#define ABC__base__sn__snMiniGate_h
#include "snMiniLut.h"
ABC_NAMESPACE_HEADER_START
typedef uint32_t (*sn_gate_id_resolver_t)(void* context, const char* gate_name);
// Reconstructs ABC's mini-mapping array as one-bit SN_GATE objects. Mini-mapping numbers CIs first and mapped nodes
// afterward in topological order. Gate names stored at the end of the array are resolved into the current library's
// stable gate IDs; the name is also retained as the SN object name for structural Verilog emission.
static inline sn_module_id_t sn_design_add_gate_module(sn_design_t* design, sn_module_id_t source_top_id,
const int* mapping, size_t mapping_count,
const sn_blast_boundary_t* boundary,
sn_gate_id_resolver_t resolver, void* resolver_context,
const char* module_name)
{
assert(design && source_top_id < design->modules.size && mapping && boundary && resolver && module_name);
if (mapping_count < 4 || mapping[0] < 0 || mapping[1] < 0 || mapping[2] < 0 || mapping[3] < 0)
return SN_INVALID_ID;
uint32_t ci_count = (uint32_t)mapping[0];
uint32_t co_count = (uint32_t)mapping[1];
uint32_t node_count = (uint32_t)mapping[2];
uint32_t reg_count = (uint32_t)mapping[3];
if (reg_count != 0 || ci_count != boundary->cis.size || co_count != boundary->cos.size ||
node_count > UINT32_MAX - ci_count)
return SN_INVALID_ID;
// Validate the complete structural prefix and resolve all bounded gate-name strings before mutating the design.
// A changed genlib or malformed mini-mapping can otherwise leave a partially constructed module behind.
size_t position = 4;
uint32_t* fanin_counts = node_count ? (uint32_t*)malloc(sizeof(uint32_t) * node_count) : NULL;
const uint32_t** fanin_indices =
node_count ? (const uint32_t**)malloc(sizeof(uint32_t*) * node_count) : NULL;
uint32_t* gate_ids = node_count ? (uint32_t*)malloc(sizeof(uint32_t) * node_count) : NULL;
bool valid = true;
assert((fanin_counts && fanin_indices && gate_ids) || node_count == 0);
for (uint32_t i = 0; valid && i < node_count; i++)
{
if (position >= mapping_count || mapping[position] < 0)
{
valid = false;
break;
}
uint32_t count = (uint32_t)mapping[position++];
if (count > mapping_count - position)
{
valid = false;
break;
}
fanin_counts[i] = count;
fanin_indices[i] = (const uint32_t*)(mapping + position);
for (uint32_t k = 0; k < count; k++)
if (mapping[position + k] < 0 || (uint32_t)mapping[position + k] >= ci_count + i)
valid = false;
position += count;
}
if (valid && co_count > mapping_count - position)
valid = false;
const uint32_t* output_indices = valid ? (const uint32_t*)(mapping + position) : NULL;
for (uint32_t i = 0; valid && i < co_count; i++)
if (mapping[position + i] < 0 || (uint32_t)mapping[position + i] >= ci_count + node_count)
valid = false;
if (valid)
position += co_count;
const char* gate_names = valid ? (const char*)(mapping + position) : NULL;
const char* gate_name = gate_names;
size_t name_bytes = valid ? (mapping_count - position) * sizeof(int) : 0;
for (uint32_t i = 0; valid && i < node_count; i++)
{
const char* end = (const char*)memchr(gate_name, '\0', name_bytes);
if (!end || end == gate_name)
{
valid = false;
break;
}
gate_ids[i] = resolver(resolver_context, gate_name);
if (gate_ids[i] == SN_INVALID_ID)
{
valid = false;
break;
}
size_t length = (size_t)(end - gate_name) + 1;
gate_name += length;
name_bytes -= length;
}
if (!valid)
{
free(gate_ids);
free(fanin_indices);
free(fanin_counts);
return SN_INVALID_ID;
}
const sn_module_t* source = sn_design_get_module_const(design, source_top_id);
sn_module_id_t result_id = sn_design_add_module(design, module_name);
sn_module_t* result = sn_design_get_module(design, result_id);
sn_obj_id_t* top_inputs = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * source->obj_types.size);
sn_obj_id_t* objects = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * (ci_count + node_count));
sn_boundary_regs_t regs;
assert(top_inputs && objects);
for (size_t i = 0; i < source->obj_types.size; i++)
top_inputs[i] = SN_INVALID_ID;
for (uint32_t i = 0; i < ci_count + node_count; i++)
objects[i] = SN_INVALID_ID;
for (size_t i = 0; i < source->type_objects[SN_PI].size; i++)
{
sn_obj_id_t old_pi = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PI], i);
top_inputs[old_pi] = sn_module_add_pi(result, sn_obj_width(source, old_pi), sn_obj_is_signed(source, old_pi),
sn_obj_name(source, old_pi));
}
sn_boundary_regs_init(&regs, design, boundary, result, top_inputs);
for (uint32_t i = 0; i < ci_count; i++)
{
sn_blast_boundary_bit_t bit = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, i);
if (bit.kind == SN_BLAST_BOUNDARY_TOP_PI)
{
assert(bit.signal.occurrence == 0 && top_inputs[bit.signal.object] != SN_INVALID_ID);
objects[i] = sn_module_add_slice(result, top_inputs[bit.signal.object], (int32_t)bit.signal.bit,
(int32_t)bit.signal.bit, "gate_pi_bit");
}
else if (bit.kind == SN_BLAST_BOUNDARY_REG_OUTPUT)
objects[i] = sn_boundary_reg_output_bit(&regs, bit.owner, bit.signal.bit);
else if (bit.kind == SN_BLAST_BOUNDARY_LOOP_OUTPUT)
objects[i] = sn_boundary_loop_output_bit(&regs, bit.owner, bit.signal.bit);
else if (bit.kind == SN_BLAST_BOUNDARY_PRIMITIVE_OUTPUT)
objects[i] = sn_boundary_primitive_output_bit(&regs, bit.owner, bit.port, bit.signal.bit);
else
assert(false);
}
gate_name = gate_names;
for (uint32_t i = 0; i < node_count; i++)
{
uint32_t count = fanin_counts[i];
sn_obj_id_t* fanins = count ? (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * count) : NULL;
assert(fanins || count == 0);
for (uint32_t k = 0; k < count; k++)
{
uint32_t fanin = fanin_indices[i][k];
assert(fanin < ci_count + i && objects[fanin] != SN_INVALID_ID);
fanins[k] = objects[fanin];
}
objects[ci_count + i] = sn_module_add_gate(result, count, fanins, gate_ids[i], gate_name);
free(fanins);
gate_name += strlen(gate_name) + 1;
}
uint32_t co_index = 0;
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
{
sn_obj_id_t old_po = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
uint32_t width = sn_obj_width(source, old_po);
sn_obj_id_t* bits = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * width);
assert(bits);
for (uint32_t bit = 0; bit < width; bit++)
{
sn_blast_boundary_bit_t endpoint = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, co_index);
assert(endpoint.kind == SN_BLAST_BOUNDARY_TOP_PO && endpoint.port == i && endpoint.signal.bit == bit);
assert(output_indices[co_index] < ci_count + node_count);
bits[bit] = objects[output_indices[co_index++]];
}
sn_obj_id_t driver = sn_lut_pack_bits(result, bits, width, "gate_po_word");
sn_module_add_po(result, width, sn_obj_is_signed(source, old_po), sn_obj_name(source, old_po), driver);
free(bits);
}
assert(co_index <= co_count);
sn_obj_id_t* co_drivers = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * co_count);
assert(co_drivers || co_count == 0);
for (uint32_t i = 0; i < co_count; i++)
{
assert(output_indices[i] < ci_count + node_count);
co_drivers[i] = objects[output_indices[i]];
}
sn_boundary_regs_finish(&regs, co_drivers);
result = sn_design_get_module(design, result_id);
free(co_drivers);
free(fanin_indices);
free(fanin_counts);
free(gate_ids);
free(objects);
free(top_inputs);
if (!sn_module_is_topo(result))
sn_design_reorder_module_topo(design, result_id);
assert(sn_module_is_topo(sn_design_get_module_const(design, result_id)));
return result_id;
}
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,407 +0,0 @@
/**CFile****************************************************************
FileName [snMiniLut.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Analysis and reconstruction of SN LUTs from MiniLUT networks.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snMiniLut.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef SN_MINI_LUT_H
#define SN_MINI_LUT_H
// Utilities for validating and analyzing the MiniLUT files written by ABC's
// "&write -l" command.
#include "snBoundary.h"
#include "aig/miniaig/minilut.h"
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
ABC_NAMESPACE_HEADER_START
typedef struct sn_lut_stats_t
{
uint32_t pi_count;
uint32_t po_count;
uint32_t register_count;
uint32_t lut_count;
uint32_t lut_size;
uint32_t lut_levels;
uint32_t top_output_levels;
uint32_t register_control_levels;
uint32_t memory_input_levels;
uint32_t primitive_input_levels;
uint32_t loop_input_levels;
uint32_t register_input_levels;
} sn_lut_stats_t;
static inline uint32_t sn_lut_max_u32(uint32_t a, uint32_t b)
{
return a > b ? a : b;
}
static inline Mini_Lut_t* sn_lut_load(const char* file_name)
{
if (!file_name)
return NULL;
FILE* file = fopen(file_name, "rb");
if (!file)
return NULL;
int32_t node_count = 0, register_count = 0, lut_size = 0;
bool valid = fread(&node_count, sizeof(node_count), 1, file) == 1 &&
fread(&register_count, sizeof(register_count), 1, file) == 1 &&
fread(&lut_size, sizeof(lut_size), 1, file) == 1;
uint64_t array_count = 0, truth_count = 0;
if (valid && node_count >= 2 && register_count >= 0 && register_count <= node_count && lut_size >= 2 &&
lut_size <= 16)
{
array_count = (uint64_t)(uint32_t)node_count * (uint32_t)lut_size;
truth_count = (uint64_t)(uint32_t)node_count * (uint32_t)Mini_LutWordNum(lut_size);
valid = array_count <= SIZE_MAX / sizeof(int) && truth_count <= SIZE_MAX / sizeof(unsigned);
}
else
valid = false;
if (valid)
{
uint64_t payload_bytes = (array_count + truth_count) * sizeof(uint32_t);
#if defined(_WIN32)
__int64 position = _ftelli64(file);
valid = position >= 0 && _fseeki64(file, 0, SEEK_END) == 0;
__int64 end = valid ? _ftelli64(file) : -1;
valid = end >= position && (uint64_t)(end - position) == payload_bytes &&
_fseeki64(file, position, SEEK_SET) == 0;
#else
long position = ftell(file);
valid = position >= 0 && fseek(file, 0, SEEK_END) == 0;
long end = valid ? ftell(file) : -1;
valid = end >= position && (uint64_t)(end - position) == payload_bytes && fseek(file, position, SEEK_SET) == 0;
#endif
}
Mini_Lut_t* lut = valid ? (Mini_Lut_t*)calloc(1, sizeof(Mini_Lut_t)) : NULL;
if (lut)
{
lut->nSize = lut->nCap = node_count;
lut->nRegs = register_count;
lut->LutSize = lut_size;
lut->pArray = (int*)malloc((size_t)array_count * sizeof(int));
lut->pTruths = (unsigned*)malloc((size_t)truth_count * sizeof(unsigned));
if (!lut->pArray || !lut->pTruths)
valid = false;
else
valid = fread(lut->pArray, sizeof(int), (size_t)array_count, file) == array_count &&
fread(lut->pTruths, sizeof(unsigned), (size_t)truth_count, file) == truth_count &&
fgetc(file) == EOF && !ferror(file);
}
if (fclose(file) != 0)
valid = false;
if (!valid || !lut)
{
if (lut)
Mini_LutStop(lut);
return NULL;
}
for (int object = 2; object < node_count; object++)
{
int* fanins = lut->pArray + (size_t)object * lut_size;
if (fanins[0] == MINI_LUT_NULL)
{
for (int i = 1; i < lut_size; i++)
valid &= fanins[i] == MINI_LUT_NULL;
continue;
}
if (fanins[0] < 0 || fanins[0] >= object)
valid = false;
else if (fanins[0] >= 2)
{
int* source = lut->pArray + (size_t)fanins[0] * lut_size;
if (source[0] != MINI_LUT_NULL && source[1] == MINI_LUT_NULL2)
valid = false;
}
if (fanins[1] == MINI_LUT_NULL2)
{
for (int i = 2; i < lut_size; i++)
valid &= fanins[i] == MINI_LUT_NULL;
continue;
}
bool padding = false;
for (int i = 0; i < lut_size; i++)
if (fanins[i] == MINI_LUT_NULL)
padding = true;
else if (padding || fanins[i] < 0 || fanins[i] >= object || fanins[i] == MINI_LUT_NULL2)
valid = false;
else if (fanins[i] >= 2)
{
int* source = lut->pArray + (size_t)fanins[i] * lut_size;
if (source[0] != MINI_LUT_NULL && source[1] == MINI_LUT_NULL2)
valid = false;
}
}
if (!valid)
{
Mini_LutStop(lut);
return NULL;
}
return lut;
}
static inline bool sn_lut_interface_matches(Mini_Lut_t* lut, const sn_blast_boundary_t* boundary)
{
if (!lut || !boundary)
return false;
uint32_t pi_count = 0, po_count = 0;
int object;
Mini_LutForEachPi(lut, object)
pi_count++;
Mini_LutForEachPo(lut, object)
po_count++;
uint32_t register_count = (uint32_t)Mini_LutRegNum(lut);
if (pi_count != boundary->cis.size || po_count != boundary->cos.size ||
register_count != boundary->register_bits || register_count > pi_count || register_count > po_count)
return false;
for (uint32_t i = 0; i < register_count; i++)
if (sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, pi_count - register_count + i).kind !=
SN_BLAST_BOUNDARY_REG_OUTPUT ||
sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, po_count - register_count + i).kind !=
SN_BLAST_BOUNDARY_REG_INPUT)
return false;
return true;
}
// Validates MiniLUT topology and its positional interface against the boundary
// saved while deriving the pre-ABC MiniAIG. Levels count LUTs; constants and
// CIs have level zero. The boundary CO vector is in the same order as MiniLUT
// POs, so depths can be reported separately for top outputs, hard-block inputs,
// register controls, and register inputs.
static inline sn_lut_stats_t sn_lut_analyze(Mini_Lut_t* lut, const sn_blast_boundary_t* boundary)
{
assert(lut && boundary);
assert(sn_lut_interface_matches(lut, boundary));
assert(Mini_LutSize(lut) >= 2 && Mini_LutSize(lut) <= 16);
size_t object_count = (size_t)Mini_LutNodeNum(lut);
uint32_t* levels = (uint32_t*)calloc(object_count, sizeof(uint32_t));
assert(levels);
sn_lut_stats_t stats = {0};
stats.lut_size = (uint32_t)Mini_LutSize(lut);
for (int object = 0; object < Mini_LutNodeNum(lut); object++)
{
if (Mini_LutNodeIsConst(lut, object))
continue;
if (Mini_LutNodeIsPi(lut, object))
{
stats.pi_count++;
continue;
}
if (Mini_LutNodeIsNode(lut, object))
{
uint32_t level = 0;
int fanin, slot;
Mini_LutForEachFanin(lut, object, fanin, slot)
{
assert(fanin >= 0 && fanin < object);
level = sn_lut_max_u32(level, levels[fanin]);
}
levels[object] = level + 1;
stats.lut_levels = sn_lut_max_u32(stats.lut_levels, levels[object]);
stats.lut_count++;
continue;
}
assert(Mini_LutNodeIsPo(lut, object));
int fanin = Mini_LutNodeFanin(lut, object, 0);
assert(fanin >= 0 && fanin < object);
levels[object] = levels[fanin];
stats.po_count++;
}
stats.register_count = (uint32_t)Mini_LutRegNum(lut);
uint32_t po_index = 0;
int object;
Mini_LutForEachPo(lut, object)
{
sn_blast_boundary_kind_t kind =
sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, po_index++).kind;
uint32_t level = levels[object];
if (kind == SN_BLAST_BOUNDARY_TOP_PO)
stats.top_output_levels = sn_lut_max_u32(stats.top_output_levels, level);
else if (kind == SN_BLAST_BOUNDARY_REG_CONTROL)
stats.register_control_levels = sn_lut_max_u32(stats.register_control_levels, level);
else if (kind == SN_BLAST_BOUNDARY_MEMORY_INPUT)
stats.memory_input_levels = sn_lut_max_u32(stats.memory_input_levels, level);
else if (kind == SN_BLAST_BOUNDARY_PRIMITIVE_INPUT)
stats.primitive_input_levels = sn_lut_max_u32(stats.primitive_input_levels, level);
else if (kind == SN_BLAST_BOUNDARY_LOOP_INPUT)
stats.loop_input_levels = sn_lut_max_u32(stats.loop_input_levels, level);
else if (kind == SN_BLAST_BOUNDARY_REG_INPUT)
stats.register_input_levels = sn_lut_max_u32(stats.register_input_levels, level);
else
assert(false);
}
assert(po_index == stats.po_count);
free(levels);
return stats;
}
static inline sn_obj_id_t sn_lut_pack_bits(sn_module_t* module, const sn_obj_id_t* bits, uint32_t width,
const char* name)
{
assert(width && bits);
if (width == 1)
return bits[0];
return sn_module_add_operator(module, SN_CONCAT, width, false, width, bits, name);
}
static inline uint64_t sn_lut_node_truth(Mini_Lut_t* lut, int object)
{
unsigned* words = Mini_LutNodeTruth(lut, object);
return (uint64_t)words[0] | (Mini_LutWordNum(Mini_LutSize(lut)) > 1 ? (uint64_t)words[1] << 32 : 0);
}
// Decomposes a mapped LUT wider than the physical SN_LUT6 primitive by Shannon expansion on its most-significant
// inputs. The leaves are LUT6 objects and each internal selector is another LUT3. MiniLUT and SN both use fanin 0 as
// the least-significant truth-table variable, so each cofactor is a contiguous truth-table interval.
static inline sn_obj_id_t sn_lut_add_physical_rec(sn_module_t* module, const sn_obj_id_t* fanins,
uint32_t count, const unsigned* truth, uint32_t offset)
{
assert(module && fanins && truth && count > 0 && count <= 16);
if (count <= 6)
{
uint64_t leaf_truth = 0;
for (uint32_t bit = 0; bit < (UINT32_C(1) << count); bit++)
leaf_truth |= (uint64_t)((truth[(offset + bit) >> 5] >> ((offset + bit) & 31)) & 1) << bit;
return sn_module_add_lut(module, count, fanins, leaf_truth, "lut");
}
uint32_t select_bit = count - 1;
sn_obj_id_t low = sn_lut_add_physical_rec(module, fanins, select_bit, truth, offset);
sn_obj_id_t high = sn_lut_add_physical_rec(module, fanins, select_bit, truth,
offset + (UINT32_C(1) << select_bit));
sn_obj_id_t mux_fanins[3] = {fanins[select_bit], high, low};
return sn_module_add_lut(module, 3, mux_fanins, UINT64_C(0xd8), "lut_wide_mux");
}
// Reconstructs the MiniLUT combinational network and its top-level/register
// boundary as a new flat SN module. Hard-block and control reconnection is
// added by subsequent reconstruction stages; this core establishes the direct
// MiniLUT-object-to-SN-object mapping and preserves MiniLUT register order.
static inline sn_module_id_t sn_design_add_lut_module(sn_design_t* design, sn_module_id_t source_top_id,
Mini_Lut_t* lut, const sn_blast_boundary_t* boundary,
const char* module_name)
{
assert(design && source_top_id < design->modules.size && lut && boundary && module_name);
sn_lut_analyze(lut, boundary);
const sn_module_t* source = sn_design_get_module_const(design, source_top_id);
sn_module_id_t result_id = sn_design_add_module(design, module_name);
sn_module_t* result = sn_design_get_module(design, result_id);
sn_obj_id_t* top_inputs = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * source->obj_types.size);
sn_obj_id_t* mini_objects = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * Mini_LutNodeNum(lut));
sn_obj_id_t* co_drivers = (sn_obj_id_t*)malloc(sizeof(sn_obj_id_t) * boundary->cos.size);
sn_boundary_regs_t regs;
assert(top_inputs && mini_objects && co_drivers);
for (size_t i = 0; i < source->obj_types.size; i++)
top_inputs[i] = SN_INVALID_ID;
for (int i = 0; i < Mini_LutNodeNum(lut); i++)
mini_objects[i] = SN_INVALID_ID;
for (size_t i = 0; i < source->type_objects[SN_PI].size; i++)
{
sn_obj_id_t old_pi = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PI], i);
top_inputs[old_pi] = sn_module_add_pi(result, sn_obj_width(source, old_pi), sn_obj_is_signed(source, old_pi),
sn_obj_name(source, old_pi));
}
sn_boundary_regs_init(&regs, design, boundary, result, top_inputs);
uint32_t zero_word = 0, one_word = 1;
mini_objects[Mini_LutNodeConst0()] = sn_module_add_const(result, 1, false, &zero_word, "lut_const0");
mini_objects[Mini_LutNodeConst1()] = sn_module_add_const(result, 1, false, &one_word, "lut_const1");
uint32_t ci_index = 0;
int mini_object;
Mini_LutForEachPi(lut, mini_object)
{
sn_blast_boundary_bit_t bit = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cis, ci_index++);
if (bit.kind == SN_BLAST_BOUNDARY_TOP_PI)
{
assert(bit.signal.occurrence == 0 && top_inputs[bit.signal.object] != SN_INVALID_ID);
mini_objects[mini_object] =
sn_module_add_slice(result, top_inputs[bit.signal.object], (int32_t)bit.signal.bit,
(int32_t)bit.signal.bit, "lut_pi_bit");
}
else if (bit.kind == SN_BLAST_BOUNDARY_REG_OUTPUT)
mini_objects[mini_object] = sn_boundary_reg_output_bit(&regs, bit.owner, bit.signal.bit);
else if (bit.kind == SN_BLAST_BOUNDARY_LOOP_OUTPUT)
mini_objects[mini_object] = sn_boundary_loop_output_bit(&regs, bit.owner, bit.signal.bit);
else if (bit.kind == SN_BLAST_BOUNDARY_PRIMITIVE_OUTPUT)
mini_objects[mini_object] =
sn_boundary_primitive_output_bit(&regs, bit.owner, bit.port, bit.signal.bit);
else
assert(false);
}
assert(ci_index == boundary->cis.size);
Mini_LutForEachNode(lut, mini_object)
{
sn_obj_id_t fanins[16];
int fanin, slot, count = 0;
Mini_LutForEachFanin(lut, mini_object, fanin, slot)
{
assert(count < 16 && mini_objects[fanin] != SN_INVALID_ID);
fanins[count++] = mini_objects[fanin];
}
mini_objects[mini_object] = count <= 6
? sn_module_add_lut(result, (uint32_t)count, fanins,
sn_lut_node_truth(lut, mini_object), "lut")
: sn_lut_add_physical_rec(result, fanins, (uint32_t)count,
Mini_LutNodeTruth(lut, mini_object), 0);
}
uint32_t co_index = 0;
Mini_LutForEachPo(lut, mini_object)
{
int fanin = Mini_LutNodeFanin(lut, mini_object, 0);
assert(mini_objects[fanin] != SN_INVALID_ID);
co_drivers[co_index++] = mini_objects[fanin];
}
assert(co_index == boundary->cos.size);
co_index = 0;
for (size_t i = 0; i < source->type_objects[SN_PO].size; i++)
{
sn_obj_id_t old_po = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_PO], i);
uint32_t width = sn_obj_width(source, old_po);
sn_obj_id_t* bits = co_drivers + co_index;
for (uint32_t bit = 0; bit < width; bit++)
{
sn_blast_boundary_bit_t endpoint = sn_vec_at(sn_blast_boundary_bit_t, &boundary->cos, co_index + bit);
assert(endpoint.kind == SN_BLAST_BOUNDARY_TOP_PO && endpoint.port == i && endpoint.signal.bit == bit);
}
co_index += width;
sn_obj_id_t driver = sn_lut_pack_bits(result, bits, width, "lut_po_word");
sn_module_add_po(result, width, sn_obj_is_signed(source, old_po), sn_obj_name(source, old_po), driver);
}
sn_boundary_regs_finish(&regs, co_drivers);
result = sn_design_get_module(design, result_id);
free(co_drivers);
free(mini_objects);
free(top_inputs);
if (!sn_module_is_topo(result))
sn_design_reorder_module_topo(design, result_id);
assert(sn_module_is_topo(sn_design_get_module_const(design, result_id)));
return result_id;
}
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,921 +0,0 @@
/**CFile****************************************************************
FileName [snMux.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Mux-path sharing and restructuring for word-level SN designs.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snMux.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef SN_MUX_H
#define SN_MUX_H
// Word-level mux-path sharing for register-fed SN_MUX trees and nested SN_PMUX objects. Root-to-terminal paths are
// enumerated, structurally equal LSB-first words are represented once, and their path conditions are ORed. A hold
// terminal is moved into SN_REG_ENABLE when controls are provably exclusive. General PMUX alternatives preserve SN's
// one-hot-select semantics; as for SN_PMUX itself, behavior for multi-hot selects is unspecified. Modules are
// duplicated and rewritten transactionally; hierarchy, stable module IDs, and the complete canonical register
// interface are preserved.
#include "sn.h"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
ABC_NAMESPACE_HEADER_START
typedef struct sn_share_options_t
{
uint32_t min_width;
uint32_t min_alternatives;
uint32_t min_saved_paths;
} sn_share_options_t;
typedef struct sn_share_stats_t
{
uint64_t modules;
uint64_t registers;
uint64_t muxes;
uint64_t paths_before;
uint64_t paths_after;
} sn_share_stats_t;
typedef struct sn_share_step_t
{
sn_obj_id_t select;
uint32_t bit;
bool positive;
} sn_share_step_t;
typedef struct sn_share_path_t
{
sn_obj_id_t term;
uint32_t step_offset;
uint32_t step_count;
uint32_t group;
} sn_share_path_t;
enum
{
SN_SHARE_MAX_PATHS = 1 << 20,
SN_SHARE_MAX_DEPTH = 4096,
SN_SHARE_MAX_STEPS = 1 << 24
};
static inline sn_share_options_t sn_share_default_options(void)
{
sn_share_options_t options = {4, 6, 2};
return options;
}
static inline sn_obj_id_t sn_share_strip_value(const sn_module_t* module, sn_obj_id_t object)
{
while (object != SN_INVALID_ID)
{
sn_obj_type_t type = sn_obj_type(module, object);
if ((type != SN_BUF && type != SN_POS && type != SN_CAST) || sn_obj_fanin_count(module, object) != 1 ||
sn_obj_width(module, object) != sn_obj_width(module, sn_obj_fanin(module, object, 0)))
break;
object = sn_obj_fanin(module, object, 0);
}
return object;
}
static inline bool sn_share_const_equal(const sn_module_t* module, sn_obj_id_t a, sn_obj_id_t b)
{
if (sn_obj_width(module, a) != sn_obj_width(module, b))
return false;
sn_obj_type_t ta = sn_obj_type(module, a), tb = sn_obj_type(module, b);
if ((ta != SN_CONST0 && ta != SN_CONST1 && ta != SN_CONST) ||
(tb != SN_CONST0 && tb != SN_CONST1 && tb != SN_CONST))
return false;
uint32_t width = sn_obj_width(module, a);
for (uint32_t bit = 0; bit < width; bit++)
{
bool av = (ta == SN_CONST1 && bit == 0) ||
(ta == SN_CONST && ((sn_const_words(module, a)[bit >> 5] >> (bit & 31)) & 1));
bool bv = (tb == SN_CONST1 && bit == 0) ||
(tb == SN_CONST && ((sn_const_words(module, b)[bit >> 5] >> (bit & 31)) & 1));
if (av != bv)
return false;
}
return true;
}
// Returns the unique raw selector value accepted by an equality comparison,
// accounting for the comparison's signed extension. A wider constant whose
// high bits cannot equal the extended selector makes the predicate impossible.
static inline bool sn_share_decode_value(const sn_module_t* module, sn_obj_id_t value,
sn_obj_id_t constant, uint32_t* decoded)
{
uint32_t value_width = sn_obj_width(module, value);
uint32_t constant_width = sn_obj_width(module, constant);
bool sign = sn_obj_is_signed(module, value) && sn_obj_is_signed(module, constant);
if (!value_width || value_width >= 31)
return false;
uint32_t result = 0;
for (uint32_t bit = 0; bit < value_width; bit++)
{
bool constant_bit = bit < constant_width ? sn_const_bit(module, constant, bit)
: sign && sn_const_bit(module, constant, constant_width - 1);
result |= (uint32_t)constant_bit << bit;
}
if (constant_width > value_width)
{
bool extension = sign && ((result >> (value_width - 1)) & 1);
for (uint32_t bit = value_width; bit < constant_width; bit++)
if (sn_const_bit(module, constant, bit) != extension)
return false;
}
*decoded = result;
return true;
}
// Structural word identity through the inexpensive wiring operators used heavily by Slang lowering. This is the
// object-level counterpart of UtilMux's canonical bit-vector IDs: separately-created slices/concatenations of the
// same LSB-first source bits are recognized as the same mux terminal without bit-blasting the module.
static inline bool sn_share_value_equal(const sn_module_t* module, sn_obj_id_t a, sn_obj_id_t b)
{
a = sn_share_strip_value(module, a);
b = sn_share_strip_value(module, b);
if (a == b)
return true;
if (sn_obj_width(module, a) != sn_obj_width(module, b))
return false;
sn_obj_type_t ta = sn_obj_type(module, a), tb = sn_obj_type(module, b);
if ((ta == SN_CONST0 || ta == SN_CONST1 || ta == SN_CONST) &&
(tb == SN_CONST0 || tb == SN_CONST1 || tb == SN_CONST))
return sn_share_const_equal(module, a, b);
if (ta != tb)
return false;
if (ta == SN_SLICE)
{
const sn_slice_info_t* ia = sn_obj_slice_info(module, a);
const sn_slice_info_t* ib = sn_obj_slice_info(module, b);
return ia->left_index == ib->left_index && ia->right_index == ib->right_index &&
sn_share_value_equal(module, sn_obj_fanin(module, a, 0), sn_obj_fanin(module, b, 0));
}
if (ta == SN_REPLICATE)
return sn_obj_repeat_count(module, a) == sn_obj_repeat_count(module, b) &&
sn_share_value_equal(module, sn_obj_fanin(module, a, 0), sn_obj_fanin(module, b, 0));
if (ta == SN_CONCAT && sn_obj_fanin_count(module, a) == sn_obj_fanin_count(module, b))
{
for (uint32_t i = 0; i < sn_obj_fanin_count(module, a); i++)
if (!sn_share_value_equal(module, sn_obj_fanin(module, a, i), sn_obj_fanin(module, b, i)))
return false;
return true;
}
return false;
}
static inline uint64_t sn_share_hash_mix(uint64_t hash, uint64_t value)
{
hash ^= value;
return hash * UINT64_C(1099511628211);
}
// Compute structural hashes for the inexpensive wiring words recognized by sn_share_value_equal(). Modules entering
// @opt_mux are topologically ordered, so every hashed wiring fanin is already available. Unsupported terminals retain
// object identity. Hash collisions are always resolved with the exact structural comparison.
static inline uint64_t* sn_share_value_hashes(const sn_module_t* module)
{
uint64_t* hashes = (uint64_t*)calloc(module->obj_types.size, sizeof(uint64_t));
assert(hashes || module->obj_types.size == 0);
for (sn_obj_id_t object = 0; object < module->obj_types.size; object++)
{
sn_obj_type_t type = sn_obj_type(module, object);
uint64_t hash = sn_share_hash_mix(UINT64_C(1469598103934665603), sn_obj_width(module, object));
if (type == SN_BUF || type == SN_POS || type == SN_CAST)
{
sn_obj_id_t fanin = sn_obj_fanin(module, object, 0);
hashes[object] = sn_obj_width(module, object) == sn_obj_width(module, fanin)
? hashes[fanin] : sn_share_hash_mix(hash, object);
continue;
}
if (type == SN_CONST0 || type == SN_CONST1 || type == SN_CONST)
{
uint32_t count = sn_const_word_count(sn_obj_width(module, object));
for (uint32_t i = 0; i < count; i++)
{
uint32_t word = type == SN_CONST ? sn_const_words(module, object)[i]
: type == SN_CONST1 && i == 0 ? 1 : 0;
if (i + 1 == count && (sn_obj_width(module, object) & 31))
word &= (UINT32_C(1) << (sn_obj_width(module, object) & 31)) - 1;
hash = sn_share_hash_mix(hash, word);
}
hashes[object] = hash;
continue;
}
hash = sn_share_hash_mix(hash, type);
if (type == SN_SLICE)
{
const sn_slice_info_t* info = sn_obj_slice_info(module, object);
hash = sn_share_hash_mix(hash, (uint32_t)info->left_index);
hash = sn_share_hash_mix(hash, (uint32_t)info->right_index);
hash = sn_share_hash_mix(hash, hashes[sn_obj_fanin(module, object, 0)]);
}
else if (type == SN_REPLICATE)
{
hash = sn_share_hash_mix(hash, sn_obj_repeat_count(module, object));
hash = sn_share_hash_mix(hash, hashes[sn_obj_fanin(module, object, 0)]);
}
else if (type == SN_CONCAT)
for (uint32_t i = 0; i < sn_obj_fanin_count(module, object); i++)
hash = sn_share_hash_mix(hash, hashes[sn_obj_fanin(module, object, i)]);
else
hash = sn_share_hash_mix(hash, object);
hashes[object] = hash;
}
return hashes;
}
static inline bool sn_share_hashed_equal(const sn_module_t* module, const uint64_t* hashes,
sn_obj_id_t a, sn_obj_id_t b)
{
a = sn_share_strip_value(module, a);
b = sn_share_strip_value(module, b);
return hashes[a] == hashes[b] && sn_share_value_equal(module, a, b);
}
// Recognize a binary decode. The equality predicates compare one common selector against distinct constants, so at
// most one PMUX select bit is true and ordinary combinational CEC is valid. An incomplete decode uses the PMUX default.
static inline bool sn_share_select_is_decode(const sn_module_t* module, sn_obj_id_t select)
{
if (sn_obj_type(module, select) != SN_CONCAT || sn_obj_fanin_count(module, select) < 2)
return false;
sn_obj_id_t common = SN_INVALID_ID;
sn_vec_t decoded_values;
sn_vec_init(&decoded_values);
for (uint32_t i = 0; i < sn_obj_fanin_count(module, select); i++)
{
sn_obj_id_t compare = sn_obj_fanin(module, select, i);
sn_obj_type_t type = sn_obj_type(module, compare);
if ((type != SN_EQ && type != SN_CASE_EQ) || sn_obj_fanin_count(module, compare) != 2)
{
sn_vec_destroy(&decoded_values);
return false;
}
sn_obj_id_t value = sn_obj_fanin(module, compare, 0), constant = sn_obj_fanin(module, compare, 1);
sn_obj_type_t constant_type = sn_obj_type(module, constant);
if (constant_type != SN_CONST0 && constant_type != SN_CONST1 && constant_type != SN_CONST)
{
sn_vec_destroy(&decoded_values);
return false;
}
if (common == SN_INVALID_ID)
common = value;
else if (sn_share_strip_value(module, value) != sn_share_strip_value(module, common) ||
sn_obj_width(module, value) != sn_obj_width(module, common) ||
sn_obj_is_signed(module, value) != sn_obj_is_signed(module, common))
{
sn_vec_destroy(&decoded_values);
return false;
}
uint32_t decoded;
if (!sn_share_decode_value(module, value, constant, &decoded))
continue;
for (size_t j = 0; j < decoded_values.size; j++)
if (sn_vec_at(uint32_t, &decoded_values, j) == decoded)
{
sn_vec_destroy(&decoded_values);
return false;
}
*sn_vec_push(uint32_t, &decoded_values) = decoded;
}
uint32_t width = sn_obj_width(module, common);
bool result = width < 31 && sn_obj_fanin_count(module, select) <= (UINT32_C(1) << width);
sn_vec_destroy(&decoded_values);
return result;
}
static inline bool sn_share_pmux_words(const sn_module_t* module, sn_obj_id_t pmux, sn_vec_t* words)
{
assert(sn_obj_type(module, pmux) == SN_PMUX);
sn_obj_id_t select = sn_obj_fanin(module, pmux, SN_PMUX_SELECT);
sn_obj_id_t packed = sn_obj_fanin(module, pmux, SN_PMUX_ALTERNATIVES);
uint32_t count = sn_obj_width(module, select), width = sn_obj_width(module, pmux);
sn_vec_init(words);
if (sn_obj_type(module, packed) != SN_CONCAT || sn_obj_fanin_count(module, packed) != count)
return false;
sn_vec_reserve(sn_obj_id_t, words, count);
for (uint32_t i = 0; i < count; i++)
{
sn_obj_id_t word = sn_obj_fanin(module, packed, i);
if (sn_obj_width(module, word) != width)
{
sn_vec_destroy(words);
sn_vec_init(words);
return false;
}
*sn_vec_push(sn_obj_id_t, words) = sn_share_strip_value(module, word);
}
return true;
}
static inline sn_obj_id_t sn_share_or(sn_module_t* module, const sn_obj_id_t* values, uint32_t count)
{
assert(count);
if (count == 1)
return values[0];
sn_vec_t level, next;
sn_vec_init(&level);
sn_vec_init(&next);
sn_vec_reserve(sn_obj_id_t, &level, count);
for (uint32_t i = 0; i < count; i++)
*sn_vec_push(sn_obj_id_t, &level) = values[i];
while (level.size > 1)
{
next.size = 0;
for (size_t i = 0; i < level.size; i += 2)
{
if (i + 1 == level.size)
*sn_vec_push(sn_obj_id_t, &next) = sn_vec_at(sn_obj_id_t, &level, i);
else
{
sn_obj_id_t fanins[2] = {sn_vec_at(sn_obj_id_t, &level, i),
sn_vec_at(sn_obj_id_t, &level, i + 1)};
*sn_vec_push(sn_obj_id_t, &next) =
sn_module_add_operator(module, SN_BIT_OR, 1, false, 2, fanins, NULL);
}
}
sn_vec_t swap = level;
level = next;
next = swap;
}
sn_obj_id_t result = sn_vec_at(sn_obj_id_t, &level, 0);
sn_vec_destroy(&level);
sn_vec_destroy(&next);
return result;
}
static inline sn_obj_id_t sn_share_and(sn_module_t* module, const sn_obj_id_t* values, uint32_t count)
{
assert(count);
if (count == 1)
return values[0];
sn_vec_t level, next;
sn_vec_init(&level);
sn_vec_init(&next);
for (uint32_t i = 0; i < count; i++)
*sn_vec_push(sn_obj_id_t, &level) = values[i];
while (level.size > 1)
{
next.size = 0;
for (size_t i = 0; i < level.size; i += 2)
{
if (i + 1 == level.size)
*sn_vec_push(sn_obj_id_t, &next) = sn_vec_at(sn_obj_id_t, &level, i);
else
{
sn_obj_id_t fanins[2] = {sn_vec_at(sn_obj_id_t, &level, i),
sn_vec_at(sn_obj_id_t, &level, i + 1)};
*sn_vec_push(sn_obj_id_t, &next) =
sn_module_add_operator(module, SN_BIT_AND, 1, false, 2, fanins, NULL);
}
}
sn_vec_t swap = level;
level = next;
next = swap;
}
sn_obj_id_t result = sn_vec_at(sn_obj_id_t, &level, 0);
sn_vec_destroy(&level);
sn_vec_destroy(&next);
return result;
}
static inline void sn_share_collect_mux_paths(const sn_module_t* module, sn_obj_id_t object, sn_vec_t* stack,
sn_vec_t* steps, sn_vec_t* paths, uint8_t* active, bool* exclusive,
bool* overflow)
{
if (*overflow)
return;
if (stack->size >= SN_SHARE_MAX_DEPTH || paths->size >= SN_SHARE_MAX_PATHS ||
steps->size > SN_SHARE_MAX_STEPS - stack->size)
{
*overflow = true;
return;
}
object = sn_share_strip_value(module, object);
if (sn_obj_type(module, object) == SN_MUX && !active[object])
{
active[object] = 1;
sn_share_step_t* step = sn_vec_push(sn_share_step_t, stack);
step->select = sn_obj_fanin(module, object, SN_MUX_SELECT);
step->bit = 0;
step->positive = true;
sn_share_collect_mux_paths(module, sn_obj_fanin(module, object, SN_MUX_SELECTED), stack, steps, paths,
active, exclusive, overflow);
sn_vec_at(sn_share_step_t, stack, stack->size - 1).positive = false;
sn_share_collect_mux_paths(module, sn_obj_fanin(module, object, SN_MUX_DEFAULT), stack, steps, paths,
active, exclusive, overflow);
stack->size--;
active[object] = 0;
return;
}
if (sn_obj_type(module, object) == SN_PMUX && !active[object])
{
sn_obj_id_t select = sn_obj_fanin(module, object, SN_PMUX_SELECT);
sn_vec_t words;
sn_vec_init(&words);
if (sn_share_pmux_words(module, object, &words))
{
if (!sn_share_select_is_decode(module, select))
*exclusive = false;
active[object] = 1;
for (uint32_t i = 0; i < words.size; i++)
{
sn_share_step_t* step = sn_vec_push(sn_share_step_t, stack);
step->select = select;
step->bit = i;
step->positive = true;
sn_share_collect_mux_paths(module, sn_vec_at(sn_obj_id_t, &words, i), stack, steps, paths, active,
exclusive, overflow);
stack->size--;
}
size_t old_stack_size = stack->size;
for (uint32_t i = 0; i < words.size; i++)
{
sn_share_step_t* step = sn_vec_push(sn_share_step_t, stack);
step->select = select;
step->bit = i;
step->positive = false;
}
sn_share_collect_mux_paths(module, sn_obj_fanin(module, object, SN_PMUX_DEFAULT), stack, steps, paths,
active, exclusive, overflow);
stack->size = old_stack_size;
active[object] = 0;
sn_vec_destroy(&words);
return;
}
sn_vec_destroy(&words);
}
assert(steps->size <= UINT32_MAX && stack->size <= UINT32_MAX);
sn_share_path_t* path = sn_vec_push(sn_share_path_t, paths);
path->term = object;
path->step_offset = (uint32_t)steps->size;
path->step_count = (uint32_t)stack->size;
path->group = SN_INVALID_ID;
sn_vec_reserve(sn_share_step_t, steps, steps->size + stack->size);
for (size_t i = 0; i < stack->size; i++)
*sn_vec_push(sn_share_step_t, steps) = sn_vec_at(sn_share_step_t, stack, i);
}
static inline sn_obj_id_t sn_share_path_condition(sn_module_t* target, const sn_module_t* source,
const sn_share_path_t* path, const sn_vec_t* steps)
{
sn_vec_t literals;
sn_vec_init(&literals);
for (uint32_t i = 0; i < path->step_count; i++)
{
sn_share_step_t step = sn_vec_at(sn_share_step_t, steps, path->step_offset + i);
sn_obj_id_t literal = sn_obj_dup(source, step.select);
if (sn_obj_width(target, literal) != 1)
literal = sn_module_add_slice(target, literal, (int32_t)step.bit, (int32_t)step.bit, NULL);
if (!step.positive)
literal = sn_module_add_operator(target, SN_LOG_NOT, 1, false, 1, &literal, NULL);
*sn_vec_push(sn_obj_id_t, &literals) = literal;
}
sn_obj_id_t result = sn_share_and(target, sn_vec_data(sn_obj_id_t, &literals), (uint32_t)literals.size);
sn_vec_destroy(&literals);
return result;
}
static inline bool sn_share_reg_mux_tree(sn_module_t* target, const sn_module_t* source, sn_obj_id_t old_reg,
const uint64_t* hashes, sn_share_options_t options, sn_share_stats_t* stats)
{
sn_obj_id_t old_in = sn_obj_pair_in(source, old_reg);
sn_obj_id_t old_root = sn_obj_fanin(source, old_in, 0);
if (old_root == SN_INVALID_ID || sn_obj_type(source, sn_share_strip_value(source, old_root)) != SN_MUX)
return false;
if (sn_obj_width(source, old_reg) < options.min_width)
return false;
sn_vec_t stack, steps, paths, terms, term_hashes, term_links, data_terms, controls;
sn_obj_id_t hold = SN_INVALID_ID, data = SN_INVALID_ID, new_reg = SN_INVALID_ID;
uint32_t* term_buckets = NULL;
uint32_t* group_heads = NULL;
uint32_t* path_links = NULL;
uint32_t term_bucket_count = 0;
size_t hold_index = 0;
bool exclusive = true, overflow = false;
sn_vec_init(&stack);
sn_vec_init(&steps);
sn_vec_init(&paths);
sn_vec_init(&terms);
sn_vec_init(&term_hashes);
sn_vec_init(&term_links);
sn_vec_init(&data_terms);
sn_vec_init(&controls);
uint8_t* active = (uint8_t*)calloc(source->obj_types.size, sizeof(uint8_t));
assert(active);
sn_share_collect_mux_paths(source, old_root, &stack, &steps, &paths, active, &exclusive, &overflow);
free(active);
if (overflow)
goto unchanged;
if (paths.size < options.min_alternatives)
goto unchanged;
term_bucket_count = 1;
while (term_bucket_count < 2 * paths.size)
term_bucket_count <<= 1;
term_buckets = (uint32_t*)malloc((size_t)term_bucket_count * sizeof(uint32_t));
assert(term_buckets);
memset(term_buckets, 0xff, (size_t)term_bucket_count * sizeof(uint32_t));
for (size_t i = 0; i < paths.size; i++)
{
sn_share_path_t* path = &sn_vec_at(sn_share_path_t, &paths, i);
sn_obj_id_t term = path->term;
uint64_t term_hash = hashes[sn_share_strip_value(source, term)];
uint32_t bucket = (uint32_t)term_hash & (term_bucket_count - 1);
uint32_t k;
for (k = term_buckets[bucket]; k != SN_INVALID_ID; k = sn_vec_at(uint32_t, &term_links, k))
if (sn_vec_at(uint64_t, &term_hashes, k) == term_hash &&
sn_share_value_equal(source, sn_vec_at(sn_obj_id_t, &terms, k), term))
break;
if (k == SN_INVALID_ID)
{
k = (uint32_t)terms.size;
*sn_vec_push(sn_obj_id_t, &terms) = term;
*sn_vec_push(uint64_t, &term_hashes) = term_hash;
*sn_vec_push(uint32_t, &term_links) = term_buckets[bucket];
term_buckets[bucket] = k;
}
path->group = k;
}
if (paths.size <= terms.size || paths.size - terms.size < options.min_saved_paths || paths.size < 2 * terms.size)
goto unchanged;
group_heads = (uint32_t*)malloc(terms.size * sizeof(uint32_t));
path_links = (uint32_t*)malloc(paths.size * sizeof(uint32_t));
assert(group_heads && path_links);
for (size_t k = 0; k < terms.size; k++)
group_heads[k] = SN_INVALID_ID;
for (size_t i = 0; i < paths.size; i++)
{
uint32_t group = sn_vec_at(sn_share_path_t, &paths, i).group;
assert(group < terms.size);
path_links[i] = group_heads[group];
group_heads[group] = (uint32_t)i;
}
hold = sn_share_strip_value(source, old_reg);
hold_index = terms.size;
if (exclusive)
for (size_t k = 0; k < terms.size; k++)
if (sn_share_hashed_equal(source, hashes, sn_vec_at(sn_obj_id_t, &terms, k), hold))
hold_index = k;
for (size_t k = 0; k < terms.size; k++)
{
if (k == hold_index)
continue;
sn_vec_t cubes;
sn_vec_init(&cubes);
for (uint32_t i = group_heads[k]; i != SN_INVALID_ID; i = path_links[i])
{
sn_share_path_t* path = &sn_vec_at(sn_share_path_t, &paths, i);
*sn_vec_push(sn_obj_id_t, &cubes) = sn_share_path_condition(target, source, path, &steps);
}
*sn_vec_push(sn_obj_id_t, &controls) =
sn_share_or(target, sn_vec_data(sn_obj_id_t, &cubes), (uint32_t)cubes.size);
*sn_vec_push(sn_obj_id_t, &data_terms) = sn_obj_dup(source, sn_vec_at(sn_obj_id_t, &terms, k));
sn_vec_destroy(&cubes);
}
if (!data_terms.size)
{
goto unchanged;
}
data = sn_vec_at(sn_obj_id_t, &data_terms, data_terms.size - 1);
if (data_terms.size > 1)
{
sn_obj_id_t packed_select =
sn_module_add_concat(target, (uint32_t)controls.size, sn_vec_data(sn_obj_id_t, &controls), NULL);
sn_obj_id_t packed_data =
sn_module_add_concat(target, (uint32_t)data_terms.size, sn_vec_data(sn_obj_id_t, &data_terms), NULL);
data = sn_module_add_pmux(target, packed_select, packed_data, data, NULL);
}
new_reg = sn_obj_dup(source, old_reg);
sn_obj_connect(target, sn_obj_pair_in(target, new_reg), 0, data);
if (hold_index < terms.size)
{
sn_obj_id_t update = sn_share_or(target, sn_vec_data(sn_obj_id_t, &controls), (uint32_t)controls.size);
sn_obj_id_t enable = sn_obj_fanin(target, new_reg, SN_REG_ENABLE);
if (enable != SN_INVALID_ID)
{
sn_obj_id_t fanins[2] = {enable, update};
update = sn_module_add_operator(target, SN_BIT_AND, 1, false, 2, fanins, NULL);
}
sn_reg_set_fanin(target, new_reg, SN_REG_ENABLE, update);
}
stats->registers++;
stats->muxes++;
stats->paths_before += paths.size;
stats->paths_after += terms.size;
sn_vec_destroy(&data_terms);
sn_vec_destroy(&controls);
sn_vec_destroy(&stack);
sn_vec_destroy(&steps);
sn_vec_destroy(&paths);
sn_vec_destroy(&terms);
sn_vec_destroy(&term_hashes);
sn_vec_destroy(&term_links);
free(path_links);
free(group_heads);
free(term_buckets);
return true;
unchanged:
sn_vec_destroy(&stack);
sn_vec_destroy(&steps);
sn_vec_destroy(&paths);
sn_vec_destroy(&terms);
sn_vec_destroy(&term_hashes);
sn_vec_destroy(&term_links);
free(path_links);
free(group_heads);
free(term_buckets);
sn_vec_destroy(&data_terms);
sn_vec_destroy(&controls);
return false;
}
static inline sn_obj_id_t sn_share_select_bit(sn_module_t* module, sn_obj_id_t select, uint32_t bit)
{
if (sn_obj_width(module, select) == 1)
return select;
return sn_module_add_slice(module, select, (int32_t)bit, (int32_t)bit, NULL);
}
static inline bool sn_share_reg_pmux(sn_module_t* target, const sn_module_t* source, sn_obj_id_t old_reg,
const uint64_t* hashes, sn_share_options_t options, sn_share_stats_t* stats)
{
sn_obj_id_t old_in = sn_obj_pair_in(source, old_reg);
sn_obj_id_t old_root = sn_obj_fanin(source, old_in, 0);
if (old_root != SN_INVALID_ID)
old_root = sn_share_strip_value(source, old_root);
if (old_root == SN_INVALID_ID || sn_obj_type(source, old_root) != SN_PMUX)
return false;
if (sn_obj_width(source, old_reg) < options.min_width)
return false;
sn_vec_t words;
if (!sn_share_pmux_words(source, old_root, &words))
return false;
uint32_t count = (uint32_t)words.size;
if (count < options.min_alternatives || count > UINT16_MAX)
{
sn_vec_destroy(&words);
return false;
}
sn_obj_id_t old_default = sn_share_strip_value(source, sn_obj_fanin(source, old_root, SN_PMUX_DEFAULT));
sn_obj_id_t old_hold = sn_share_strip_value(source, old_reg);
bool extracts_hold = sn_share_select_is_decode(source, sn_obj_fanin(source, old_root, SN_PMUX_SELECT)) &&
sn_share_hashed_equal(source, hashes, old_default, old_hold);
sn_vec_t unique, unique_hashes, unique_links, conditions, members;
sn_vec_init(&unique);
sn_vec_init(&unique_hashes);
sn_vec_init(&unique_links);
sn_vec_init(&conditions);
sn_vec_init(&members);
uint32_t bucket_count = 1;
while (bucket_count < 2 * count)
bucket_count <<= 1;
uint32_t* buckets = (uint32_t*)malloc((size_t)bucket_count * sizeof(uint32_t));
uint32_t* member_heads = NULL;
uint32_t* member_links = NULL;
assert(buckets);
memset(buckets, 0xff, (size_t)bucket_count * sizeof(uint32_t));
for (uint32_t i = 0; i < count; i++)
{
sn_obj_id_t value = sn_vec_at(sn_obj_id_t, &words, i);
if (extracts_hold && sn_share_hashed_equal(source, hashes, value, old_hold))
continue;
uint64_t value_hash = hashes[sn_share_strip_value(source, value)];
uint32_t bucket = (uint32_t)value_hash & (bucket_count - 1);
uint32_t k;
for (k = buckets[bucket]; k != SN_INVALID_ID; k = sn_vec_at(uint32_t, &unique_links, k))
if (sn_vec_at(uint64_t, &unique_hashes, k) == value_hash &&
sn_share_value_equal(source, sn_vec_at(sn_obj_id_t, &unique, k), value))
break;
if (k == SN_INVALID_ID)
{
k = (uint32_t)unique.size;
*sn_vec_push(sn_obj_id_t, &unique) = value;
*sn_vec_push(uint64_t, &unique_hashes) = value_hash;
*sn_vec_push(uint32_t, &unique_links) = buckets[bucket];
buckets[bucket] = k;
}
assert(k <= UINT16_MAX && i <= UINT16_MAX);
*sn_vec_push(uint32_t, &members) = ((uint32_t)k << 16) | i;
}
uint32_t after = (uint32_t)unique.size;
uint32_t before = count + 1;
if (!extracts_hold)
after++;
if (!unique.size || before <= after || before - after < options.min_saved_paths || before < 2 * after)
{
sn_vec_destroy(&words);
sn_vec_destroy(&unique);
sn_vec_destroy(&unique_hashes);
sn_vec_destroy(&unique_links);
sn_vec_destroy(&conditions);
sn_vec_destroy(&members);
free(buckets);
return false;
}
member_heads = (uint32_t*)malloc(unique.size * sizeof(uint32_t));
member_links = (uint32_t*)malloc(members.size * sizeof(uint32_t));
assert(member_heads && member_links);
for (size_t k = 0; k < unique.size; k++)
member_heads[k] = SN_INVALID_ID;
for (size_t j = 0; j < members.size; j++)
{
uint32_t group = sn_vec_at(uint32_t, &members, j) >> 16;
assert(group < unique.size);
member_links[j] = member_heads[group];
member_heads[group] = (uint32_t)j;
}
sn_obj_id_t new_reg = sn_obj_dup(source, old_reg);
sn_obj_id_t new_in = sn_obj_pair_in(target, new_reg);
sn_obj_id_t new_select = sn_obj_dup(source, sn_obj_fanin(source, old_root, SN_PMUX_SELECT));
for (size_t k = 0; k < unique.size; k++)
{
sn_vec_t bits;
sn_vec_init(&bits);
for (uint32_t j = member_heads[k]; j != SN_INVALID_ID; j = member_links[j])
{
uint32_t member = sn_vec_at(uint32_t, &members, j);
*sn_vec_push(sn_obj_id_t, &bits) = sn_share_select_bit(target, new_select, member & UINT16_MAX);
}
*sn_vec_push(sn_obj_id_t, &conditions) =
sn_share_or(target, sn_vec_data(sn_obj_id_t, &bits), (uint32_t)bits.size);
sn_vec_destroy(&bits);
}
sn_obj_id_t new_data;
if (unique.size == 1)
{
sn_obj_id_t alternative = sn_obj_dup(source, sn_vec_at(sn_obj_id_t, &unique, 0));
new_data = extracts_hold ? alternative
: sn_module_add_mux(target, sn_vec_at(sn_obj_id_t, &conditions, 0), alternative,
sn_obj_dup(source, old_default), NULL);
}
else
{
sn_vec_t alternatives;
sn_vec_init(&alternatives);
for (size_t k = 0; k < unique.size; k++)
*sn_vec_push(sn_obj_id_t, &alternatives) = sn_obj_dup(source, sn_vec_at(sn_obj_id_t, &unique, k));
sn_obj_id_t packed_select =
sn_module_add_concat(target, (uint32_t)conditions.size, sn_vec_data(sn_obj_id_t, &conditions), NULL);
sn_obj_id_t packed_data =
sn_module_add_concat(target, (uint32_t)alternatives.size, sn_vec_data(sn_obj_id_t, &alternatives), NULL);
sn_obj_id_t default_data = extracts_hold ? sn_vec_at(sn_obj_id_t, &alternatives, alternatives.size - 1)
: sn_obj_dup(source, old_default);
new_data = sn_module_add_pmux(target, packed_select, packed_data, default_data, NULL);
sn_vec_destroy(&alternatives);
}
sn_obj_connect(target, new_in, 0, new_data);
if (extracts_hold)
{
sn_obj_id_t update =
sn_share_or(target, sn_vec_data(sn_obj_id_t, &conditions), (uint32_t)conditions.size);
sn_obj_id_t enable = sn_obj_fanin(target, new_reg, SN_REG_ENABLE);
if (enable != SN_INVALID_ID)
{
sn_obj_id_t fanins[2] = {enable, update};
update = sn_module_add_operator(target, SN_BIT_AND, 1, false, 2, fanins, NULL);
}
sn_reg_set_fanin(target, new_reg, SN_REG_ENABLE, update);
}
stats->registers++;
stats->muxes++;
stats->paths_before += before;
stats->paths_after += after;
sn_vec_destroy(&words);
sn_vec_destroy(&unique);
sn_vec_destroy(&unique_hashes);
sn_vec_destroy(&unique_links);
sn_vec_destroy(&conditions);
sn_vec_destroy(&members);
free(member_links);
free(member_heads);
free(buckets);
return true;
}
static inline void sn_share_replace_module(sn_design_t* design, sn_module_id_t old_id, sn_module_id_t new_id)
{
assert(new_id + 1 == design->modules.size && old_id != new_id);
sn_module_t* old_module = sn_design_get_module(design, old_id);
sn_module_t* new_module = sn_design_get_module(design, new_id);
sn_name_id_t temporary_name_id = new_module->name;
sn_name_id_t name = old_module->name;
bool interface_locked = old_module->interface_locked;
sn_design_invalidate_copies_to_module(design, old_id);
sn_module_destroy(old_module);
free(old_module);
new_module->id = old_id;
new_module->name = name;
new_module->interface_locked = interface_locked;
sn_vec_at(sn_module_t*, &design->modules, old_id) = new_module;
design->modules.size--;
sn_name_remove_last(&design->names, temporary_name_id);
}
static inline bool sn_share_module_has_candidate(const sn_module_t* module, sn_share_options_t options)
{
for (size_t i = 0; i < module->type_objects[SN_REG_OUT].size; i++)
{
sn_obj_id_t reg = sn_vec_at(sn_obj_id_t, &module->type_objects[SN_REG_OUT], i);
if (sn_obj_width(module, reg) < options.min_width)
continue;
sn_obj_id_t root = sn_obj_fanin(module, sn_obj_pair_in(module, reg), 0);
if (root == SN_INVALID_ID)
continue;
root = sn_share_strip_value(module, root);
if (sn_obj_type(module, root) == SN_MUX)
return true;
if (sn_obj_type(module, root) == SN_PMUX)
{
sn_obj_id_t select = sn_obj_fanin(module, root, SN_PMUX_SELECT);
sn_obj_id_t alternatives = sn_obj_fanin(module, root, SN_PMUX_ALTERNATIVES);
uint32_t count = sn_obj_width(module, select);
if (count >= options.min_alternatives &&
(uint64_t)count * sn_obj_width(module, root) == sn_obj_width(module, alternatives))
return true;
}
}
return false;
}
static inline bool sn_design_share_module(sn_design_t* design, sn_module_id_t module_id,
sn_share_options_t options, sn_share_stats_t* stats)
{
sn_module_t* source = sn_design_get_module(design, module_id);
if (!sn_share_module_has_candidate(source, options))
return false;
char name[96];
uint32_t suffix = 0;
do
{
int length = snprintf(name, sizeof(name), "__sn_share_%u_%u", module_id, suffix++);
assert(length > 0 && (size_t)length < sizeof(name) && suffix != 0);
(void)length;
} while (sn_name_find(&design->names, name) != SN_INVALID_ID);
sn_module_id_t target_id = sn_design_dup_module_topo(design, module_id, name);
sn_module_t* target = sn_design_get_module(design, target_id);
uint64_t* hashes = sn_share_value_hashes(source);
bool changed = false;
for (size_t i = 0; i < source->type_objects[SN_REG_OUT].size; i++)
{
sn_obj_id_t reg = sn_vec_at(sn_obj_id_t, &source->type_objects[SN_REG_OUT], i);
bool reg_changed = sn_share_reg_mux_tree(target, source, reg, hashes, options, stats);
if (!reg_changed)
reg_changed = sn_share_reg_pmux(target, source, reg, hashes, options, stats);
changed |= reg_changed;
}
free(hashes);
if (!changed)
{
sn_name_id_t temporary_name_id = target->name;
sn_module_destroy(target);
free(target);
design->modules.size--;
sn_name_remove_last(&design->names, temporary_name_id);
sn_vec_destroy(&source->copy_ids);
sn_vec_init(&source->copy_ids);
source->copy_module = SN_INVALID_ID;
return false;
}
sn_share_replace_module(design, module_id, target_id);
// Do not use observable-cone cleanup here: even a constant or externally unobservable register is part of the
// canonical transition interface used by pre/post CEC. Reordering preserves every pair and its type ID. Dangling
// mux objects retained by this first implementation are harmless because hierarchical blasting is demand-driven.
sn_design_reorder_module_topo(design, module_id);
stats->modules++;
return true;
}
static inline sn_share_stats_t sn_design_share(sn_design_t* design, sn_share_options_t options)
{
assert(design && sn_design_is_topo(design));
sn_share_stats_t stats = {0};
size_t module_count = design->modules.size;
for (sn_module_id_t module = 0; module < module_count; module++)
sn_design_share_module(design, module, options, &stats);
assert(design->modules.size == module_count && sn_design_is_topo(design));
return stats;
}
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,148 +0,0 @@
/**CFile****************************************************************
FileName [snPth.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Bounded worker support for parallel SN mapping jobs.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snPth.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef SN_PTH_H
#define SN_PTH_H
// Small self-contained pthread scheduler for SN passes. The requested process count includes the coordinating caller,
// so P > 1 creates exactly P-1 workers. Windows and builds without ABC_USE_PTHREADS compile this scheduler as a
// sequential loop, avoiding any SN dependency on pthreads while retaining full P=1 functionality.
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#if defined(ABC_USE_PTHREADS) && !defined(_WIN32)
#define SN_PTH_USE_THREADS 1
#include <pthread.h>
#else
#define SN_PTH_USE_THREADS 0
#endif
ABC_NAMESPACE_HEADER_START
typedef void (*sn_pth_job_fn)(void* context, void* job);
typedef struct sn_pth_pool_t
{
void** jobs;
size_t count;
size_t next;
void* context;
sn_pth_job_fn function;
#if SN_PTH_USE_THREADS
pthread_mutex_t mutex;
#endif
} sn_pth_pool_t;
#if SN_PTH_USE_THREADS
static inline void* sn_pth_worker(void* argument)
{
sn_pth_pool_t* pool = (sn_pth_pool_t*)argument;
for (;;)
{
size_t index;
int status = pthread_mutex_lock(&pool->mutex);
if (status != 0)
return NULL;
index = pool->next++;
status = pthread_mutex_unlock(&pool->mutex);
assert(status == 0);
(void)status;
if (index >= pool->count)
return NULL;
pool->function(pool->context, pool->jobs[index]);
}
}
#endif
static inline int sn_pth_parallel_available(void)
{
return SN_PTH_USE_THREADS;
}
static inline void sn_pth_process(void** jobs, size_t count, unsigned processes,
sn_pth_job_fn function, void* context)
{
assert((jobs || count == 0) && processes >= 1 && function);
#if !SN_PTH_USE_THREADS
(void)processes;
for (size_t i = 0; i < count; i++)
function(context, jobs[i]);
#else
if (processes == 1 || count < 2)
{
for (size_t i = 0; i < count; i++)
function(context, jobs[i]);
return;
}
unsigned worker_count = processes - 1;
if (worker_count > count)
worker_count = (unsigned)count;
sn_pth_pool_t pool;
pool.jobs = jobs;
pool.count = count;
pool.next = 0;
pool.context = context;
pool.function = function;
int status = pthread_mutex_init(&pool.mutex, NULL);
if (status != 0)
{
for (size_t i = 0; i < count; i++)
function(context, jobs[i]);
return;
}
pthread_t* workers = (pthread_t*)malloc(sizeof(pthread_t) * worker_count);
if (!workers)
{
status = pthread_mutex_destroy(&pool.mutex);
assert(status == 0);
(void)status;
for (size_t i = 0; i < count; i++)
function(context, jobs[i]);
return;
}
unsigned created = 0;
for (; created < worker_count; created++)
{
if (pthread_create(&workers[created], NULL, sn_pth_worker, &pool) != 0)
break;
}
for (unsigned i = 0; i < created; i++)
{
int status = pthread_join(workers[i], NULL);
assert(status == 0);
(void)status;
}
// A worker that could not use the mutex leaves its unclaimed suffix for the coordinator.
while (pool.next < count)
function(context, jobs[pool.next++]);
status = pthread_mutex_destroy(&pool.mutex);
assert(status == 0);
(void)status;
free(workers);
#endif
}
#undef SN_PTH_USE_THREADS
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -1,137 +0,0 @@
/**CFile****************************************************************
FileName [snTech.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [New word-level design interface.]
Synopsis [Target-technology descriptions for SN mapping passes.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: snTech.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef SN_TECH_H
#define SN_TECH_H
// Technology-independent descriptions used by the SN memory and DSP mappers.
// These describe legal primitive configurations and mapping costs; they do not
// describe device placement or the total number of resources on a die.
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "misc/util/abc_namespaces.h"
ABC_NAMESPACE_HEADER_START
typedef enum sn_mem_port_mode_t
{
SN_MEM_PORT_SINGLE = 0,
SN_MEM_PORT_SIMPLE_DUAL,
SN_MEM_PORT_TRUE_DUAL
} sn_mem_port_mode_t;
typedef enum sn_mem_read_write_mode_t
{
SN_MEM_READ_WRITE_NO_CHANGE = 0,
SN_MEM_READ_WRITE_READ_FIRST,
SN_MEM_READ_WRITE_WRITE_FIRST
} sn_mem_read_write_mode_t;
typedef struct sn_mem_tech_t
{
const char* name;
uint32_t cap_bits;
uint32_t address_bits;
const uint32_t* widths;
size_t width_count;
sn_mem_port_mode_t port_mode;
uint32_t byte_width;
bool synchronous_read;
bool has_clock_enable;
bool has_byte_enable;
bool supports_init;
bool supports_read_first;
bool supports_write_first;
bool supports_no_change;
uint32_t mapping_cost;
const uint32_t* simple_dual_widths;
size_t simple_dual_width_count;
} sn_mem_tech_t;
typedef struct sn_dsp_tech_t
{
const char* name;
uint32_t a_width;
uint32_t b_width;
uint32_t p_width;
uint32_t preadder_width;
uint32_t min_a_width;
uint32_t min_b_width;
uint32_t min_p_width;
bool signed_only;
bool has_preadder;
bool has_postadder;
bool has_simd;
bool has_cascade;
uint32_t max_cascade_length;
uint32_t latency;
uint32_t mapping_cost;
} sn_dsp_tech_t;
typedef struct sn_carry_tech_t
{
const char* name;
uint32_t width;
uint32_t min_op_width;
uint32_t mapping_cost;
} sn_carry_tech_t;
typedef struct sn_tech_t
{
const sn_mem_tech_t* memories;
size_t memory_count;
const sn_dsp_tech_t* dsps;
size_t dsp_count;
const sn_carry_tech_t* carries;
size_t carry_count;
} sn_tech_t;
// AMD/Xilinx UltraScale+ primitives used by the initial mapper. Width lists
// follow the legal BRAM/URAM port widths in the Yosys Xilinx memory library.
static inline sn_tech_t sn_tech_xilinx_ultrascale(void)
{
static const uint32_t bram18_widths[] = {1, 2, 4, 9, 18};
static const uint32_t bram36_widths[] = {1, 2, 4, 9, 18, 36};
static const uint32_t bram18_sdp_widths[] = {1, 2, 4, 9, 18, 36};
static const uint32_t bram36_sdp_widths[] = {1, 2, 4, 9, 18, 36, 72};
static const uint32_t uram_widths[] = {72, 144};
static const sn_mem_tech_t memories[] = {
{"RAMB18E2", 18u * 1024u, 14, bram18_widths, 5, SN_MEM_PORT_TRUE_DUAL, 9, true, true, true, true, true,
true, true, 129, bram18_sdp_widths, 6},
{"RAMB36E2", 36u * 1024u, 15, bram36_widths, 6, SN_MEM_PORT_TRUE_DUAL, 9, true, true, true, true, true,
true, true, 257, bram36_sdp_widths, 7},
{"URAM288", 288u * 1024u, 12, uram_widths, 2, SN_MEM_PORT_TRUE_DUAL, 9, true, true, true, true, false,
true, true, 1024, NULL, 0},
};
static const sn_dsp_tech_t dsps[] = {
{"DSP48E2", 27, 18, 48, 27, 2, 2, 9, true, true, true, true, true, 20, 0, 1},
};
static const sn_carry_tech_t carries[] = {{"CARRY4", 4, 3, 1}};
sn_tech_t result = {memories, sizeof(memories) / sizeof(memories[0]), dsps, sizeof(dsps) / sizeof(dsps[0]),
carries, sizeof(carries) / sizeof(carries[0])};
return result;
}
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -482,11 +482,6 @@ private:
for ( uint32_t i = 0; i < num_vars; ++i ) for ( uint32_t i = 0; i < num_vars; ++i )
{ {
pComb[i] = pInvPerm[i] = i; pComb[i] = pInvPerm[i] = i;
/* bestPerm is written only when some combination beats the initial
* best_cost. When none does, the loop below still evaluates
* permutations[bestPerm[i]], which reads uninitialised stack and then
* indexes permutations[] with it. Seed the identity permutation. */
bestPerm[i] = i;
} }
/* early bail-out conditions */ /* early bail-out conditions */
@ -1322,10 +1317,7 @@ private:
{ {
auto mask = *tt.begin(); auto mask = *tt.begin();
/* Replicate within the word only. Variables 6 and above are replicated by the for ( auto i = real_num_vars; i < num_vars; ++i )
* std::fill below, and shifting a 64-bit word by (1 << i) for i >= 6 is undefined
* behaviour rather than a no-op. */
for ( auto i = real_num_vars; i < std::min( num_vars, 6u ); ++i )
{ {
mask |= ( mask << ( 1 << i ) ); mask |= ( mask << ( 1 << i ) );
} }

View File

@ -121,8 +121,9 @@ namespace eSLIM {
} }
std::vector<bool> DelayEngine::reduceDelay(unsigned int max_size, unsigned int initial_delay) { std::vector<bool> DelayEngine::reduceDelay(unsigned int max_size, unsigned int initial_delay) {
assert (delay_selectors.find(initial_delay) != delay_selectors.end());
std::vector<bool> last_model; std::vector<bool> last_model;
for( auto it = delay_selectors.lower_bound(initial_delay); it != delay_selectors.end(); ++it ) { for( auto it = delay_selectors.find(initial_delay); it != delay_selectors.end(); ++it ) {
int d = it->first; int d = it->first;
double timeout = getDynamicTimeout(max_size); double timeout = getDynamicTimeout(max_size);
int status = existsReplacement(max_size, d, timeout); int status = existsReplacement(max_size, d, timeout);

View File

@ -202,24 +202,6 @@ pMan->timeEvalMuxAn += Abc_Clock() - clk;
assert( pResMux == NULL || pResDsd == NULL ); assert( pResMux == NULL || pResDsd == NULL );
if ( pResMux ) if ( pResMux )
{ {
// Lpk_MuxAnalize() decides feasibility from the cached cofactor supports in
// p->puSupps. Those may have come from Lpk_ComputeSupports(), which derives
// them from two BDDs built in opposite variable orders and stitches the halves
// together, and that estimate can be a strict SUBSET of the true cofactor
// support. When it is, the component retained by the split below ends up with
// no vacant fanin slot for the component that is split off, and Lpk_MuxSplit()
// fails its assertion `iVarVac < (int)p->nVars'. Re-derive the one support the
// split actually depends on and decline the MUX decomposition if it does not fit.
unsigned * pTruthThis = Lpk_FunTruth( p, 0 );
unsigned * pTruthCof = Lpk_FunTruth( p, 1 );
unsigned uSuppExact;
if ( pResMux->Polarity )
Kit_TruthCofactor1New( pTruthCof, pTruthThis, p->nVars, pResMux->Variable );
else
Kit_TruthCofactor0New( pTruthCof, pTruthThis, p->nVars, pResMux->Variable );
uSuppExact = Kit_TruthSupport( pTruthCof, p->nVars ) | ( 1 << pResMux->Variable );
if ( Kit_WordCountOnes( uSuppExact ) >= (int)p->nVars )
return 0;
clk = Abc_Clock(); clk = Abc_Clock();
p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity ); p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity );
pMan->timeEvalMuxSp += Abc_Clock() - clk; pMan->timeEvalMuxSp += Abc_Clock() - clk;