Streamlining support for multi-output gates

This commit is contained in:
Alan Mishchenko 2026-05-08 00:45:46 -07:00
parent fc4cfc0c35
commit eaa8496b42
6 changed files with 314 additions and 43 deletions

View File

@ -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 );

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 };

View File

@ -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