/**CFile**************************************************************** FileName [wlnNdr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Word-level network.] Synopsis [Constructing WLN network from NDR data structure.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 23, 2018.] Revision [$Id: wlnNdr.c,v 1.00 2018/09/23 00:00:00 alanmi Exp $] ***********************************************************************/ #include "wln.h" #include "aig/miniaig/ndr.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Wln_NtkToNdr( Wln_Ntk_t * p ) { Vec_Int_t * vFanins; int i, k, iObj, iFanin; // create a new module void * pDesign = Ndr_Create( 1 ); int ModId = Ndr_AddModule( pDesign, 1 ); // add primary inputs Wln_NtkForEachPi( p, iObj, i ) { Ndr_AddObject( pDesign, ModId, ABC_OPER_CI, 0, Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), 0, NULL, 1, &iObj, NULL ); // no fanins } // add internal nodes vFanins = Vec_IntAlloc( 10 ); Wln_NtkForEachObjInternal( p, iObj ) { Vec_IntClear( vFanins ); Wln_ObjForEachFanin( p, iObj, iFanin, k ) Vec_IntPush( vFanins, iFanin ); Ndr_AddObject( pDesign, ModId, Wln_ObjType(p, iObj), 0, Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), Vec_IntSize(vFanins), Vec_IntArray(vFanins), 1, &iObj, Wln_ObjIsConst(p, iObj) ? Wln_ObjConstString(p, iObj) : NULL ); } Vec_IntFree( vFanins ); // add primary outputs Wln_NtkForEachPo( p, iObj, i ) { Ndr_AddObject( pDesign, ModId, ABC_OPER_CO, 0, Wln_ObjRangeEnd(p, iObj), Wln_ObjRangeBeg(p, iObj), Wln_ObjIsSigned(p, iObj), 1, &iObj, 0, NULL, NULL ); } return pDesign; } void Wln_WriteNdr( Wln_Ntk_t * p, char * pFileName ) { void * pDesign = Wln_NtkToNdr( p ); Ndr_Write( pFileName, pDesign ); Ndr_Delete( pDesign ); printf( "Dumped the current design into file \"%s\".\n", pFileName ); } void Wln_NtkToNdrTest( Wln_Ntk_t * p ) { // transform void * pDesign = Wln_NtkToNdr( p ); // collect names char ** ppNames = ABC_ALLOC( char *, Wln_NtkObjNum(p) + 1 ); int i; Wln_NtkForEachObj( p, i ) ppNames[i] = Abc_UtilStrsav(Wln_ObjName(p, i)); // verify by writing Verilog Ndr_WriteVerilog( NULL, pDesign, ppNames ); Ndr_Write( "test.ndr", pDesign ); // cleanup Ndr_Delete( pDesign ); Wln_NtkForEachObj( p, i ) ABC_FREE( ppNames[i] ); ABC_FREE( ppNames ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ndr_ObjGetRange( Ndr_Data_t * p, int Obj, int * End, int * Beg ) { int * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_RANGE, &pArray ); int Signed = 0; *End = *Beg = 0; if ( nArray == 0 ) return 0; if ( nArray == 3 ) Signed = 1; if ( nArray == 1 ) *End = *Beg = pArray[0]; else *End = pArray[0], *Beg = pArray[1]; return Signed; } void Ndr_NtkPrintObjects( Wln_Ntk_t * pNtk ) { int k, iObj, iFanin; printf( "Node IDs and their fanins:\n" ); Wln_NtkForEachObj( pNtk, iObj ) { printf( "%5d = ", iObj ); Wln_ObjForEachFanin( pNtk, iObj, iFanin, k ) printf( "%5d ", iFanin ); for ( ; k < 4; k++ ) printf( " " ); printf( " Name Id %d ", Wln_ObjNameId(pNtk, iObj) ); if ( Wln_ObjIsPi(pNtk, iObj) ) printf( " pi " ); if ( Wln_ObjIsPo(pNtk, iObj) ) printf( " po " ); printf( "\n" ); } } void Wln_NtkCheckIntegrity( void * pData ) { Ndr_Data_t * p = (Ndr_Data_t *)pData; Vec_Int_t * vMap = Vec_IntAlloc( 100 ); int Mod = 2, Obj; Ndr_ModForEachObj( p, Mod, Obj ) { int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); if ( NameId == -1 ) { int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); if ( Type != ABC_OPER_CO ) printf( "Internal object %d of type %s has no output name.\n", Obj, Abc_OperName(Type) ); continue; } if ( Vec_IntGetEntry(vMap, NameId) > 0 ) printf( "Output name %d is used more than once (obj %d and obj %d).\n", NameId, Vec_IntGetEntry(vMap, NameId), Obj ); Vec_IntSetEntry( vMap, NameId, Obj ); } Ndr_ModForEachObj( p, Mod, Obj ) { int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); int i, * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); for ( i = 0; i < nArray; i++ ) if ( Vec_IntGetEntry(vMap, pArray[i]) == 0 && !(Type == ABC_OPER_DFFRSE && (i >= 5 || i <= 7)) ) printf( "Input name %d appearing as fanin %d of obj %d is not used as output name in any object.\n", pArray[i], i, Obj ); } Vec_IntFree( vMap ); } Wln_Ntk_t * Wln_NtkFromNdr( void * pData ) { Ndr_Data_t * p = (Ndr_Data_t *)pData; Vec_Int_t * vName2Obj, * vFanins = Vec_IntAlloc( 100 ); Vec_Ptr_t * vConstStrings = Vec_PtrAlloc( 100 ); int Mod = 2, i, k, iFanin, iObj, Obj, * pArray, nDigits, fFound, NameId, NameIdMax; Wln_Ntk_t * pTemp, * pNtk = Wln_NtkAlloc( "top", Ndr_DataObjNum(p, Mod) ); Wln_NtkCheckIntegrity( pData ); //pNtk->pSpec = Abc_UtilStrsav( pFileName ); // construct network and save name IDs Wln_NtkCleanNameId( pNtk ); Wln_NtkCleanInstId( pNtk ); Ndr_ModForEachPi( p, Mod, Obj ) { int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); int iObj = Wln_ObjAlloc( pNtk, ABC_OPER_CI, Signed, End, Beg ); int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); Wln_ObjSetNameId( pNtk, iObj, NameId ); if ( InstId > 0 ) Wln_ObjSetInstId( pNtk, iObj, InstId ); } Ndr_ModForEachNode( p, Mod, Obj ) { int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); int Type = Ndr_ObjReadBody( p, Obj, NDR_OPERTYPE ); int nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); Vec_Int_t F = {nArray, nArray, pArray}, * vTemp = &F; int iObj = Wln_ObjAlloc( pNtk, Type, Signed, End, Beg ); int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); Vec_IntClear( vFanins ); Vec_IntAppend( vFanins, vTemp ); assert( Type != ABC_OPER_DFF ); if ( Wln_ObjIsSlice(pNtk, iObj) ) Wln_ObjSetSlice( pNtk, iObj, Hash_Int2ManInsert(pNtk->pRanges, End, Beg, 0) ); else if ( Wln_ObjIsConst(pNtk, iObj) ) Vec_PtrPush( vConstStrings, (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) ); // else if ( Type == ABC_OPER_BIT_MUX && Vec_IntSize(vFanins) == 3 ) // ABC_SWAP( int, Wln_ObjFanins(pNtk, iObj)[1], Wln_ObjFanins(pNtk, iObj)[2] ); Wln_ObjAddFanins( pNtk, iObj, vFanins ); Wln_ObjSetNameId( pNtk, iObj, NameId ); if ( InstId > 0 ) Wln_ObjSetInstId( pNtk, iObj, InstId ); if ( Type == ABC_OPER_ARI_SMUL ) { assert( Wln_ObjFaninNum(pNtk, iObj) == 2 ); Wln_ObjSetSigned( pNtk, Wln_ObjFanin0(pNtk, iObj) ); Wln_ObjSetSigned( pNtk, Wln_ObjFanin1(pNtk, iObj) ); } } // mark primary outputs Ndr_ModForEachPo( p, Mod, Obj ) { int End, Beg, Signed = Ndr_ObjGetRange(p, Obj, &End, &Beg); int nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); int iObj = Wln_ObjAlloc( pNtk, ABC_OPER_CO, Signed, End, Beg ); int NameId = Ndr_ObjReadBody( p, Obj, NDR_OUTPUT ); int InstId = Ndr_ObjReadBody( p, Obj, NDR_NAME ); assert( nArray == 1 && NameId == -1 && InstId == -1 ); Wln_ObjAddFanin( pNtk, iObj, pArray[0] ); } Vec_IntFree( vFanins ); // remove instance names if they are not given //Vec_IntPrint( &pNtk->vInstIds ); if ( Vec_IntCountPositive(&pNtk->vInstIds) == 0 ) Vec_IntErase( &pNtk->vInstIds ); // map name IDs into object IDs vName2Obj = Vec_IntInvert( &pNtk->vNameIds, 0 ); Wln_NtkForEachObj( pNtk, i ) Wln_ObjForEachFanin( pNtk, i, iFanin, k ) Wln_ObjSetFanin( pNtk, i, k, Vec_IntEntry(vName2Obj, iFanin) ); Vec_IntFree(vName2Obj); // create fake object names NameIdMax = Vec_IntFindMax(&pNtk->vNameIds); nDigits = Abc_Base10Log( NameIdMax+1 ); pNtk->pManName = Abc_NamStart( NameIdMax+1, 10 ); for ( i = 1; i <= NameIdMax; i++ ) { char pName[20]; sprintf( pName, "s%0*d", nDigits, i ); NameId = Abc_NamStrFindOrAdd( pNtk->pManName, pName, &fFound ); assert( !fFound && i == NameId ); } // add const strings i = 0; Wln_NtkForEachObj( pNtk, iObj ) if ( Wln_ObjIsConst(pNtk, iObj) ) Wln_ObjSetConst( pNtk, iObj, Abc_NamStrFindOrAdd(pNtk->pManName, (char *)Vec_PtrEntry(vConstStrings, i++), NULL) ); assert( i == Vec_PtrSize(vConstStrings) ); Vec_PtrFree( vConstStrings ); //Ndr_NtkPrintObjects( pNtk ); Wln_WriteVer( pNtk, "temp_ndr.v" ); printf( "Dumped design \"%s\" into file \"temp_ndr.v\".\n", pNtk->pName ); // derive topological order pNtk = Wln_NtkDupDfs( pTemp = pNtk ); Wln_NtkFree( pTemp ); //Ndr_NtkPrintObjects( pNtk ); //pNtk->fMemPorts = 1; // the network contains memory ports //pNtk->fEasyFfs = 1; // the network contains simple flops return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Wln_Ntk_t * Wln_ReadNdr( char * pFileName ) { void * pData = Ndr_Read( pFileName ); Wln_Ntk_t * pNtk = Wln_NtkFromNdr( pData ); //char * ppNames[10] = { NULL, "a", "b", "c", "d", "e", "f", "g", "h", "i" }; //Ndr_WriteVerilog( NULL, pData, ppNames ); Ndr_Delete( pData ); return pNtk; } void Wln_ReadNdrTest() { Wln_Ntk_t * pNtk = Wln_ReadNdr( "D:\\temp\\brijesh\\for_alan_dff_warning\\work_fir_filter_fir_filter_proc_out.ndr" ); //Wln_Ntk_t * pNtk = Wln_ReadNdr( "flop.ndr" ); Wln_WriteVer( pNtk, "test__test.v" ); Wln_NtkPrint( pNtk ); Wln_NtkStaticFanoutTest( pNtk ); Wln_NtkFree( pNtk ); } void Wln_NtkRetimeTest( char * pFileName ) { void * pData = Ndr_Read( pFileName ); Wln_Ntk_t * pNtk = Wln_NtkFromNdr( pData ); Ndr_Delete( pData ); if ( Wln_NtkHasInstId(pNtk) ) Vec_IntErase( &pNtk->vInstIds ); if ( !Wln_NtkHasInstId(pNtk) ) { int iObj; printf( "The design has no delay information.\n" ); Wln_NtkCleanInstId(pNtk); Wln_NtkForEachObj( pNtk, iObj ) if ( Wln_ObjIsFf(pNtk, iObj) ) Wln_ObjSetInstId( pNtk, iObj, 1 ); else if ( !Wln_ObjIsCio(pNtk, iObj) && Wln_ObjFaninNum(pNtk, iObj) > 0 ) Wln_ObjSetInstId( pNtk, iObj, 10 ); printf( "Assuming user-specified delays for internal nodes.\n" ); } /* else { int iObj; Wln_NtkForEachObj( pNtk, iObj ) if ( !Wln_ObjIsCio(pNtk, iObj) && Wln_ObjFaninNum(pNtk, iObj) > 0 && !Wln_ObjIsFf(pNtk, iObj) ) printf( "Obj %5d : NameId = %6d InstId = %6d\n", iObj, Wln_ObjNameId(pNtk, iObj), Wln_ObjInstId(pNtk, iObj) ); } */ //else { Vec_Int_t * vMoves = Wln_NtkRetime( pNtk ); //Vec_IntPrint( vMoves ); Vec_IntFree( vMoves ); } Wln_NtkFree( pNtk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END