mirror of https://github.com/YosysHQ/abc.git
Command %blastmem for bit-blasting small memories.
This commit is contained in:
parent
f4a267d581
commit
28a1307a61
|
|
@ -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 );
|
||||
|
|
@ -1104,6 +1106,52 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function********************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
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 []
|
||||
|
|
|
|||
|
|
@ -33,6 +33,133 @@ ABC_NAMESPACE_IMPL_START
|
|||
/// FUNCTION DEFINITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**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.]
|
||||
|
|
|
|||
|
|
@ -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] );
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue