/**Function*************************************************************

  Synopsis    [Retimes node forward by one latch.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_ObjRetimeForward( Abc_Obj_t * pObj )  
{
    Abc_Obj_t * pFanout;
    int Init0, Init1, Init, i;
    assert( Abc_ObjFaninNum(pObj) == 2 );
    assert( Seq_ObjFaninL0(pObj) >= 1 );
    assert( Seq_ObjFaninL1(pObj) >= 1 );
    // remove the init values from the fanins
    Init0 = Seq_NodeDeleteFirst( pObj, 0 ); 
    Init1 = Seq_NodeDeleteFirst( pObj, 1 );
    assert( Init0 != ABC_INIT_NONE );
    assert( Init1 != ABC_INIT_NONE );
    // take into account the complements in the node
    if ( Abc_ObjFaninC0(pObj) )
    {
        if ( Init0 == ABC_INIT_ZERO )
            Init0 = ABC_INIT_ONE;
        else if ( Init0 == ABC_INIT_ONE )
            Init0 = ABC_INIT_ZERO;
    }
    if ( Abc_ObjFaninC1(pObj) )
    {
        if ( Init1 == ABC_INIT_ZERO )
            Init1 = ABC_INIT_ONE;
        else if ( Init1 == ABC_INIT_ONE )
            Init1 = ABC_INIT_ZERO;
    }
    // compute the value at the output of the node
    if ( Init0 == ABC_INIT_ZERO || Init1 == ABC_INIT_ZERO )
        Init = ABC_INIT_ZERO;
    else if ( Init0 == ABC_INIT_ONE && Init1 == ABC_INIT_ONE )
        Init = ABC_INIT_ONE;
    else
        Init = ABC_INIT_DC;

    // make sure the label is clean
    Abc_ObjForEachFanout( pObj, pFanout, i )
        assert( pFanout->fMarkC == 0 );
    // add the init values to the fanouts
    Abc_ObjForEachFanout( pObj, pFanout, i )
    {
        if ( pFanout->fMarkC )
            continue;
        pFanout->fMarkC = 1;
        if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) )
            Seq_NodeInsertLast( pFanout, Abc_ObjFanoutEdgeNum(pObj, pFanout), Init );
        else
        {
            assert( Abc_ObjFanin0(pFanout) == pObj );
            Seq_NodeInsertLast( pFanout, 0, Init );
            Seq_NodeInsertLast( pFanout, 1, Init );
        }
    }
    // clean the label
    Abc_ObjForEachFanout( pObj, pFanout, i )
        pFanout->fMarkC = 0;
}
示例#2
0
/**Function*************************************************************

  Synopsis    [Prints statistics about latches.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk )
{
    Abc_Obj_t * pLatch, * pFanin;
    int i, Counter0, Counter1, Counter2;
    int InitNums[4], Init;

    assert( !Abc_NtkIsNetlist(pNtk) );
    if ( Abc_NtkLatchNum(pNtk) == 0 )
    {
        fprintf( pFile, "The network is combinational.\n" );
        return;
    }

    for ( i = 0; i < 4; i++ )    
        InitNums[i] = 0;
    Counter0 = Counter1 = Counter2 = 0;
    Abc_NtkForEachLatch( pNtk, pLatch, i )
    {
        Init = Abc_LatchInit( pLatch );
        assert( Init < 4 );
        InitNums[Init]++;

        pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch));
        if ( Abc_NtkIsLogic(pNtk) )
        {
            if ( !Abc_NodeIsConst(pFanin) )
                continue;
        }
        else if ( Abc_NtkIsStrash(pNtk) )
        {
            if ( !Abc_AigNodeIsConst(pFanin) )
                continue;
        }
        else
            assert( 0 );

        // the latch input is a constant node
        Counter0++;
        if ( Abc_LatchIsInitDc(pLatch) )
        {
            Counter1++;
            continue;
        }
        // count the number of cases when the constant is equal to the initial value
        if ( Abc_NtkIsStrash(pNtk) )
        {
            if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) )
                Counter2++;
        }
        else
        {
            if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(pLatch) )
                Counter2++;
        }
    }
示例#3
0
/**Function*************************************************************

  Synopsis    [Finalizes the network using the existing network as a model.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
    Abc_Obj_t * pObj, * pDriver, * pDriverNew;
    int i;
    // set the COs of the strashed network
    Abc_NtkForEachCo( pNtk, pObj, i )
    {
        pDriver    = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) );
        pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj));
        Abc_ObjAddFanin( pObj->pCopy, pDriverNew );
    }
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes )
{
    Abc_Obj_t * pObj;
    unsigned uTruth0, uTruth1;
    int i;
    Vec_PtrForEachEntry( vNodes, pObj, i )
    {
        uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy);
        uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy);
        if ( Abc_ObjFaninC0(pObj) )
            uTruth0 = ~uTruth0;
        if ( Abc_ObjFaninC1(pObj) )
            uTruth1 = ~uTruth1;
        pObj->pCopy = (void *)(uTruth0 & uTruth1);
    }
示例#5
0
 Vec_PtrForEachEntry( vNodes, pNode, i )
 {
     Extra_ProgressBarUpdate( pProgress, i, NULL );
     // add the node to the mapper
     pNodeFpga = Fpga_NodeAnd( pMan, 
         Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ),
         Fpga_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) );
     assert( pNode->pCopy == NULL );
     // remember the node
     pNode->pCopy = (Abc_Obj_t *)pNodeFpga;
     if ( pSwitching )
         Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] );
     // set up the choice node
     if ( Abc_AigNodeIsChoice( pNode ) )
         for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData )
         {
             Fpga_NodeSetNextE( (Fpga_Node_t *)pPrev->pCopy, (Fpga_Node_t *)pFanin->pCopy );
             Fpga_NodeSetRepr( (Fpga_Node_t *)pFanin->pCopy, (Fpga_Node_t *)pNode->pCopy );
         }
 }
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj )
{
    if ( pObj == Abc_AigConst1(pObj->pNtk) )
    {
        printf( "1" );
        return;
    }
    if ( Abc_ObjIsPi(pObj) )
    {
        printf( "%c", pObj->Id - 1 + 'a' );
        return;
    }

    printf( "(" );
    Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) );
    if ( Abc_ObjFaninC0(pObj) )
        printf( "\'" );
    Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) );
    if ( Abc_ObjFaninC1(pObj) )
        printf( "\'" );
    printf( ")" );
}
示例#7
0
/**Function*************************************************************

  Synopsis    [Converts the network from ABC into the AIG manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Abc_NodeFanin0Copy2( Abc_Obj_t * pObj )
{
    return Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, Abc_ObjFaninC0(pObj) );
}
static inline int  Abc_ObjGetXsimFanin0( Abc_Obj_t * pObj )       
{ 
    int RetValue;
    RetValue = Abc_ObjGetXsim(Abc_ObjFanin0(pObj));
    return Abc_ObjFaninC0(pObj)? Abc_XsimInv(RetValue) : RetValue;
}
/**Function*************************************************************

  Synopsis    [Load the network into manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose )
{
    Map_Man_t * pMan;
    Map_Node_t * pNodeMap;
    Vec_Ptr_t * vNodes;
    Abc_Obj_t * pNode, * pFanin, * pPrev;
    int i;

    assert( Abc_NtkIsStrash(pNtk) );

    // start the mapping manager and set its parameters
    pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, fVerbose );
    if ( pMan == NULL )
        return NULL;
    Map_ManSetAreaRecovery( pMan, fRecovery );
    Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) );
    Map_ManSetDelayTarget( pMan, (float)DelayTarget );
    Map_ManSetInputArrivals( pMan, Abc_NtkMapCopyCiArrival(pNtk, Abc_NtkGetCiArrivalTimes(pNtk)) );
    Map_ManSetOutputRequireds( pMan, Abc_NtkMapCopyCoRequired(pNtk, Abc_NtkGetCoRequiredTimes(pNtk)) );

    // create PIs and remember them in the old nodes
    Abc_NtkCleanCopy( pNtk );
    Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan);
    Abc_NtkForEachCi( pNtk, pNode, i )
    {
        if ( i == Abc_NtkCiNum(pNtk) - pNtk->nBarBufs )
            break;
        pNodeMap = Map_ManReadInputs(pMan)[i];
        pNode->pCopy = (Abc_Obj_t *)pNodeMap;
        if ( pSwitching )
            Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] );
    }

    // load the AIG into the mapper
    vNodes = Abc_AigDfsMap( pNtk );
    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i )
    {
        if ( Abc_ObjIsLatch(pNode) )
        {
            pFanin = Abc_ObjFanin0(pNode);
            pNodeMap = Map_NodeBuf( pMan, Map_NotCond( Abc_ObjFanin0(pFanin)->pCopy, (int)Abc_ObjFaninC0(pFanin) ) );
            Abc_ObjFanout0(pNode)->pCopy = (Abc_Obj_t *)pNodeMap;
            continue;
        }
        assert( Abc_ObjIsNode(pNode) );
        // add the node to the mapper
        pNodeMap = Map_NodeAnd( pMan, 
            Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ),
            Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ) );
        assert( pNode->pCopy == NULL );
        // remember the node
        pNode->pCopy = (Abc_Obj_t *)pNodeMap;
        if ( pSwitching )
            Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] );
        // set up the choice node
        if ( Abc_AigNodeIsChoice( pNode ) )
            for ( pPrev = pNode, pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData )
            {
                Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy );
                Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy );
            }
    }
    assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs );
    Vec_PtrFree( vNodes );

    // set the primary outputs in the required phase
    Abc_NtkForEachCo( pNtk, pNode, i )
    {
        if ( i == Abc_NtkCoNum(pNtk) - pNtk->nBarBufs )
            break;
        Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) );
    }
    return pMan;
}
示例#10
0
/**Function*************************************************************

  Synopsis    [Performs minimum-register retiming.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Abc_Ntk_t *
Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, 
                       int fComputeInitState, int fGuaranteeInitState, int fBlockConst,
                       int fForwardOnly, int fBackwardOnly, int nMaxIters,
                       int maxDelay, int fFastButConservative ) {

  int i;
  Abc_Obj_t   *pObj, *pNext;
  InitConstraint_t *pData;

  // create manager
  pManMR = ALLOC( MinRegMan_t, 1 );

  pManMR->pNtk = pNtk;
  pManMR->fVerbose = fVerbose;
  pManMR->fComputeInitState = fComputeInitState;
  pManMR->fGuaranteeInitState = fGuaranteeInitState;
  pManMR->fBlockConst = fBlockConst;
  pManMR->fForwardOnly = fForwardOnly;
  pManMR->fBackwardOnly = fBackwardOnly;
  pManMR->nMaxIters = nMaxIters;
  pManMR->maxDelay = maxDelay;
  pManMR->fComputeInitState = fComputeInitState;
  pManMR->fConservTimingOnly = fFastButConservative;
  pManMR->vNodes = Vec_PtrAlloc(100);
  pManMR->vInitConstraints = Vec_PtrAlloc(2);
  pManMR->pInitNtk = NULL;
  pManMR->pInitToOrig = NULL;
  pManMR->sizeInitToOrig = 0;

  vprintf("Flow-based minimum-register retiming...\n");  

  if (!Abc_NtkHasOnlyLatchBoxes(pNtk)) {
    printf("\tERROR: Can not retime with black/white boxes\n");
    return pNtk;
  }

  if (maxDelay) {
    vprintf("\tmax delay constraint = %d\n", maxDelay);
    if (maxDelay < (i = Abc_NtkLevel(pNtk))) {
      printf("ERROR: max delay constraint (%d) must be > current max delay (%d)\n", maxDelay, i);
      return pNtk;
    }
  }

  // print info about type of network
  vprintf("\tnetlist type = ");
  if (Abc_NtkIsNetlist( pNtk )) { vprintf("netlist/"); }
  else if (Abc_NtkIsLogic( pNtk )) { vprintf("logic/"); }
  else if (Abc_NtkIsStrash( pNtk )) { vprintf("strash/"); }
  else { vprintf("***unknown***/"); }
  if (Abc_NtkHasSop( pNtk )) { vprintf("sop\n"); }
  else if (Abc_NtkHasBdd( pNtk )) { vprintf("bdd\n"); }
  else if (Abc_NtkHasAig( pNtk )) { vprintf("aig\n"); }
  else if (Abc_NtkHasMapping( pNtk )) { vprintf("mapped\n"); }
  else { vprintf("***unknown***\n"); }

  vprintf("\tinitial reg count = %d\n", Abc_NtkLatchNum(pNtk));
  vprintf("\tinitial levels = %d\n", Abc_NtkLevel(pNtk));

  // remove bubbles from latch boxes
  if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk);
  vprintf("\tpushing bubbles out of latch boxes\n");
  Abc_NtkForEachLatch( pNtk, pObj, i )
    Abc_FlowRetime_RemoveLatchBubbles(pObj);
  if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk);

  // check for box inputs/outputs
  Abc_NtkForEachLatch( pNtk, pObj, i ) {
    assert(Abc_ObjFaninNum(pObj) == 1);
    assert(Abc_ObjFanoutNum(pObj) == 1);
    assert(!Abc_ObjFaninC0(pObj));

    pNext = Abc_ObjFanin0(pObj);
    assert(Abc_ObjIsBi(pNext));
    assert(Abc_ObjFaninNum(pNext) <= 1);
    if(Abc_ObjFaninNum(pNext) == 0) // every Bi should have a fanin
      Abc_FlowRetime_AddDummyFanin( pNext );
 
    pNext = Abc_ObjFanout0(pObj);
    assert(Abc_ObjIsBo(pNext));
    assert(Abc_ObjFaninNum(pNext) == 1);
    assert(!Abc_ObjFaninC0(pNext));
  }
示例#11
0
/**Function*************************************************************

  Synopsis    [Verifies sequential equivalence by fraiging followed by SAT.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose )
{
    extern int Cmd_CommandExecute( void * pAbc, char * sCommand );
    extern void * Abc_FrameGetGlobalFrame();

    Prove_Params_t Params, * pParams = &Params;
    Abc_Ntk_t * pMiter, * pMiterPart;
    Abc_Obj_t * pObj;
    int i, RetValue, Status, nOutputs;

    // solve the CNF using the SAT solver
    Prove_ParamsSetDefault( pParams );
    pParams->nItersMax = 5;
    //    pParams->fVerbose = 1;

    assert( nPartSize > 0 );

    // get the miter of the two networks
    pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize );
    if ( pMiter == NULL )
    {
        printf( "Miter computation has failed.\n" );
        return;
    }
    RetValue = Abc_NtkMiterIsConstant( pMiter );
    if ( RetValue == 0 )
    {
        printf( "Networks are NOT EQUIVALENT after structural hashing.\n" );
        // report the error
        pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 );
        Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
        FREE( pMiter->pModel );
        Abc_NtkDelete( pMiter );
        return;
    }
    if ( RetValue == 1 )
    {
        printf( "Networks are equivalent after structural hashing.\n" );
        Abc_NtkDelete( pMiter );
        return;
    }

    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" );

    // solve the problem iteratively for each output of the miter
    Status = 1;
    nOutputs = 0;
    Abc_NtkForEachPo( pMiter, pObj, i )
    {
        if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) )
        {
            if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0
                RetValue = 1;
            else
                RetValue = 0;
            pMiterPart = NULL;
        }
        else
        {
            // get the cone of this output
            pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 );
            if ( Abc_ObjFaninC0(pObj) )
                Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 );
            // solve the cone
        //    RetValue = Abc_NtkMiterProve( &pMiterPart, pParams );
            RetValue = Abc_NtkIvyProve( &pMiterPart, pParams );
        }

        if ( RetValue == -1 )
        {
            printf( "Networks are undecided (resource limits is reached).\r" );
            Status = -1;
        }
        else if ( RetValue == 0 )
        {
            int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel );
            if ( pSimInfo[0] != 1 )
                printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" );
            else
                printf( "Networks are NOT EQUIVALENT.                 \n" );
            free( pSimInfo );
            Status = 0;
            break;
        }
        else
        {
            printf( "Finished part %d (out of %d)\r", i+1, Abc_NtkPoNum(pMiter) );
            nOutputs += nPartSize;
        }
//        if ( pMiter->pModel )
//            Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel );
        if ( pMiterPart )
            Abc_NtkDelete( pMiterPart );
    }

    Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" );

    if ( Status == 1 )
        printf( "Networks are equivalent.                         \n" );
    else if ( Status == -1 )
        printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) );
    Abc_NtkDelete( pMiter );
}
        // clean the label
        Abc_ObjForEachFanout( pObj, pFanout, i )
            pFanout->fMarkC = 0;
        // update the fanin edges
        Abc_ObjRetimeBackwardUpdateEdge( pObj, 0, tTable );
        Abc_ObjRetimeBackwardUpdateEdge( pObj, 1, tTable );
        Seq_NodeInsertFirst( pObj, 0, ABC_INIT_DC );
        Seq_NodeInsertFirst( pObj, 1, ABC_INIT_DC );
        return 0;
    }
    // the initial values on the fanout edges contain 0, 1, or unknown
    // the new values on the fanin edges will be unknown

    // add new AND-gate to the network
    pNodeNew = Abc_NtkCreateNode( pNtkNew );
    pNodeNew->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );

    // add PO fanouts if any
    if ( fMet0 )
    {
        Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew );
        Vec_IntPush( vValues, 0 );
    }
    if ( fMet1 )
    {
        Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew );
        Vec_IntPush( vValues, 1 );
    }

    // make sure the label is clean
    Abc_ObjForEachFanout( pObj, pFanout, i )
示例#13
0
Abc_Ntk_t * My_Command_Associative(Abc_Ntk_t * pNtk)
{// check abc.h and abcNtk.c(Abc_ntkDup, duplication) freeXXX
	//a new network to return
    printf("inside the My_Command_Associative\n");
	Abc_Ntk_t * new_pNtk;
	Abc_Obj_t * pObj;

	int i, j,k,m;
    int changed = 0;
	//check partial nodes satisfying a certain associative law
	Abc_NtkForEachObj( pNtk, pObj, i)
	{
        //printf("Node ID: %d \n", Abc_ObjId(pObj));
        //printf("FanInNum: %d \n",Abc_ObjFaninNum(pObj));

        if(changed <1 && Abc_ObjFaninNum(pObj) == 2 && !Abc_ObjFaninC0(pObj) && !Abc_ObjFaninC1(pObj) )
        {
            Abc_Obj_t * pFanin_0 = Abc_ObjFanin0(pObj);
            Abc_Obj_t * pFanin_1 = Abc_ObjFanin1(pObj);
            // (x*y)*z => x*(y*z)
            if(changed <1 && Abc_ObjFaninNum(pFanin_0) == 2 && !Abc_ObjFaninC0(pFanin_0) && !Abc_ObjFaninC1(pFanin_0) ) // (x*y)*z => x*(y*z)
            {
               printf("1st Condition, Node ID: %d\n",Abc_ObjId(pObj) );
               printf("Abc_ObjFaninNum(pFanin_0): Node ID: %d\n",Abc_ObjId(pFanin_0) );
               Abc_Obj_t * tempObj;
               Abc_Obj_t * pFanin_0_0 = Abc_ObjFanin0(pFanin_0);
               Abc_Obj_t * pFanin_0_1 = Abc_ObjFanin1(pFanin_0);

               Abc_Obj_t * NewParentNode = Abc_NtkDupObj(pNtk, pObj, 1);
               Abc_Obj_t * NewChildNode = Abc_NtkDupObj(pNtk, pFanin_0, 1);

               int FanoutNum = Abc_ObjFanoutNum(pObj);

               for (j=0; j<FanoutNum; j++)
               {
                tempObj = Abc_ObjFanout(pObj, j);
                Abc_ObjDeleteFanin( tempObj , pObj );
                Abc_ObjAddFanin( tempObj, NewParentNode);
               }
               printf("ParentNode Created and connected\n" );
               Abc_ObjAddFanin(NewParentNode,pFanin_0_0 );
               Abc_ObjAddFanin( NewParentNode, NewChildNode );
               Abc_ObjAddFanin( NewChildNode, pFanin_0_1);
               Abc_ObjAddFanin(NewChildNode,pFanin_1 );
               printf("ChildNode Created and connected\n" );

               printf("Abc_ObjFanoutNum(pFanin_0): %d\n",Abc_ObjFanoutNum(pFanin_0) );
               if(Abc_ObjFanoutNum(pFanin_0)>1)
               {
               		printf("pFanin_0 's FanOut > 1\n" );
               }
               else
               {
               	   Abc_ObjForEachFanin(pFanin_0,tempObj, k )
	               {
	                	Abc_ObjDeleteFanin(pFanin_0,tempObj);
	               }                 
	               Abc_NtkDeleteObj(pFanin_0);      	
               }
               Abc_ObjForEachFanin(pObj,tempObj, k )
               {
                	Abc_ObjDeleteFanin(pObj,tempObj);
               }