/**CFile**************************************************************** FileName [abcFpga.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Interface with the FPGA mapping package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFpga.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "fpgaInt.h" //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fVerbose ); static Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ); static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Interface with the FPGA mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, int fRecovery, int fSwitching, int fVerbose ) { int fShowSwitching = 1; Abc_Ntk_t * pNtkNew; Fpga_Man_t * pMan; Vec_Int_t * vSwitching; float * pSwitching = NULL; assert( Abc_NtkIsStrash(pNtk) ); // print a warning about choice nodes if ( Abc_NtkGetChoiceNum( pNtk ) ) printf( "Performing FPGA mapping with choices.\n" ); // compute switching activity fShowSwitching |= fSwitching; if ( fShowSwitching ) { extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); pSwitching = (float *)vSwitching->pArray; } // perform FPGA mapping pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fVerbose ); if ( pSwitching ) Vec_IntFree( vSwitching ); if ( pMan == NULL ) return NULL; Fpga_ManSetSwitching( pMan, fSwitching ); if ( !Fpga_Mapping( pMan ) ) { Fpga_ManFree( pMan ); return NULL; } // transform the result of mapping into a BDD network pNtkNew = Abc_NtkFromFpga( pMan, pNtk ); if ( pNtkNew == NULL ) return NULL; Fpga_ManFree( pMan ); // make the network minimum base Abc_NtkMinimumBase( pNtkNew ); // make sure that everything is okay if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkFpga: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Load the network into FPGA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fVerbose ) { Fpga_Man_t * pMan; ProgressBar * pProgress; Fpga_Node_t * pNodeFpga; 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 = Fpga_ManCreate( Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), fVerbose ); if ( pMan == NULL ) return NULL; Fpga_ManSetAreaRecovery( pMan, fRecovery ); Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); Fpga_ManSetInputArrivals( pMan, Abc_NtkGetCiArrivalFloats(pNtk) ); // create PIs and remember them in the old nodes Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachCi( pNtk, pNode, i ) { pNodeFpga = Fpga_ManReadInputs(pMan)[i]; pNode->pCopy = (Abc_Obj_t *)pNodeFpga; if ( pSwitching ) Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); } // load the AIG into the mapper vNodes = Abc_AigDfs( pNtk, 0, 0 ); pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); Vec_PtrForEachEntry( vNodes, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // consider the case of a constant if ( Abc_NodeIsConst(pNode) ) { Abc_AigConst1(pNtk->pManFunc)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan); continue; } // 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_NodeIsAigChoice( 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 ); } } Extra_ProgressBarStop( pProgress ); Vec_PtrFree( vNodes ); // set the primary outputs without copying the phase Abc_NtkForEachCo( pNtk, pNode, i ) Fpga_ManReadOutputs(pMan)[i] = (Fpga_Node_t *)Abc_ObjFanin0(pNode)->pCopy; return pMan; } /**Function************************************************************* Synopsis [Creates the mapped network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ) { ProgressBar * pProgress; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode, * pNodeNew; int i, nDupGates; // create the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); // make the mapper point to the new network Fpga_CutsCleanSign( pMan ); Fpga_ManCleanData0( pMan ); Abc_NtkForEachCi( pNtk, pNode, i ) Fpga_NodeSetData0( Fpga_ManReadInputs(pMan)[i], (char *)pNode->pCopy ); // set the constant node if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk->pManFunc) ) > 0 ) Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NodeCreateConst1(pNtkNew) ); // process the nodes in topological order pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); pNodeNew = Abc_NodeFromFpga_rec( pNtkNew, Fpga_ManReadOutputs(pMan)[i] ); assert( !Abc_ObjIsComplement(pNodeNew) ); Abc_ObjFanin0(pNode)->pCopy = pNodeNew; } Extra_ProgressBarStop( pProgress ); // finalize the new network Abc_NtkFinalize( pNtk, pNtkNew ); // decouple the PO driver nodes to reduce the number of levels nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); // if ( nDupGates && Fpga_ManReadVerbose(pMan) ) // printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); return pNtkNew; } /**Function************************************************************* Synopsis [Derive one node after FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ) { Fpga_Cut_t * pCutBest; Fpga_Node_t ** ppLeaves; Abc_Obj_t * pNodeNew; int i, nLeaves; assert( !Fpga_IsComplement(pNodeFpga) ); // return if the result if known pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0( pNodeFpga ); if ( pNodeNew ) return pNodeNew; assert( Fpga_NodeIsAnd(pNodeFpga) ); // get the parameters of the best cut pCutBest = Fpga_NodeReadCutBest( pNodeFpga ); ppLeaves = Fpga_CutReadLeaves( pCutBest ); nLeaves = Fpga_CutReadLeavesNum( pCutBest ); // create a new node pNodeNew = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < nLeaves; i++ ) Abc_ObjAddFanin( pNodeNew, Abc_NodeFromFpga_rec(pNtkNew, ppLeaves[i]) ); // derive the function of this node pNodeNew->pData = Fpga_TruthsCutBdd( pNtkNew->pManFunc, pCutBest ); Cudd_Ref( pNodeNew->pData ); Fpga_NodeSetData0( pNodeFpga, (char *)pNodeNew ); return pNodeNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// ////////////////////////////////////////////////////////////////////////