| /**CFile**************************************************************** |
| |
| FileName [cutPre22.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Network and node package.] |
| |
| Synopsis [Precomputes truth tables for the 2x2 macro cell.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "cutInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| #define CUT_CELL_MVAR 9 |
| |
| typedef struct Cut_Cell_t_ Cut_Cell_t; |
| typedef struct Cut_CMan_t_ Cut_CMan_t; |
| |
| struct Cut_Cell_t_ |
| { |
| Cut_Cell_t * pNext; // pointer to the next cell in the table |
| Cut_Cell_t * pNextVar; // pointer to the next cell of this support size |
| Cut_Cell_t * pParent; // pointer to the cell used to derive this one |
| int nUsed; // the number of times the cell is used |
| char Box[4]; // functions in the boxes |
| unsigned nVars : 4; // the number of variables |
| unsigned CrossBar0 : 4; // the variable set equal |
| unsigned CrossBar1 : 4; // the variable set equal |
| unsigned CrossBarPhase : 2; // the phase of the cross bar (0, 1, or 2) |
| unsigned CanonPhase : 18; // the canonical phase |
| char CanonPerm[CUT_CELL_MVAR+3]; // semicanonical permutation |
| short Store[2*CUT_CELL_MVAR]; // minterm counts in the cofactors |
| unsigned uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table |
| }; |
| |
| struct Cut_CMan_t_ |
| { |
| // storage for canonical cells |
| Extra_MmFixed_t * pMem; |
| st__table * tTable; |
| Cut_Cell_t * pSameVar[CUT_CELL_MVAR+1]; |
| // elementary truth tables |
| unsigned uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)]; |
| // temporary truth tables |
| unsigned uTemp1[22][1<<(CUT_CELL_MVAR-5)]; |
| unsigned uTemp2[22][1<<(CUT_CELL_MVAR-5)]; |
| unsigned uTemp3[22][1<<(CUT_CELL_MVAR-5)]; |
| unsigned uFinal[1<<(CUT_CELL_MVAR-5)]; |
| unsigned puAux[1<<(CUT_CELL_MVAR-5)]; |
| // statistical variables |
| int nTotal; |
| int nGood; |
| int nVarCounts[CUT_CELL_MVAR+1]; |
| int nSymGroups[CUT_CELL_MVAR+1]; |
| int nSymGroupsE[CUT_CELL_MVAR+1]; |
| abctime timeCanon; |
| abctime timeSupp; |
| abctime timeTable; |
| int nCellFound; |
| int nCellNotFound; |
| }; |
| |
| // NP-classes of functions of 3 variables (22) |
| //static char * s_NP3[22] = { |
| // " 0\n", // 00 const 0 // 0 vars |
| // " 1\n", // 01 const 1 // 0 vars |
| // "1 1\n", // 02 a // 1 vars |
| // "11 1\n", // 03 ab // 2 vars |
| // "11 0\n", // 04 (ab)' // 2 vars |
| // "10 1\n01 1\n", // 05 a<+>b // 2 vars |
| // "111 1\n", // 06 0s abc // 3 vars |
| // "111 0\n", // 07 (abc)' // |
| // "11- 1\n1-1 1\n", // 08 1p a(b+c) // |
| // "11- 0\n1-1 0\n", // 09 (a(b+c))' // |
| // "111 1\n100 1\n010 1\n001 1\n", // 10 2s a<+>b<+>c // |
| // "10- 0\n1-0 0\n011 0\n", // 11 3p a<+>bc // |
| // "101 1\n110 1\n", // 12 4p a(b<+>c) // |
| // "101 0\n110 0\n", // 13 (a(b<+>c))' // |
| // "11- 1\n1-1 1\n-11 1\n", // 14 5s ab+bc+ac // |
| // "111 1\n000 1\n", // 15 6s abc+a'b'c' // |
| // "111 0\n000 0\n", // 16 (abc+a'b'c')' // |
| // "11- 1\n-11 1\n0-1 1\n", // 17 7 ab+bc+a'c // |
| // "011 1\n101 1\n110 1\n", // 18 8s a'bc+ab'c+abc' // |
| // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' // |
| // "100 1\n-11 1\n", // 20 9p ab'c'+bc // |
| // "100 0\n-11 0\n" // 21 (ab'c'+bc)' // |
| //}; |
| |
| // NP-classes of functions of 3 variables (22) |
| static char * s_NP3Names[22] = { |
| " const 0 ", |
| " const 1 ", |
| " a ", |
| " ab ", |
| " (ab)' ", |
| " a<+>b ", |
| "0s abc ", |
| " (abc)' ", |
| "1p a(b+c) ", |
| " (a(b+c))' ", |
| "2s a<+>b<+>c ", |
| "3p a<+>bc ", |
| "4p a(b<+>c) ", |
| " (a(b<+>c))' ", |
| "5s ab+bc+ac ", |
| "6s abc+a'b'c' ", |
| " (abc+a'b'c')' ", |
| "7 ab+bc+a'c ", |
| "8s a'bc+ab'c+abc' ", |
| " (a'bc+ab'c+abc')' ", |
| "9p ab'c'+bc ", |
| " (ab'c'+bc)' " |
| }; |
| |
| // the number of variables in each function |
| //static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; |
| |
| // NPN classes of functions of exactly 3 inputs (10) |
| static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 }; |
| |
| // NPN classes of functions of exactly 3 inputs that are symmetric (5) |
| //static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 }; |
| |
| // NPN classes of functions of exactly 3 inputs (4) |
| //static int s_NPNe3p[10] = { 8, 11, 12, 20 }; |
| |
| static Cut_CMan_t * Cut_CManStart(); |
| static void Cut_CManStop( Cut_CMan_t * p ); |
| static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ); |
| static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell ); |
| static int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ); |
| static void Cut_CellSuppMin( Cut_Cell_t * pCell ); |
| static void Cut_CellCrossBar( Cut_Cell_t * pCell ); |
| |
| |
| static Cut_CMan_t * s_pCMan = NULL; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Start the precomputation manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cut_CellLoad() |
| { |
| FILE * pFile; |
| char * pFileName = "cells22_daomap_iwls.txt"; |
| char pString[1000]; |
| Cut_CMan_t * p; |
| Cut_Cell_t * pCell; |
| int Length; //, i; |
| pFile = fopen( pFileName, "r" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cannot open file \"%s\".\n", pFileName ); |
| return; |
| } |
| // start the manager |
| p = Cut_CManStart(); |
| // load truth tables |
| while ( fgets(pString, 1000, pFile) ) |
| { |
| Length = strlen(pString); |
| pString[Length--] = 0; |
| if ( Length == 0 ) |
| continue; |
| // derive the cell |
| pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); |
| memset( pCell, 0, sizeof(Cut_Cell_t) ); |
| pCell->nVars = Abc_Base2Log(Length*4); |
| pCell->nUsed = 1; |
| // Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); |
| Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars ); |
| Cut_CellSuppMin( pCell ); |
| /* |
| // set the elementary permutation |
| for ( i = 0; i < (int)pCell->nVars; i++ ) |
| pCell->CanonPerm[i] = i; |
| // canonicize |
| pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); |
| */ |
| // add to the table |
| p->nTotal++; |
| |
| // Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" ); |
| // if ( p->nTotal == 500 ) |
| // break; |
| |
| if ( !Cut_CellTableLookup( p, pCell ) ) // new cell |
| p->nGood++; |
| } |
| printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood ); |
| fclose( pFile ); |
| // return p; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Precomputes truth tables for the 2x2 macro cell.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cut_CellPrecompute() |
| { |
| Cut_CMan_t * p; |
| Cut_Cell_t * pCell, * pTemp; |
| int i1, i2, i3, i, j, k, c; |
| abctime clk = Abc_Clock(); //, clk2 = Abc_Clock(); |
| |
| p = Cut_CManStart(); |
| |
| // precompute truth tables |
| for ( i = 0; i < 22; i++ ) |
| Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i ); |
| for ( i = 0; i < 22; i++ ) |
| Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i ); |
| for ( i = 0; i < 22; i++ ) |
| Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i ); |
| /* |
| if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) ) |
| { |
| Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " ); |
| for ( i = 0; i < pCell->nVars; i++ ) |
| printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); |
| Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); |
| printf( "\n" ); |
| } |
| */ |
| /* |
| // go through symmetric roots |
| for ( k = 0; k < 5; k++ ) |
| for ( i1 = 0; i1 < 22; i1++ ) |
| for ( i2 = i1; i2 < 22; i2++ ) |
| for ( i3 = i2; i3 < 22; i3++ ) |
| { |
| // derive the cell |
| pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); |
| memset( pCell, 0, sizeof(Cut_Cell_t) ); |
| pCell->nVars = 9; |
| pCell->Box[0] = s_NPNe3s[k]; |
| pCell->Box[1] = i1; |
| pCell->Box[2] = i2; |
| pCell->Box[3] = i3; |
| // fill in the truth table |
| Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] ); |
| // canonicize |
| Cut_CellCanonicize( pCell ); |
| |
| // add to the table |
| p->nTotal++; |
| if ( Cut_CellTableLookup( p, pCell ) ) // already exists |
| Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); |
| else |
| p->nGood++; |
| } |
| |
| // go through partially symmetric roots |
| for ( k = 0; k < 4; k++ ) |
| for ( i1 = 0; i1 < 22; i1++ ) |
| for ( i2 = 0; i2 < 22; i2++ ) |
| for ( i3 = i2; i3 < 22; i3++ ) |
| { |
| // derive the cell |
| pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); |
| memset( pCell, 0, sizeof(Cut_Cell_t) ); |
| pCell->nVars = 9; |
| pCell->Box[0] = s_NPNe3p[k]; |
| pCell->Box[1] = i1; |
| pCell->Box[2] = i2; |
| pCell->Box[3] = i3; |
| // fill in the truth table |
| Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] ); |
| // canonicize |
| Cut_CellCanonicize( pCell ); |
| |
| // add to the table |
| p->nTotal++; |
| if ( Cut_CellTableLookup( p, pCell ) ) // already exists |
| Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); |
| else |
| p->nGood++; |
| } |
| |
| // go through non-symmetric functions |
| for ( i1 = 0; i1 < 22; i1++ ) |
| for ( i2 = 0; i2 < 22; i2++ ) |
| for ( i3 = 0; i3 < 22; i3++ ) |
| { |
| // derive the cell |
| pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); |
| memset( pCell, 0, sizeof(Cut_Cell_t) ); |
| pCell->nVars = 9; |
| pCell->Box[0] = 17; |
| pCell->Box[1] = i1; |
| pCell->Box[2] = i2; |
| pCell->Box[3] = i3; |
| // fill in the truth table |
| Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 ); |
| // canonicize |
| Cut_CellCanonicize( pCell ); |
| |
| // add to the table |
| p->nTotal++; |
| if ( Cut_CellTableLookup( p, pCell ) ) // already exists |
| Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); |
| else |
| p->nGood++; |
| } |
| */ |
| |
| // go through non-symmetric functions |
| for ( k = 0; k < 10; k++ ) |
| for ( i1 = 0; i1 < 22; i1++ ) |
| for ( i2 = 0; i2 < 22; i2++ ) |
| for ( i3 = 0; i3 < 22; i3++ ) |
| { |
| // derive the cell |
| pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); |
| memset( pCell, 0, sizeof(Cut_Cell_t) ); |
| pCell->nVars = 9; |
| pCell->Box[0] = s_NPNe3[k]; |
| pCell->Box[1] = i1; |
| pCell->Box[2] = i2; |
| pCell->Box[3] = i3; |
| // set the elementary permutation |
| for ( i = 0; i < (int)pCell->nVars; i++ ) |
| pCell->CanonPerm[i] = i; |
| // fill in the truth table |
| Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] ); |
| // minimize the support |
| Cut_CellSuppMin( pCell ); |
| |
| // canonicize |
| pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); |
| |
| // add to the table |
| p->nTotal++; |
| if ( Cut_CellTableLookup( p, pCell ) ) // already exists |
| Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); |
| else |
| { |
| p->nGood++; |
| p->nVarCounts[pCell->nVars]++; |
| |
| if ( pCell->nVars ) |
| for ( i = 0; i < (int)pCell->nVars-1; i++ ) |
| { |
| if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric |
| continue; |
| // i and i+1 can be symmetric |
| // find the end of this group |
| for ( j = i+1; j < (int)pCell->nVars; j++ ) |
| if ( pCell->Store[2*i] != pCell->Store[2*j] ) |
| break; |
| |
| if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) |
| p->nSymGroupsE[j-i]++; |
| else |
| p->nSymGroups[j-i]++; |
| i = j - 1; |
| } |
| /* |
| if ( pCell->nVars == 3 ) |
| { |
| Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); |
| for ( i = 0; i < (int)pCell->nVars; i++ ) |
| printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); |
| printf( "\n" ); |
| } |
| */ |
| } |
| } |
| |
| printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", (int)p->nTotal, (int)p->nGood, (int)sizeof(Cut_Cell_t) ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| printf( "Cells: " ); |
| for ( i = 0; i <= 9; i++ ) |
| printf( "%d=%d ", i, p->nVarCounts[i] ); |
| printf( "\nDiffs: " ); |
| for ( i = 0; i <= 9; i++ ) |
| printf( "%d=%d ", i, p->nSymGroups[i] ); |
| printf( "\nEquals: " ); |
| for ( i = 0; i <= 9; i++ ) |
| printf( "%d=%d ", i, p->nSymGroupsE[i] ); |
| printf( "\n" ); |
| |
| // continue adding new cells using support |
| for ( k = CUT_CELL_MVAR; k > 3; k-- ) |
| { |
| for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) |
| for ( i1 = 0; i1 < k; i1++ ) |
| for ( i2 = i1+1; i2 < k; i2++ ) |
| for ( c = 0; c < 3; c++ ) |
| { |
| // derive the cell |
| pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); |
| memset( pCell, 0, sizeof(Cut_Cell_t) ); |
| pCell->nVars = pTemp->nVars; |
| pCell->pParent = pTemp; |
| // set the elementary permutation |
| for ( i = 0; i < (int)pCell->nVars; i++ ) |
| pCell->CanonPerm[i] = i; |
| // fill in the truth table |
| Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars ); |
| // create the cross-bar |
| pCell->CrossBar0 = i1; |
| pCell->CrossBar1 = i2; |
| pCell->CrossBarPhase = c; |
| Cut_CellCrossBar( pCell ); |
| // minimize the support |
| //clk2 = Abc_Clock(); |
| Cut_CellSuppMin( pCell ); |
| //p->timeSupp += Abc_Clock() - clk2; |
| // canonicize |
| //clk2 = Abc_Clock(); |
| pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); |
| //p->timeCanon += Abc_Clock() - clk2; |
| |
| // add to the table |
| //clk2 = Abc_Clock(); |
| p->nTotal++; |
| if ( Cut_CellTableLookup( p, pCell ) ) // already exists |
| Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); |
| else |
| { |
| p->nGood++; |
| p->nVarCounts[pCell->nVars]++; |
| |
| for ( i = 0; i < (int)pCell->nVars-1; i++ ) |
| { |
| if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric |
| continue; |
| // i and i+1 can be symmetric |
| // find the end of this group |
| for ( j = i+1; j < (int)pCell->nVars; j++ ) |
| if ( pCell->Store[2*i] != pCell->Store[2*j] ) |
| break; |
| |
| if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) |
| p->nSymGroupsE[j-i]++; |
| else |
| p->nSymGroups[j-i]++; |
| i = j - 1; |
| } |
| /* |
| if ( pCell->nVars == 3 ) |
| { |
| Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); |
| for ( i = 0; i < (int)pCell->nVars; i++ ) |
| printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); |
| printf( "\n" ); |
| } |
| */ |
| } |
| //p->timeTable += Abc_Clock() - clk2; |
| } |
| |
| printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, (int)sizeof(Cut_Cell_t) ); |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| printf( "Cells: " ); |
| for ( i = 0; i <= 9; i++ ) |
| printf( "%d=%d ", i, p->nVarCounts[i] ); |
| printf( "\nDiffs: " ); |
| for ( i = 0; i <= 9; i++ ) |
| printf( "%d=%d ", i, p->nSymGroups[i] ); |
| printf( "\nEquals: " ); |
| for ( i = 0; i <= 9; i++ ) |
| printf( "%d=%d ", i, p->nSymGroupsE[i] ); |
| printf( "\n" ); |
| } |
| // printf( "\n" ); |
| ABC_PRT( "Supp ", p->timeSupp ); |
| ABC_PRT( "Canon", p->timeCanon ); |
| ABC_PRT( "Table", p->timeTable ); |
| // Cut_CManStop( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Check the table.] |
| |
| Description [Returns 1 if such a truth table already exists.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ) |
| { |
| Cut_Cell_t ** pSlot, * pTemp; |
| unsigned Hash; |
| Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) ); |
| if ( ! st__find_or_add( p->tTable, (char *)(ABC_PTRUINT_T)Hash, (char ***)&pSlot ) ) |
| *pSlot = NULL; |
| for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext ) |
| { |
| if ( pTemp->nVars != pCell->nVars ) |
| continue; |
| if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) |
| return 1; |
| } |
| // the entry is new |
| pCell->pNext = *pSlot; |
| *pSlot = pCell; |
| // add it to the variable support list |
| pCell->pNextVar = p->pSameVar[pCell->nVars]; |
| p->pSameVar[pCell->nVars] = pCell; |
| return 0; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cut_CellSuppMin( Cut_Cell_t * pCell ) |
| { |
| static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; |
| unsigned * pIn, * pOut, * pTemp; |
| int i, k, Counter, Temp; |
| |
| // go backward through the support variables and remove redundant |
| for ( k = pCell->nVars - 1; k >= 0; k-- ) |
| if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) ) |
| { |
| // shift all the variables above this one |
| Counter = 0; |
| pIn = pCell->uTruth; pOut = uTemp; |
| for ( i = k; i < (int)pCell->nVars - 1; i++ ) |
| { |
| Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i ); |
| pTemp = pIn; pIn = pOut; pOut = pTemp; |
| // swap the support vars |
| Temp = pCell->CanonPerm[i]; |
| pCell->CanonPerm[i] = pCell->CanonPerm[i+1]; |
| pCell->CanonPerm[i+1] = Temp; |
| Counter++; |
| } |
| // return the function back into its place |
| if ( Counter & 1 ) |
| Extra_TruthCopy( pOut, pIn, pCell->nVars ); |
| // remove one variable |
| pCell->nVars--; |
| // Extra_PrintBinary( stdout, pCell->uTruth, (1<<pCell->nVars) ); printf( "\n" ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cut_CellCrossBar( Cut_Cell_t * pCell ) |
| { |
| static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)]; |
| static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)]; |
| Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars ); |
| Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars ); |
| if ( pCell->CanonPhase == 0 ) |
| { |
| Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); |
| Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); |
| Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); |
| Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); |
| } |
| else if ( pCell->CanonPhase == 1 ) |
| { |
| Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 ); |
| Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); |
| Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 ); |
| Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); |
| } |
| else if ( pCell->CanonPhase == 2 ) |
| { |
| Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); |
| Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 ); |
| Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); |
| Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 ); |
| } |
| else assert( 0 ); |
| Extra_TruthMux( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ) |
| { |
| int nWords = Extra_TruthWordNum( nVars ); |
| int i; |
| |
| assert( Type < 22 ); |
| switch ( Type ) |
| { |
| // " 0\n", // 00 const 0 |
| case 0: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = 0; |
| return; |
| // " 1\n", // 01 const 1 |
| case 1: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = 0xFFFFFFFF; |
| return; |
| // "1 1\n", // 02 a |
| case 2: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = InA[i]; |
| return; |
| // "11 1\n", // 03 ab |
| case 3: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = InA[i] & InB[i]; |
| return; |
| // "11 0\n", // 04 (ab)' |
| case 4: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = ~(InA[i] & InB[i]); |
| return; |
| // "10 1\n01 1\n", // 05 a<+>b |
| case 5: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = InA[i] ^ InB[i]; |
| return; |
| // "111 1\n", // 06 + abc |
| case 6: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = InA[i] & InB[i] & InC[i]; |
| return; |
| // "111 0\n", // 07 (abc)' |
| case 7: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = ~(InA[i] & InB[i] & InC[i]); |
| return; |
| // "11- 1\n1-1 1\n", // 08 + a(b+c) |
| case 8: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = InA[i] & (InB[i] | InC[i]); |
| return; |
| // "11- 0\n1-1 0\n", // 09 (a(b+c))' |
| case 9: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = ~(InA[i] & (InB[i] | InC[i])); |
| return; |
| // "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c |
| case 10: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = InA[i] ^ InB[i] ^ InC[i]; |
| return; |
| // "10- 0\n1-0 0\n011 0\n", // 11 + a<+>bc |
| case 11: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = InA[i] ^ (InB[i] & InC[i]); |
| return; |
| // "101 1\n110 1\n", // 12 + a(b<+>c) |
| case 12: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = InA[i] & (InB[i] ^ InC[i]); |
| return; |
| // "101 0\n110 0\n", // 13 (a(b<+>c))' |
| case 13: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = ~(InA[i] & (InB[i] ^ InC[i])); |
| return; |
| // "11- 1\n1-1 1\n-11 1\n", // 14 + ab+bc+ac |
| case 14: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]); |
| return; |
| // "111 1\n000 1\n", // 15 + abc+a'b'c' |
| case 15: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]); |
| return; |
| // "111 0\n000 0\n", // 16 (abc+a'b'c')' |
| case 16: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i])); |
| return; |
| // "11- 1\n-11 1\n0-1 1\n", // 17 + ab+bc+a'c |
| case 17: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]); |
| return; |
| // "011 1\n101 1\n110 1\n", // 18 + a'bc+ab'c+abc' |
| case 18: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]); |
| return; |
| // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' |
| case 19: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i])); |
| return; |
| // "100 1\n-11 1\n", // 20 + ab'c'+bc |
| case 20: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]); |
| return; |
| // "100 0\n-11 0\n" // 21 (ab'c'+bc)' |
| case 21: |
| for ( i = 0; i < nWords; i++ ) |
| pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i])); |
| return; |
| } |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Start the precomputation manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Cut_CMan_t * Cut_CManStart() |
| { |
| Cut_CMan_t * p; |
| int i, k; |
| // start the manager |
| assert( sizeof(unsigned) == 4 ); |
| p = ABC_ALLOC( Cut_CMan_t, 1 ); |
| memset( p, 0, sizeof(Cut_CMan_t) ); |
| // start the table and the memory manager |
| p->tTable = st__init_table( st__ptrcmp, st__ptrhash);; |
| p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) ); |
| // set elementary truth tables |
| for ( k = 0; k < CUT_CELL_MVAR; k++ ) |
| for ( i = 0; i < (1<<CUT_CELL_MVAR); i++ ) |
| if ( i & (1 << k) ) |
| p->uInputs[k][i>>5] |= (1 << (i&31)); |
| s_pCMan = p; |
| return p; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cut_CManStop( Cut_CMan_t * p ) |
| { |
| st__free_table( p->tTable ); |
| Extra_MmFixedStop( p->pMem ); |
| ABC_FREE( p ); |
| } |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Cut_CellIsRunning() |
| { |
| return s_pCMan != NULL; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Cut_CellDumpToFile() |
| { |
| FILE * pFile; |
| Cut_CMan_t * p = s_pCMan; |
| Cut_Cell_t * pTemp; |
| char * pFileName = "celllib22.txt"; |
| int NumUsed[10][5] = {{0}}; |
| int BoxUsed[22][5] = {{0}}; |
| int i, k, Counter; |
| abctime clk = Abc_Clock(); |
| |
| if ( p == NULL ) |
| { |
| printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" ); |
| return; |
| } |
| |
| // count the number of cells used |
| for ( k = CUT_CELL_MVAR; k >= 0; k-- ) |
| { |
| for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) |
| { |
| if ( pTemp->nUsed == 0 ) |
| NumUsed[k][0]++; |
| else if ( pTemp->nUsed < 10 ) |
| NumUsed[k][1]++; |
| else if ( pTemp->nUsed < 100 ) |
| NumUsed[k][2]++; |
| else if ( pTemp->nUsed < 1000 ) |
| NumUsed[k][3]++; |
| else |
| NumUsed[k][4]++; |
| |
| for ( i = 0; i < 4; i++ ) |
| if ( pTemp->nUsed == 0 ) |
| BoxUsed[ (int)pTemp->Box[i] ][0]++; |
| else if ( pTemp->nUsed < 10 ) |
| BoxUsed[ (int)pTemp->Box[i] ][1]++; |
| else if ( pTemp->nUsed < 100 ) |
| BoxUsed[ (int)pTemp->Box[i] ][2]++; |
| else if ( pTemp->nUsed < 1000 ) |
| BoxUsed[ (int)pTemp->Box[i] ][3]++; |
| else |
| BoxUsed[ (int)pTemp->Box[i] ][4]++; |
| } |
| } |
| |
| printf( "Functions found = %10d. Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound ); |
| for ( k = 0; k <= CUT_CELL_MVAR; k++ ) |
| { |
| printf( "%3d : ", k ); |
| for ( i = 0; i < 5; i++ ) |
| printf( "%8d ", NumUsed[k][i] ); |
| printf( "\n" ); |
| } |
| printf( "Box usage:\n" ); |
| for ( k = 0; k < 22; k++ ) |
| { |
| printf( "%3d : ", k ); |
| for ( i = 0; i < 5; i++ ) |
| printf( "%8d ", BoxUsed[k][i] ); |
| printf( " %s", s_NP3Names[k] ); |
| printf( "\n" ); |
| } |
| |
| pFile = fopen( pFileName, "w" ); |
| if ( pFile == NULL ) |
| { |
| printf( "Cut_CellDumpToFile: Cannout open output file.\n" ); |
| return; |
| } |
| |
| Counter = 0; |
| for ( k = 0; k <= CUT_CELL_MVAR; k++ ) |
| { |
| for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) |
| if ( pTemp->nUsed > 0 ) |
| { |
| Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) ); |
| fprintf( pFile, "\n" ); |
| Counter++; |
| } |
| fprintf( pFile, "\n" ); |
| } |
| fclose( pFile ); |
| |
| printf( "Library composed of %d functions is written into file \"%s\". ", Counter, pFileName ); |
| |
| ABC_PRT( "Time", Abc_Clock() - clk ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Looks up if the given function exists in the hash table.] |
| |
| Description [If the function exists, returns 1, meaning that it can be |
| implemented using two levels of 3-input LUTs. If the function does not |
| exist, return 0.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Cut_CellTruthLookup( unsigned * pTruth, int nVars ) |
| { |
| Cut_CMan_t * p = s_pCMan; |
| Cut_Cell_t * pTemp; |
| Cut_Cell_t Cell, * pCell = &Cell; |
| unsigned Hash; |
| int i; |
| |
| // cell manager is not defined |
| if ( p == NULL ) |
| { |
| printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" ); |
| return 0; |
| } |
| |
| // canonicize |
| memset( pCell, 0, sizeof(Cut_Cell_t) ); |
| pCell->nVars = nVars; |
| Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); |
| Cut_CellSuppMin( pCell ); |
| // set the elementary permutation |
| for ( i = 0; i < (int)pCell->nVars; i++ ) |
| pCell->CanonPerm[i] = i; |
| // canonicize |
| pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); |
| |
| |
| // check if the cell exists |
| Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) ); |
| if ( st__lookup( p->tTable, (char *)(ABC_PTRUINT_T)Hash, (char **)&pTemp ) ) |
| { |
| for ( ; pTemp; pTemp = pTemp->pNext ) |
| { |
| if ( pTemp->nVars != pCell->nVars ) |
| continue; |
| if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) |
| { |
| pTemp->nUsed++; |
| p->nCellFound++; |
| return 1; |
| } |
| } |
| } |
| p->nCellNotFound++; |
| return 0; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |