diff --git a/src/base/io/ioJsonc.c b/src/base/io/ioJsonc.c index 5efffe995..ce069a18a 100644 --- a/src/base/io/ioJsonc.c +++ b/src/base/io/ioJsonc.c @@ -108,6 +108,8 @@ void json_print_string(json_t *json, json_value_t val, FILE *fp); void json_debug_value(json_t *json, json_value_t val, int indent); extern Abc_Ntk_t * Abc_NtkFromMiniMapping( int * pArray ); +static json_value_t * Jsonc_ObjectLookup( json_t * pJson, json_value_t object, const char * pKey ); +static char * Jsonc_StringDup( json_t * pJson, json_value_t value ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -671,6 +673,68 @@ static const char * Jsonc_GetNodeOutName( Abc_Obj_t * pObj ) snprintf( Buffer, sizeof(Buffer), "n%d", Abc_ObjId(pObj) ); return Buffer; } +static char * Jsonc_GetInstanceOutName( json_t * pJson, json_value_t Node ) +{ + json_value_t * pOutName = Jsonc_ObjectLookup( pJson, Node, "pin" ); + if ( pOutName == NULL ) + pOutName = Jsonc_ObjectLookup( pJson, Node, "output" ); + return pOutName && pOutName->type == JSON_STRING ? Jsonc_StringDup( pJson, *pOutName ) : NULL; +} +static int Jsonc_IsPrevTwinNode( Abc_Obj_t * pObj, Abc_Obj_t ** ppPrev ) +{ + Abc_Obj_t * pPrev; + Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; + if ( ppPrev ) + *ppPrev = NULL; + if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL || Abc_ObjId(pObj) == 0 ) + return 0; + pPrev = Abc_NtkObj( pObj->pNtk, Abc_ObjId(pObj) - 1 ); + if ( pPrev == NULL || !Abc_ObjIsNode(pPrev) || Abc_ObjFaninNum(pPrev) != Abc_ObjFaninNum(pObj) ) + return 0; + if ( Mio_GateReadTwin(pGate) != (Mio_Gate_t *)pPrev->pData ) + return 0; + if ( ppPrev ) + *ppPrev = pPrev; + return 1; +} +static Vec_Ptr_t * Jsonc_OrderTwinNodes( Abc_Ntk_t * p, Vec_Ptr_t * vNodes ) +{ + Vec_Int_t * vInDfs = Vec_IntStart( Abc_NtkObjNumMax(p) ); + Vec_Int_t * vSeen = Vec_IntStart( Abc_NtkObjNumMax(p) ); + Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_PtrSize(vNodes) ); + Abc_Obj_t * pObj, * pTwin; + int i; + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Vec_IntWriteEntry( vInDfs, Abc_ObjId(pObj), 1 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + if ( Vec_IntEntry(vSeen, Abc_ObjId(pObj)) ) + continue; + if ( Jsonc_IsPrevTwinNode( pObj, &pTwin ) && Vec_IntEntry(vInDfs, Abc_ObjId(pTwin)) ) + { + if ( !Vec_IntEntry(vSeen, Abc_ObjId(pTwin)) ) + { + Vec_PtrPush( vRes, pTwin ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pTwin), 1 ); + } + Vec_PtrPush( vRes, pObj ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + continue; + } + Vec_PtrPush( vRes, pObj ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pObj), 1 ); + pTwin = Abc_NtkFetchTwinNode( pObj ); + if ( pTwin && Vec_IntEntry(vInDfs, Abc_ObjId(pTwin)) && !Vec_IntEntry(vSeen, Abc_ObjId(pTwin)) ) + { + Vec_PtrPush( vRes, pTwin ); + Vec_IntWriteEntry( vSeen, Abc_ObjId(pTwin), 1 ); + } + } + assert( Vec_PtrSize(vRes) == Vec_PtrSize(vNodes) ); + Vec_IntFree( vInDfs ); + Vec_IntFree( vSeen ); + return vRes; +} /**Function************************************************************* @@ -692,8 +756,18 @@ void Jsonc_WriteTest( Abc_Ntk_t * p, char * pFileName ) int i, Counter, Total; assert( Abc_NtkHasMapping(p) ); vNodes = Abc_NtkDfs2( p ); + { + Vec_Ptr_t * vTemp = Jsonc_OrderTwinNodes( p, vNodes ); + Vec_PtrFree( vNodes ); + vNodes = vTemp; + } vObj2Num = Vec_IntStartFull( Abc_NtkObjNumMax(p) ); Total = Abc_NtkPiNum(p) + Vec_PtrSize(vNodes) + Abc_NtkPoNum(p); + Counter = 0; + Abc_NtkForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vObj2Num, Abc_ObjId(pObj), Counter++ ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Vec_IntWriteEntry( vObj2Num, Abc_ObjId(pObj), Counter++ ); pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { @@ -727,6 +801,8 @@ void Jsonc_WriteTest( Abc_Ntk_t * p, char * pFileName ) fprintf( pFile, " {\n" ); fprintf( pFile, " \"type\": \"%s\",\n", "instance" ); fprintf( pFile, " \"name\": \"%s\",\n", Mio_GateReadName(pGate) ); + if ( Mio_GateReadTwin(pGate) != NULL ) + fprintf( pFile, " \"pin\": \"%s\",\n", Mio_GateReadOutName(pGate) ); fprintf( pFile, " \"fanins\":\n" ); fprintf( pFile, " {\n" ); for ( pPin = Mio_GateReadPins(pGate), k = 0; pPin; pPin = Mio_PinReadNext(pPin), k++ ) @@ -897,9 +973,10 @@ static void Jsonc_AppendPortNames( Vec_Str_t * vNames, Vec_Ptr_t * vBases, Vec_I Vec_IntFree( vCounts ); Vec_IntFree( vBaseIds ); } -static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * pLib, char ** ppDesignName ) +static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * pLib, char ** ppDesignName, Vec_Ptr_t ** pvNodeOutNames ) { Vec_Ptr_t * vPiBases = NULL, * vPoBases = NULL; + Vec_Ptr_t * vNodeOutNames = NULL; Vec_Int_t * vPiBits = NULL, * vPoBits = NULL; Vec_Int_t * vNodeMap = NULL, * vGateIdx = NULL, * vPoIdx = NULL; Vec_Int_t * vMapping = NULL, * vPoDrivers = NULL; @@ -911,6 +988,8 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p int fSuccess = 0; if ( ppDesignName ) *ppDesignName = NULL; + if ( pvNodeOutNames ) + *pvNodeOutNames = NULL; if ( pLib == NULL ) { printf( "Genlib library is not available.\n" ); @@ -943,6 +1022,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p vPiBits = Vec_IntAlloc( pNodes->count ); vPoBases = Vec_PtrAlloc( pNodes->count ); vPoBits = Vec_IntAlloc( pNodes->count ); + vNodeOutNames = Vec_PtrAlloc( pNodes->count ); // first pass: collect object types and names for ( i = 0; i < (int)pNodes->count; i++ ) { @@ -1020,7 +1100,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p json_container_t * pFanObj; Mio_Gate_t * pGate; Mio_Pin_t * pPin; - char * pGateStr; + char * pGateStr, * pOutStr; if ( pGateName == NULL || pGateName->type != JSON_STRING ) { printf( "Gate node %d is missing a name.\n", i ); @@ -1032,16 +1112,19 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p printf( "Gate node %d has an invalid name.\n", i ); goto cleanup; } - pGate = Mio_LibraryReadGateByName( pLib, pGateStr, NULL ); + pOutStr = Jsonc_GetInstanceOutName( pJson, Node ); + pGate = Mio_LibraryReadGateByName( pLib, pGateStr, pOutStr ); if ( pGate == NULL ) { - printf( "Gate \"%s\" is not found in the current library.\n", pGateStr ); + printf( "Gate \"%s\"%s%s%s is not found in the current library.\n", pGateStr, pOutStr ? " with output pin \"" : "", pOutStr ? pOutStr : "", pOutStr ? "\"" : "" ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } if ( pFanins == NULL || pFanins->type != JSON_OBJECT ) { printf( "Gate \"%s\" is missing \"fanins\" description.\n", pGateStr ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1049,6 +1132,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p if ( pFanObj == NULL ) { printf( "Gate \"%s\" has incomplete fanin information.\n", pGateStr ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1061,6 +1145,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p if ( pPinInfo == NULL || pPinInfo->type != JSON_OBJECT ) { printf( "Gate \"%s\" is missing connection for pin \"%s\".\n", pGateStr, Mio_PinReadName(pPin) ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1068,12 +1153,14 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p if ( pNodeLit == NULL || !Jsonc_ParseInt( pJson, *pNodeLit, &NodeId ) ) { printf( "Gate \"%s\" has invalid node reference on pin \"%s\".\n", pGateStr, Mio_PinReadName(pPin) ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } if ( NodeId < 0 || NodeId >= Vec_IntSize(vNodeMap) ) { printf( "Gate \"%s\" references out-of-range node %d.\n", pGateStr, NodeId ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1081,6 +1168,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p if ( MapId < 0 ) { printf( "Gate \"%s\" refers to unsupported node %d.\n", pGateStr, NodeId ); + ABC_FREE( pOutStr ); ABC_FREE( pGateStr ); goto cleanup; } @@ -1088,6 +1176,7 @@ static Vec_Int_t * Jsonc_ConvertToMiniMapping( json_t * pJson, Mio_Library_t * p } Vec_StrPrintStr( vNames, pGateStr ); Vec_StrPush( vNames, '\0' ); + Vec_PtrPush( vNodeOutNames, pOutStr ); ABC_FREE( pGateStr ); } else if ( Jsonc_StringEqual( pJson, *pType, "PO" ) || Jsonc_StringEqual( pJson, *pType, "po" ) ) @@ -1148,6 +1237,18 @@ cleanup: Vec_IntFreeP( &vPoBits ); if ( vNames ) Vec_StrFree( vNames ); + if ( vNodeOutNames ) + { + if ( fSuccess && pvNodeOutNames ) + *pvNodeOutNames = vNodeOutNames; + else + { + char * pOutName; + Vec_PtrForEachEntry( char *, vNodeOutNames, pOutName, i ) + ABC_FREE( pOutName ); + Vec_PtrFree( vNodeOutNames ); + } + } if ( vPiBases ) { Vec_PtrForEachEntry( char *, vPiBases, pBase, i ) @@ -1171,8 +1272,12 @@ Abc_Ntk_t * Jsonc_ReadNetwork( char * pFileName ) { Mio_Library_t * pLib = (Mio_Library_t *)Abc_FrameReadLibGen(); Vec_Int_t * vMapping; + Vec_Ptr_t * vNodeOutNames = NULL; Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj; char * pDesignName = NULL; + char * pOutName; + int i; json_t * pJson = json_create(); if ( pJson == NULL ) { @@ -1185,7 +1290,7 @@ Abc_Ntk_t * Jsonc_ReadNetwork( char * pFileName ) json_destroy( pJson ); return NULL; } - vMapping = Jsonc_ConvertToMiniMapping( pJson, pLib, &pDesignName ); + vMapping = Jsonc_ConvertToMiniMapping( pJson, pLib, &pDesignName, &vNodeOutNames ); json_destroy( pJson ); if ( vMapping == NULL ) return NULL; @@ -1193,9 +1298,35 @@ Abc_Ntk_t * Jsonc_ReadNetwork( char * pFileName ) Vec_IntFree( vMapping ); if ( pNtk == NULL ) { + if ( vNodeOutNames ) + { + Vec_PtrForEachEntry( char *, vNodeOutNames, pOutName, i ) + ABC_FREE( pOutName ); + Vec_PtrFree( vNodeOutNames ); + } ABC_FREE( pDesignName ); return NULL; } + if ( vNodeOutNames ) + { + Vec_PtrForEachEntry( char *, vNodeOutNames, pOutName, i ) + { + Mio_Gate_t * pGate; + pObj = Abc_NtkObj( pNtk, Abc_NtkCiNum(pNtk) + i + 1 ); + if ( pObj == NULL ) + continue; + pGate = (Mio_Gate_t *)pObj->pData; + if ( pOutName && pGate ) + { + Mio_Gate_t * pGateOut = Mio_LibraryReadGateByName( pLib, Mio_GateReadName(pGate), pOutName ); + if ( pGateOut ) + pObj->pData = pGateOut; + } + } + Vec_PtrForEachEntry( char *, vNodeOutNames, pOutName, i ) + ABC_FREE( pOutName ); + Vec_PtrFree( vNodeOutNames ); + } ABC_FREE( pNtk->pName ); pNtk->pName = pDesignName ? pDesignName : Extra_FileNameGeneric( pFileName ); ABC_FREE( pNtk->pSpec ); diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c index e8979c9ba..38e863813 100644 --- a/src/base/io/ioReadBlif.c +++ b/src/base/io/ioReadBlif.c @@ -622,46 +622,65 @@ int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate, Mio_ } else { - if ( i != Mio_GateReadPinNum(pGate) ) // expect the correct order of input pins in the network with twin gates + int nInputs = Mio_GateReadPinNum(pGate); + int nOutputs = nSize - 2 - nInputs; + int nMatched = 0; + if ( nOutputs != 1 && nOutputs != 2 ) return 0; - // check the last two entries - if ( nSize - 3 == Mio_GateReadPinNum(pGate) ) // only one output is available + // reorder the input pins to be in the same order as in the gate + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { - pNamePin = Mio_GateReadOutName(pGate); + pNamePin = Mio_PinReadName(pGatePin); Length = strlen(pNamePin); - pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); - if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pGate + for ( k = 2; k < nSize; k++ ) { - Vec_PtrPush( vTokens, NULL ); - return 1; + pName = (char *)Vec_PtrEntry(vTokens, k); + if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) + { + Vec_PtrPush( vTokens, pName ); + nMatched++; + break; + } } - pNamePin = Mio_GateReadOutName(pTwin); - Length = strlen(pNamePin); - pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); - if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) // the last entry is pTwin + if ( k == nSize ) + return 0; + } + // add the outputs in the base/twin order, with NULL for a missing output + pNamePin = Mio_GateReadOutName(pGate); + Length = strlen(pNamePin); + for ( k = 2; k < nSize; k++ ) + { + pName = (char *)Vec_PtrEntry(vTokens, k); + if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) { - pName = (char *)Vec_PtrPop( vTokens ); - Vec_PtrPush( vTokens, NULL ); Vec_PtrPush( vTokens, pName ); - return 1; + nMatched++; + break; } - return 0; } - if ( nSize - 4 == Mio_GateReadPinNum(pGate) ) // two outputs are available + if ( k == nSize ) + Vec_PtrPush( vTokens, NULL ); + pNamePin = Mio_GateReadOutName(pTwin); + Length = strlen(pNamePin); + for ( k = 2; k < nSize; k++ ) { - pNamePin = Mio_GateReadOutName(pGate); - Length = strlen(pNamePin); - pName = (char *)Vec_PtrEntry(vTokens, nSize - 2); - if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') ) - return 0; - pNamePin = Mio_GateReadOutName(pTwin); - Length = strlen(pNamePin); - pName = (char *)Vec_PtrEntry(vTokens, nSize - 1); - if ( !(!strncmp( pNamePin, pName, Length ) && pName[Length] == '=') ) - return 0; - return 1; + pName = (char *)Vec_PtrEntry(vTokens, k); + if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) + { + Vec_PtrPush( vTokens, pName ); + nMatched++; + break; + } } - assert( 0 ); + if ( k == nSize ) + Vec_PtrPush( vTokens, NULL ); + if ( Vec_PtrEntry(vTokens, nSize + nInputs) == NULL && Vec_PtrEntry(vTokens, nSize + nInputs + 1) == NULL ) + return 0; + if ( nMatched != nSize - 2 ) + return 0; + Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nSize ) + Vec_PtrWriteEntry( vTokens, k - nSize + 2, pName ); + Vec_PtrShrink( vTokens, 2 + nInputs + 2 ); } return 1; } @@ -1713,4 +1732,3 @@ int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) ABC_NAMESPACE_IMPL_END - diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c index 818f66b37..71a40f96c 100644 --- a/src/base/io/ioWriteBlif.c +++ b/src/base/io/ioWriteBlif.c @@ -573,6 +573,17 @@ void Io_NtkWriteSubcktFanins( FILE * pFile, Abc_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ +static int Io_NtkNodesHaveSameFanins( Abc_Obj_t * pNode, Abc_Obj_t * pNode2 ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_ObjFaninNum(pNode) != Abc_ObjFaninNum(pNode2) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pFanin != Abc_ObjFanin(pNode2, i) ) + return 0; + return 1; +} int Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) { static int fReport = 0; @@ -594,6 +605,8 @@ int Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) fReport = 1, printf( "Warning: Missing second output of gate(s) \"%s\".\n", Mio_GateReadName(pGate) ); return 0; } + if ( !Io_NtkNodesHaveSameFanins( pNode, pNode2 ) ) + return 0; fprintf( pFile, " %s=%s", Mio_GateReadOutName((Mio_Gate_t *)pNode2->pData), Abc_ObjName( Abc_ObjFanout0(pNode2) ) ); return 1; } @@ -1407,4 +1420,3 @@ void Io_WriteBlifSpecial( Abc_Ntk_t * pNtk, char * FileName, char * pLutStruct, ABC_NAMESPACE_IMPL_END - diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c index acddb7551..4d3b06fcd 100644 --- a/src/base/io/ioWriteVerilog.c +++ b/src/base/io/ioWriteVerilog.c @@ -39,6 +39,8 @@ static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ); static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ); static char * Io_WriteVerilogGetName( char * pName ); +static int Io_WriteVerilogNodesHaveSameFanins( Abc_Obj_t * pNode, Abc_Obj_t * pNode2 ); +static int Io_WriteVerilogIsPrevTwinNode( Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// @@ -512,6 +514,54 @@ void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ) fprintf( pFile, " end\n" ); } +/**Function************************************************************* + + Synopsis [Checks whether two mapped nodes have the same fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_WriteVerilogNodesHaveSameFanins( Abc_Obj_t * pNode, Abc_Obj_t * pNode2 ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_ObjFaninNum(pNode) != Abc_ObjFaninNum(pNode2) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( pFanin != Abc_ObjFanin(pNode2, i) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks whether this mapped node is the second output of a twin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_WriteVerilogIsPrevTwinNode( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pPrev; + Mio_Gate_t * pGate = (Mio_Gate_t *)pNode->pData; + if ( pGate == NULL || Mio_GateReadTwin(pGate) == NULL || Abc_ObjId(pNode) == 0 ) + return 0; + pPrev = Abc_NtkObj( pNode->pNtk, Abc_ObjId(pNode) - 1 ); + if ( pPrev == NULL || !Abc_ObjIsNode(pPrev) ) + return 0; + if ( Mio_GateReadTwin(pGate) != (Mio_Gate_t *)pPrev->pData ) + return 0; + return Io_WriteVerilogNodesHaveSameFanins( pPrev, pNode ); +} + /**Function************************************************************* Synopsis [Writes the nodes and boxes.] @@ -563,12 +613,18 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) Abc_NtkForEachNode( pNtk, pObj, k ) { Mio_Gate_t * pGate = (Mio_Gate_t *)pObj->pData; + Abc_Obj_t * pNode2 = NULL; Mio_Pin_t * pGatePin; + if ( Io_WriteVerilogIsPrevTwinNode( pObj ) ) + continue; if ( Abc_ObjFaninNum(pObj) == 0 && (!strcmp(Mio_GateReadName(pGate), "_const0_") || !strcmp(Mio_GateReadName(pGate), "_const1_")) ) { fprintf( pFile, " %-*s %s = 1\'b%d;\n", Length, "assign", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )), !strcmp(Mio_GateReadName(pGate), "_const1_") ); continue; } + pNode2 = Abc_NtkFetchTwinNode( pObj ); + if ( pNode2 && !Io_WriteVerilogNodesHaveSameFanins( pObj, pNode2 ) ) + pNode2 = NULL; // write the node if ( fUseSimpleGateNames ) { @@ -591,6 +647,12 @@ void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk, int fOnlyAnds ) assert ( i == Abc_ObjFaninNum(pObj) ); fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) ); fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) ); + if ( pNode2 ) + { + fprintf( pFile, ", " ); + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName((Mio_Gate_t *)pNode2->pData)) ); + fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pNode2) )) ); + } fprintf( pFile, ");\n" ); } } @@ -972,4 +1034,3 @@ void Io_WriteVerilogLut( Abc_Ntk_t * pNtk, char * pFileName, int nLutSize, int f ABC_NAMESPACE_IMPL_END - diff --git a/src/map/scl/sclLib.h b/src/map/scl/sclLib.h index b50e6ffb7..eb2d7920d 100644 --- a/src/map/scl/sclLib.h +++ b/src/map/scl/sclLib.h @@ -656,12 +656,13 @@ static inline void Scl_LibPinRequiredI( SC_Timing * pTime, SC_PairI * pReqIn, SC SeeAlso [] ***********************************************************************/ -static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin ) +static inline SC_Timing * Scl_CellPinOutTime( SC_Cell * pCell, int iOut, int iPin ) { SC_Pin * pPin; SC_Timings * pRTime; + assert( iOut >= 0 && iOut < pCell->n_outputs ); assert( iPin >= 0 && iPin < pCell->n_inputs ); - pPin = SC_CellPin( pCell, pCell->n_inputs ); + pPin = SC_CellPin( pCell, pCell->n_inputs + iOut ); assert( Vec_PtrSize(&pPin->vRTimings) == pCell->n_inputs ); pRTime = (SC_Timings *)Vec_PtrEntry( &pPin->vRTimings, iPin ); if ( Vec_PtrSize(&pRTime->vTimings) == 0 ) @@ -669,6 +670,10 @@ static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin ) assert( Vec_PtrSize(&pRTime->vTimings) == 1 ); return (SC_Timing *)Vec_PtrEntry( &pRTime->vTimings, 0 ); } +static inline SC_Timing * Scl_CellPinTime( SC_Cell * pCell, int iPin ) +{ + return Scl_CellPinOutTime( pCell, 0, iPin ); +} static inline float Scl_LibPinArrivalEstimate( SC_Cell * pCell, int iPin, float Slew, float Load ) { SC_Pair LoadIn = { Load, Load }; diff --git a/src/map/scl/sclSize.c b/src/map/scl/sclSize.c index bf2a40090..8d3a2dd5a 100644 --- a/src/map/scl/sclSize.c +++ b/src/map/scl/sclSize.c @@ -103,6 +103,35 @@ Abc_Obj_t * Abc_SclFindMostCriticalFanin( SC_Man * p, int * pfRise, Abc_Obj_t * return pPivot; } +/**Function************************************************************* + + Synopsis [Find the output pin represented by this mapped node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_SclObjOutputIndex( Abc_Obj_t * pObj, SC_Cell * pCell ) +{ + Mio_Gate_t * pGate; + char * pOutName; + int i; + if ( pCell->n_outputs == 1 ) + return 0; + pGate = (Mio_Gate_t *)pObj->pData; + assert( pGate != NULL ); + pOutName = Mio_GateReadOutName( pGate ); + assert( pOutName != NULL ); + for ( i = 0; i < pCell->n_outputs; i++ ) + if ( !strcmp( pOutName, SC_CellPinName(pCell, pCell->n_inputs + i) ) ) + return i; + assert( 0 ); + return 0; +} + /**Function************************************************************* Synopsis [Printing timing information for the node/network.] @@ -299,10 +328,20 @@ static inline void Abc_SclDeptObj( SC_Man * p, Abc_Obj_t * pObj ) SC_PairClean( Abc_SclObjDept(p, pObj) ); Abc_ObjForEachFanout( pObj, pFanout, i ) { + SC_Cell * pFanoutCell; + int iFanin, iOut; if ( Abc_ObjIsCo(pFanout) || Abc_ObjIsLatch(pFanout) ) continue; - pTime = Scl_CellPinTime( Abc_SclObjCell(pFanout), Abc_NodeFindFanin(pFanout, pObj) ); - Abc_SclDeptFanin( p, pTime, pFanout, pObj, Abc_NodeFindFanin(pFanout, pObj) ); + pFanoutCell = Abc_SclObjCell( pFanout ); + iFanin = Abc_NodeFindFanin( pFanout, pObj ); + iOut = Abc_SclObjOutputIndex( pFanout, pFanoutCell ); + pTime = Scl_CellPinOutTime( pFanoutCell, iOut, iFanin ); + if ( pTime == NULL ) + { + assert( pFanoutCell->n_outputs > 1 ); + continue; + } + Abc_SclDeptFanin( p, pTime, pFanout, pObj, iFanin ); } } static inline float Abc_SclObjLoadValue( SC_Man * p, Abc_Obj_t * pObj ) @@ -370,7 +409,13 @@ void Abc_SclTimeNode( SC_Man * p, Abc_Obj_t * pObj, int fDept ) // compute for each fanin Abc_ObjForEachFanin( pObj, pFanin, k ) { - pTime = Scl_CellPinTime( pCell, k ); + int iOut = Abc_SclObjOutputIndex( pObj, pCell ); + pTime = Scl_CellPinOutTime( pCell, iOut, k ); + if ( pTime == NULL ) + { + assert( pCell->n_outputs > 1 ); + continue; + } if ( fDept ) Abc_SclDeptFanin( p, pTime, pObj, pFanin, k ); else @@ -928,4 +973,3 @@ void Abc_SclPrintBuffers( SC_Lib * pLib, Abc_Ntk_t * pNtk, int fVerbose ) ABC_NAMESPACE_IMPL_END -