summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2018-06-16 18:47:23 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2018-06-16 18:47:23 -0700
commit28a1307a61cbc5b3a027f21a3b1ce74c58a52d03 (patch)
tree72cc915495dad48cba2bd663f57dbf21dbeee3bf /src
parentf4a267d5815e5041c499e12322d70d7996093473 (diff)
downloadabc-28a1307a61cbc5b3a027f21a3b1ce74c58a52d03.tar.gz
abc-28a1307a61cbc5b3a027f21a3b1ce74c58a52d03.tar.bz2
abc-28a1307a61cbc5b3a027f21a3b1ce74c58a52d03.zip
Command %blastmem for bit-blasting small memories.
Diffstat (limited to 'src')
-rw-r--r--src/base/wlc/wlcCom.c48
-rw-r--r--src/base/wlc/wlcMem.c127
-rw-r--r--src/base/wlc/wlcNtk.c5
-rw-r--r--src/base/wlc/wlcWriteVer.c3
4 files changed, 182 insertions, 1 deletions
diff --git a/src/base/wlc/wlcCom.c b/src/base/wlc/wlcCom.c
index 52214d2d..06c2346b 100644
--- a/src/base/wlc/wlcCom.c
+++ b/src/base/wlc/wlcCom.c
@@ -38,6 +38,7 @@ static int Abc_CommandPdrAbs ( Abc_Frame_t * pAbc, int argc, char ** argv )
static int Abc_CommandAbs2 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMemAbs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandBlast ( Abc_Frame_t * pAbc, int argc, char ** argv );
+static int Abc_CommandBlastMem ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandGraft ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandProfile ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv );
@@ -82,6 +83,7 @@ void Wlc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Word level", "%abs2", Abc_CommandAbs2, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%memabs", Abc_CommandMemAbs, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%blast", Abc_CommandBlast, 0 );
+ Cmd_CommandAdd( pAbc, "Word level", "%blastmem", Abc_CommandBlastMem, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%graft", Abc_CommandGraft, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%profile", Abc_CommandProfile, 0 );
Cmd_CommandAdd( pAbc, "Word level", "%short_names", Abc_CommandShortNames, 0 );
@@ -1115,6 +1117,52 @@ usage:
SeeAlso []
******************************************************************************/
+int Abc_CommandBlastMem( Abc_Frame_t * pAbc, int argc, char ** argv )
+{
+ extern Wlc_Ntk_t * Wlc_NtkMemBlast( Wlc_Ntk_t * p );
+ Wlc_Ntk_t * pNtk = Wlc_AbcGetNtk(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 ( pNtk == NULL )
+ {
+ Abc_Print( 1, "Abc_CommandGraft(): There is no current design.\n" );
+ return 0;
+ }
+ pNtk = Wlc_NtkMemBlast( pNtk );
+ Wlc_AbcUpdateNtk( pAbc, pNtk );
+ return 0;
+usage:
+ Abc_Print( -2, "usage: %%blastmem [-vh]\n" );
+ Abc_Print( -2, "\t performs blasting of memory read/write ports\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 Abc_CommandGraft( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern Wlc_Ntk_t * Wlc_NtkGraftMulti( Wlc_Ntk_t * p, int fVerbose );
diff --git a/src/base/wlc/wlcMem.c b/src/base/wlc/wlcMem.c
index 9ce1764a..ccc319e5 100644
--- a/src/base/wlc/wlcMem.c
+++ b/src/base/wlc/wlcMem.c
@@ -35,6 +35,133 @@ ABC_NAMESPACE_IMPL_START
/**Function*************************************************************
+ Synopsis [Memory blasting.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Wlc_NtkMemBlast_rec( Wlc_Ntk_t * pNew, Wlc_Ntk_t * p, int iObj, Vec_Int_t * vFanins )
+{
+ Wlc_Obj_t * pObj;
+ int i, iFanin;
+ if ( Wlc_ObjCopy(p, iObj) )
+ return;
+ pObj = Wlc_NtkObj( p, iObj );
+ Wlc_ObjForEachFanin( pObj, iFanin, i )
+ Wlc_NtkMemBlast_rec( pNew, p, iFanin, vFanins );
+ if ( pObj->Type == WLC_OBJ_WRITE )
+ {
+ Vec_Int_t * vTemp = Vec_IntAlloc( 1 );
+ Vec_Int_t * vBits = Vec_IntAlloc( 100 );
+ Wlc_Obj_t * pMem = Wlc_ObjFanin0(p, pObj);
+ Wlc_Obj_t * pAddr = Wlc_ObjFanin1(p, pObj);
+ Wlc_Obj_t * pData = Wlc_ObjFanin2(p, pObj);
+ int DataW = Wlc_ObjRange(pData);
+ int AddrW = Wlc_ObjRange(pAddr);
+ int nRegs = 1 << AddrW, iObjNew, iObjDec;
+ assert( nRegs * DataW == Wlc_ObjRange(pMem) );
+ assert( Wlc_ObjRange(pObj) == Wlc_ObjRange(pMem) );
+ // create decoder
+ iObjDec = Wlc_ObjAlloc( pNew, WLC_OBJ_DEC, 0, nRegs-1, 0 );
+ Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pAddr)) );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjDec), vTemp );
+ // create decoder bits
+ for ( i = 0; i < nRegs; i++ )
+ {
+ int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i, i );
+ Vec_IntFill( vTemp, 1, iObjDec );
+ Vec_IntPushTwo( vTemp, i, i );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp );
+ Vec_IntPush( vBits, iObj2 );
+ }
+ // create data words
+ Vec_IntClear( vFanins );
+ for ( i = 0; i < nRegs; i++ )
+ {
+ int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i*DataW+DataW-1, i*DataW );
+ Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pMem)) );
+ Vec_IntPushTwo( vTemp, i*DataW+DataW-1, i*DataW );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp );
+ Vec_IntPush( vFanins, iObj2 );
+ }
+ // create MUXes of data words controlled by decoder bits
+ for ( i = 0; i < nRegs; i++ )
+ {
+ int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_MUX, 0, DataW-1, 0 );
+ Vec_IntFill( vTemp, 1, Vec_IntEntry(vBits, i) );
+ Vec_IntPushTwo( vTemp, Wlc_ObjCopy(p, Wlc_ObjId(p, pData)), Vec_IntEntry(vFanins, i) );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp );
+ Vec_IntWriteEntry( vFanins, i, iObj2 );
+ }
+ // concatenate the results
+ iObjNew = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_CONCAT, 0, nRegs*DataW-1, 0 );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjNew), vFanins );
+ Wlc_ObjSetCopy( p, iObj, iObjNew );
+ Vec_IntFree( vTemp );
+ Vec_IntFree( vBits );
+ }
+ else if ( pObj->Type == WLC_OBJ_READ )
+ {
+ Vec_Int_t * vTemp = Vec_IntAlloc( 1 );
+ Wlc_Obj_t * pMem = Wlc_ObjFanin0(p, pObj);
+ Wlc_Obj_t * pAddr = Wlc_ObjFanin1(p, pObj);
+ int DataW = Wlc_ObjRange(pObj);
+ int AddrW = Wlc_ObjRange(pAddr);
+ int nRegs = 1 << AddrW, iObjNew;
+ assert( nRegs * DataW == Wlc_ObjRange(pMem) );
+ Vec_IntClear( vFanins );
+ Vec_IntPush( vFanins, Wlc_ObjCopy(p, Wlc_ObjId(p, pAddr)) );
+ for ( i = 0; i < nRegs; i++ )
+ {
+ int iObj2 = Wlc_ObjAlloc( pNew, WLC_OBJ_BIT_SELECT, 0, i*DataW+DataW-1, i*DataW );
+ Vec_IntFill( vTemp, 1, Wlc_ObjCopy(p, Wlc_ObjId(p, pMem)) );
+ Vec_IntPushTwo( vTemp, i*DataW+DataW-1, i*DataW );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObj2), vTemp );
+ Vec_IntPush( vFanins, iObj2 );
+ }
+ iObjNew = Wlc_ObjAlloc( pNew, WLC_OBJ_MUX, 0, DataW-1, 0 );
+ Wlc_ObjAddFanins( pNew, Wlc_NtkObj(pNew, iObjNew), vFanins );
+ Wlc_ObjSetCopy( p, iObj, iObjNew );
+ Vec_IntFree( vTemp );
+ }
+ else
+ Wlc_ObjDup( pNew, p, iObj, vFanins );
+}
+Wlc_Ntk_t * Wlc_NtkMemBlast( Wlc_Ntk_t * p )
+{
+ Wlc_Ntk_t * pNew;
+ Wlc_Obj_t * pObj;
+ Vec_Int_t * vFanins;
+ int i;
+ Wlc_NtkCleanCopy( p );
+ vFanins = Vec_IntAlloc( 100 );
+ pNew = Wlc_NtkAlloc( p->pName, p->nObjsAlloc );
+ pNew->fSmtLib = p->fSmtLib;
+ pNew->fMemPorts = p->fMemPorts;
+ pNew->fEasyFfs = p->fEasyFfs;
+ Wlc_NtkForEachCi( p, pObj, i )
+ Wlc_ObjDup( pNew, p, Wlc_ObjId(p, pObj), vFanins );
+ Wlc_NtkForEachCo( p, pObj, i )
+ Wlc_NtkMemBlast_rec( pNew, p, Wlc_ObjId(p, pObj), vFanins );
+ Wlc_NtkForEachCo( p, pObj, i )
+ Wlc_ObjSetCo( pNew, Wlc_ObjCopyObj(pNew, p, pObj), pObj->fIsFi );
+ if ( p->vInits )
+ pNew->vInits = Vec_IntDup( p->vInits );
+ if ( p->pInits )
+ pNew->pInits = Abc_UtilStrsav( p->pInits );
+ Vec_IntFree( vFanins );
+ if ( p->pSpec )
+ pNew->pSpec = Abc_UtilStrsav( p->pSpec );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
Synopsis [Collect memory nodes.]
Description []
diff --git a/src/base/wlc/wlcNtk.c b/src/base/wlc/wlcNtk.c
index 0d8374c7..7f562072 100644
--- a/src/base/wlc/wlcNtk.c
+++ b/src/base/wlc/wlcNtk.c
@@ -640,6 +640,11 @@ void Wlc_NtkPrintNode( Wlc_Ntk_t * p, Wlc_Obj_t * pObj )
printf( "FO\n" );
return;
}
+ if ( pObj->Type != WLC_OBJ_CONST && Wlc_ObjFaninNum(pObj) == 0 )
+ {
+ printf( "Unknown object without fanins\n" );
+ return;
+ }
if ( pObj->Type != WLC_OBJ_CONST )
{
printf( "%6d%s %5s ", Wlc_ObjRange(Wlc_ObjFanin0(p, pObj)), Wlc_ObjIsSigned(Wlc_ObjFanin0(p, pObj)) ? "s" : " ", Wlc_Names[(int)pObj->Type] );
diff --git a/src/base/wlc/wlcWriteVer.c b/src/base/wlc/wlcWriteVer.c
index 93e2c2c6..dd25196c 100644
--- a/src/base/wlc/wlcWriteVer.c
+++ b/src/base/wlc/wlcWriteVer.c
@@ -475,7 +475,8 @@ void Wlc_WriteVerInt( FILE * pFile, Wlc_Ntk_t * p, int fNoFlops )
fprintf( pFile, "#" );
else
{
- assert( 0 );
+ //assert( 0 );
+ printf( "Failed to write node \"%s\" with unknown operator type (%d).\n", Wlc_ObjName(p, i), pObj->Type );
fprintf( pFile, "???\n" );
continue;
}