| /**CFile**************************************************************** |
| |
| FileName [bmcMesh.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [SAT-based bounded model checking.] |
| |
| Synopsis [Synthesis for mesh of LUTs.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: bmcMesh.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "bmc.h" |
| #include "sat/satoko/satoko.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| #define NCPARS 16 |
| |
| static inline int Bmc_MeshTVar( int Me[102][102], int x, int y ) { return Me[x][y]; } |
| static inline int Bmc_MeshGVar( int Me[102][102], int x, int y ) { return Me[x][y] + Me[101][100]; } |
| static inline int Bmc_MeshCVar( int Me[102][102], int x, int y ) { return Me[x][y] + Me[101][100] + Me[101][101]; } |
| static inline int Bmc_MeshUVar( int Me[102][102], int x, int y ) { return Me[x][y] + Me[101][100] + Me[101][101] + NCPARS; } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static inline int Bmc_MeshVarValue( satoko_t * p, int v ) |
| { |
| // int value = var_value(p, v) != SATOKO_VAR_UNASSING ? var_value(p, v) : satoko_var_polarity(p, v); |
| // return value == SATOKO_LIT_TRUE; |
| return satoko_var_polarity(p, v) == SATOKO_LIT_TRUE; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Bmc_MeshAddOneHotness( satoko_t * pSat, int iFirst, int iLast ) |
| { |
| int i, j, v, pVars[100], nVars = 0, nCount = 0; |
| assert( iFirst < iLast && iFirst + 110 > iLast ); |
| for ( v = iFirst; v < iLast; v++ ) |
| if ( Bmc_MeshVarValue(pSat, v) ) // v = 1 |
| { |
| assert( nVars < 100 ); |
| pVars[ nVars++ ] = v; |
| } |
| if ( nVars <= 1 ) |
| return 0; |
| for ( i = 0; i < nVars; i++ ) |
| for ( j = i+1; j < nVars; j++ ) |
| { |
| int pLits[2], RetValue; |
| pLits[0] = Abc_Var2Lit( pVars[i], 1 ); |
| pLits[1] = Abc_Var2Lit( pVars[j], 1 ); |
| RetValue = satoko_add_clause( pSat, pLits, 2 ); assert( RetValue ); |
| nCount++; |
| } |
| return nCount; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Bmc_MeshTest( Gia_Man_t * p, int X, int Y, int T, int fVerbose ) |
| { |
| abctime clk = Abc_Clock(); |
| satoko_t * pSat = satoko_create(); |
| Gia_Obj_t * pObj; |
| int Me[102][102] = {{0}}; |
| int pN[102][2] = {{0}}; |
| int I = Gia_ManPiNum(p); |
| int G = I + Gia_ManAndNum(p); |
| int i, x, y, t, g, c, status, RetValue, Lit, iVar, nClauses = 0; |
| |
| assert( X <= 100 && Y <= 100 && T <= 100 && G <= 100 ); |
| |
| // init the graph |
| for ( i = 0; i < I; i++ ) |
| pN[i][0] = pN[i][1] = -1; |
| Gia_ManForEachAnd( p, pObj, i ) |
| { |
| pN[i-1][0] = Gia_ObjFaninId0(pObj, i)-1; |
| pN[i-1][1] = Gia_ObjFaninId1(pObj, i)-1; |
| } |
| if ( fVerbose ) |
| { |
| printf( "The graph has %d inputs: ", Gia_ManPiNum(p) ); |
| for ( i = 0; i < I; i++ ) |
| printf( "%c ", 'a' + i ); |
| printf( " and %d nodes: ", Gia_ManAndNum(p) ); |
| for ( i = I; i < G; i++ ) |
| printf( "%c=%c%c ", 'a' + i, 'a' + pN[i][0] , 'a' + pN[i][1] ); |
| printf( "\n" ); |
| } |
| |
| // init SAT variables (time vars + graph vars + config vars) |
| // config variables: 16 = 4 buff vars + 12 node vars |
| iVar = 0; |
| for ( y = 0; y < Y; y++ ) |
| for ( x = 0; x < X; x++ ) |
| { |
| //printf( "%3d %3d %3d %s", iVar, iVar+T, iVar+T+G, x == X-1 ? "\n":"" ); |
| Me[x][y] = iVar; |
| iVar += T + G + NCPARS + 1; |
| } |
| Me[101][100] = T; |
| Me[101][101] = G; |
| if ( fVerbose ) |
| printf( "SAT variable count is %d (%d time vars + %d graph vars + %d config vars + %d aux vars)\n", iVar, X*Y*T, X*Y*G, X*Y*NCPARS, X*Y ); |
| |
| // add constraints |
| |
| // time 0 and primary inputs only on the boundary |
| for ( x = 0; x < X; x++ ) |
| for ( y = 0; y < Y; y++ ) |
| { |
| int iTVar = Bmc_MeshTVar( Me, x, y ); |
| int iGVar = Bmc_MeshGVar( Me, x, y ); |
| |
| if ( x == 0 || x == X-1 || y == 0 || y == Y-1 ) // boundary |
| { |
| // time 0 is required |
| for ( t = 0; t < T; t++ ) |
| { |
| Lit = Abc_Var2Lit( iTVar+t, (int)(t > 0) ); |
| RetValue = satoko_add_clause( pSat, &Lit, 1 ); assert( RetValue ); |
| } |
| // internal nodes are not allowed |
| for ( g = I; g < G; g++ ) |
| { |
| Lit = Abc_Var2Lit( iGVar+g, 1 ); |
| RetValue = satoko_add_clause( pSat, &Lit, 1 ); assert( RetValue ); |
| } |
| } |
| else // not a boundary |
| { |
| Lit = Abc_Var2Lit( iTVar, 1 ); // cannot have time 0 |
| RetValue = satoko_add_clause( pSat, &Lit, 1 ); assert( RetValue ); |
| } |
| } |
| for ( x = 1; x < X-1; x++ ) |
| for ( y = 1; y < Y-1; y++ ) |
| { |
| int pLits[100], nLits; |
| |
| int iTVar = Bmc_MeshTVar( Me, x, y ); |
| int iGVar = Bmc_MeshGVar( Me, x, y ); |
| int iCVar = Bmc_MeshCVar( Me, x, y ); |
| int iUVar = Bmc_MeshUVar( Me, x, y ); |
| |
| // 0=left 1=up 2=right 3=down |
| int iTVars[4]; |
| int iGVars[4]; |
| |
| iTVars[0] = Bmc_MeshTVar( Me, x-1, y ); |
| iGVars[0] = Bmc_MeshGVar( Me, x-1, y ); |
| |
| iTVars[1] = Bmc_MeshTVar( Me, x, y-1 ); |
| iGVars[1] = Bmc_MeshGVar( Me, x, y-1 ); |
| |
| iTVars[2] = Bmc_MeshTVar( Me, x+1, y ); |
| iGVars[2] = Bmc_MeshGVar( Me, x+1, y ); |
| |
| iTVars[3] = Bmc_MeshTVar( Me, x, y+1 ); |
| iGVars[3] = Bmc_MeshGVar( Me, x, y+1 ); |
| |
| // condition when cell is used |
| for ( g = 0; g < G; g++ ) |
| { |
| pLits[0] = Abc_Var2Lit( iGVar+g, 1 ); |
| pLits[1] = Abc_Var2Lit( iUVar, 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, 2 ); assert( RetValue ); |
| nClauses++; |
| } |
| |
| // at least one time is used |
| pLits[0] = Abc_Var2Lit( iUVar, 1 ); |
| for ( t = 1; t < T; t++ ) |
| pLits[t] = Abc_Var2Lit( iTVar+t, 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, T ); assert( RetValue ); |
| nClauses++; |
| |
| // at least one config is used |
| pLits[0] = Abc_Var2Lit( iUVar, 1 ); |
| for ( c = 0; c < NCPARS; c++ ) |
| pLits[c+1] = Abc_Var2Lit( iCVar+c, 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, NCPARS+1 ); assert( RetValue ); |
| nClauses++; |
| |
| // constraints for each time |
| for ( t = 1; t < T; t++ ) |
| { |
| int Conf[12][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}, {1, 0}, {2, 0}, {3, 0}, {2, 1}, {3, 1}, {3, 2}}; |
| // buffer |
| for ( g = 0; g < G; g++ ) |
| for ( c = 0; c < 4; c++ ) |
| { |
| nLits = 0; |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVar+t, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVar+g, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iCVar+c, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVars[c]+t-1, 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, nLits ); assert( RetValue ); |
| |
| nLits = 0; |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVar+t, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVar+g, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iCVar+c, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVars[c]+g, 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, nLits ); assert( RetValue ); |
| |
| nClauses += 2; |
| } |
| for ( g = 0; g < I; g++ ) |
| for ( c = 4; c < NCPARS; c++ ) |
| { |
| pLits[0] = Abc_Var2Lit( iGVar+g, 1 ); |
| pLits[1] = Abc_Var2Lit( iCVar+c, 1 ); |
| RetValue = satoko_add_clause( pSat, pLits, 2 ); assert( RetValue ); |
| nClauses++; |
| } |
| // node |
| for ( g = I; g < G; g++ ) |
| for ( c = 0; c < 12; c++ ) |
| { |
| assert( pN[g][0] >= 0 && pN[g][1] >= 0 ); |
| |
| nLits = 0; |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVar+t, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVar+g, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iCVar+c+4, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVars[Conf[c][0]]+t-1, 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, nLits ); assert( RetValue ); |
| |
| nLits = 0; |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVar+t, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVar+g, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iCVar+c+4, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVars[Conf[c][1]]+t-1, 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, nLits ); assert( RetValue ); |
| |
| |
| nLits = 0; |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVar+t, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVar+g, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iCVar+c+4, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVars[Conf[c][0]]+pN[g][0], 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, nLits ); assert( RetValue ); |
| |
| nLits = 0; |
| pLits[ nLits++ ] = Abc_Var2Lit( iTVar+t, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVar+g, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iCVar+c+4, 1 ); |
| pLits[ nLits++ ] = Abc_Var2Lit( iGVars[Conf[c][1]]+pN[g][1], 0 ); |
| RetValue = satoko_add_clause( pSat, pLits, nLits ); assert( RetValue ); |
| |
| nClauses += 4; |
| } |
| } |
| } |
| |
| // final condition |
| { |
| int iGVar = Bmc_MeshGVar( Me, 1, 1 ) + G-1; |
| Lit = Abc_Var2Lit( iGVar, 0 ); |
| RetValue = satoko_add_clause( pSat, &Lit, 1 ); |
| if ( RetValue == 0 ) |
| { |
| printf( "Problem has no solution. " ); |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| satoko_destroy( pSat ); |
| return; |
| } |
| } |
| |
| if ( fVerbose ) |
| printf( "Finished adding %d clauses. Started solving...\n", nClauses ); |
| |
| while ( 1 ) |
| { |
| int nAddClauses = 0; |
| status = satoko_solve( pSat ); |
| if ( status == SATOKO_UNSAT ) |
| { |
| printf( "Problem has no solution. " ); |
| break; |
| } |
| if ( status == SATOKO_UNDEC ) |
| { |
| printf( "Computation timed out. " ); |
| break; |
| } |
| assert( status == SATOKO_SAT ); |
| // check if the solution is valid and add constraints |
| for ( x = 0; x < X; x++ ) |
| for ( y = 0; y < Y; y++ ) |
| { |
| if ( x == 0 || x == X-1 || y == 0 || y == Y-1 ) // boundary |
| { |
| int iGVar = Bmc_MeshGVar( Me, x, y ); |
| nAddClauses += Bmc_MeshAddOneHotness( pSat, iGVar, iGVar + G ); |
| } |
| else |
| { |
| int iTVar = Bmc_MeshTVar( Me, x, y ); |
| int iGVar = Bmc_MeshGVar( Me, x, y ); |
| int iCVar = Bmc_MeshCVar( Me, x, y ); |
| nAddClauses += Bmc_MeshAddOneHotness( pSat, iTVar, iTVar + T ); |
| nAddClauses += Bmc_MeshAddOneHotness( pSat, iGVar, iGVar + G ); |
| nAddClauses += Bmc_MeshAddOneHotness( pSat, iCVar, iCVar + NCPARS ); |
| } |
| } |
| if ( nAddClauses > 0 ) |
| { |
| printf( "Adding %d one-hotness clauses.\n", nAddClauses ); |
| continue; |
| } |
| printf( "Satisfying solution found. " ); |
| /* |
| iVar = satoko_varnum(pSat); |
| for ( i = 0; i < iVar; i++ ) |
| if ( Bmc_MeshVarValue(pSat, i) ) |
| printf( "%d ", i ); |
| printf( "\n" ); |
| */ |
| break; |
| } |
| Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); |
| if ( status == SATOKO_SAT ) |
| { |
| // count the number of nodes and buffers |
| int nBuffs = 0, nNodes = 0; |
| for ( y = 1; y < Y-1; y++ ) |
| for ( x = 1; x < X-1; x++ ) |
| { |
| int iCVar = Bmc_MeshCVar( Me, x, y ); |
| for ( c = 0; c < 4; c++ ) |
| if ( Bmc_MeshVarValue(pSat, iCVar+c) ) |
| { |
| //printf( "Buffer y=%d x=%d (var = %d; config = %d)\n", y, x, iCVar+c, c ); |
| nBuffs++; |
| } |
| for ( c = 4; c < NCPARS; c++ ) |
| if ( Bmc_MeshVarValue(pSat, iCVar+c) ) |
| { |
| //printf( "Node y=%d x=%d (var = %d; config = %d)\n", y, x, iCVar+c, c ); |
| nNodes++; |
| } |
| } |
| printf( "The %d x %d mesh with latency %d with %d active cells (%d nodes and %d buffers):\n", X, Y, T, nNodes+nBuffs, nNodes, nBuffs ); |
| // print mesh |
| printf( " Y\\X " ); |
| for ( x = 0; x < X; x++ ) |
| printf( " %-2d ", x ); |
| printf( "\n" ); |
| for ( y = 0; y < Y; y++ ) |
| { |
| printf( " %-2d ", y ); |
| for ( x = 0; x < X; x++ ) |
| { |
| int iTVar = Bmc_MeshTVar( Me, x, y ); |
| int iGVar = Bmc_MeshGVar( Me, x, y ); |
| |
| int fFound = 0; ; |
| for ( t = 0; t < T; t++ ) |
| for ( g = 0; g < G; g++ ) |
| if ( Bmc_MeshVarValue(pSat, iTVar+t) && Bmc_MeshVarValue(pSat, iGVar+g) ) |
| { |
| printf( " %c%-2d ", 'a' + g, t ); |
| fFound = 1; |
| } |
| if ( fFound ) |
| continue; |
| if ( x == 0 || x == X-1 || y == 0 || y == Y-1 ) // boundary |
| printf( " * " ); |
| else |
| printf( " " ); |
| } |
| printf( "\n" ); |
| } |
| } |
| satoko_destroy( pSat ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |