mirror of https://github.com/YosysHQ/abc.git
750 lines
28 KiB
C
750 lines
28 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [exorLink.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Exclusive sum-of-product minimization.]
|
|
|
|
Synopsis [Cube iterators.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: exorLink.c,v 1.0 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// ///
|
|
/// Implementation of EXORCISM - 4 ///
|
|
/// An Exclusive Sum-of-Product Minimizer ///
|
|
/// ///
|
|
/// Alan Mishchenko <alanmi@ee.pdx.edu> ///
|
|
/// ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// ///
|
|
/// Generation of ExorLinked Cubes ///
|
|
/// ///
|
|
/// Ver. 1.0. Started - July 26, 2000. Last update - July 29, 2000 ///
|
|
/// Ver. 1.4. Started - Aug 10, 2000. Last update - Aug 12, 2000 ///
|
|
/// ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// This software was tested with the BDD package "CUDD", v.2.3.0 ///
|
|
/// by Fabio Somenzi ///
|
|
/// http://vlsi.colorado.edu/~fabio/ ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "exor.h"
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// MACRO DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#define LARGE_NUM 1000000
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// EXTERNAL FUNCTION DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTIONS OF THIS MODULE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
int ExorLinkCubeIteratorStart( Cube** pGroup, Cube* pC1, Cube* pC2, cubedist Dist );
|
|
// this function starts the Exor-Link iterator, which iterates
|
|
// through the cube groups starting from the group with min literals
|
|
// returns 1 on success, returns 0 if the cubes have wrong distance
|
|
|
|
int ExorLinkCubeIteratorNext( Cube** pGroup );
|
|
// give the next group in the decreasing order of sum of literals
|
|
// returns 1 on success, returns 0 if there are no more groups
|
|
|
|
int ExorLinkCubeIteratorPick( Cube** pGroup, int g );
|
|
// gives the group #g in the order in which the groups were given
|
|
// during iteration
|
|
// returns 1 on success, returns 0 if something g is too large
|
|
|
|
void ExorLinkCubeIteratorCleanUp( int fTakeLastGroup );
|
|
// removes the cubes from the store back into the list of free cubes
|
|
// if fTakeLastGroup is 0, removes all cubes
|
|
// if fTakeLastGroup is 1, does not store the last group
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// EXTERNAL VARIABLES ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// information about the cube cover before
|
|
extern cinfo g_CoverInfo;
|
|
// new IDs are assigned only when it is known that the cubes are useful
|
|
// this is done in ExorLinkCubeIteratorCleanUp();
|
|
|
|
// the head of the list of free cubes
|
|
extern Cube* g_CubesFree;
|
|
|
|
extern byte BitCount[];
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// EXORLINK INFO ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
const int s_ELMax = 4;
|
|
|
|
// ExorLink-2: there are 4 cubes, 2 literals each, combined into 2 groups
|
|
// ExorLink-3: there are 12 cubes, 3 literals each, combined into 6 groups
|
|
// ExorLink-4: there are 32 cubes, 4 literals each, combined into 24 groups
|
|
// ExorLink-5: there are 80 cubes, 5 literals each, combined into 120 groups
|
|
// Exorlink-n: there are n*2^(n-1) cubes, n literals each, combined into n! groups
|
|
const int s_ELnCubes[4] = { 4, 12, 32, 80 };
|
|
const int s_ELnGroups[4] = { 2, 6, 24, 120 };
|
|
|
|
// value sets of cubes X{a0}Y{b0}Z{c0}U{d0} and X{a1}Y{b1}Z{c1}U{d1}
|
|
// used to represent the ExorLink cube generation rules
|
|
enum { vs0, vs1, vsX };
|
|
// vs0 = 0, // the value set of the first cube
|
|
// vs1 = 1, // the value set of the second cube
|
|
// vsX = 2 // EXOR of the value sets of the first and second cubes
|
|
|
|
// representation of ExorLinked cubes
|
|
static int s_ELCubeRules[3][32][4] = {
|
|
{ // ExorLink-2 Cube Generating Rules
|
|
// | 0 | 1 | - sections
|
|
// |-------|
|
|
{vsX,vs0}, // cube 0 | | |
|
|
{vsX,vs1}, // cube 1 | | 0 |
|
|
{vs0,vsX}, // cube 2 | | |
|
|
{vs1,vsX} // cube 3 | 0 | |
|
|
},
|
|
{ // ExorLink-3 Cube Generating Rules
|
|
// | 0 | 1 | 2 | - sections
|
|
// |-----------|
|
|
{vsX,vs0,vs0}, // cube 0 | | | |
|
|
{vsX,vs0,vs1}, // cube 1 | | | 0 |
|
|
{vsX,vs1,vs0}, // cube 2 | | 0 | |
|
|
{vsX,vs1,vs1}, // cube 3 | | 1 | 1 |
|
|
|
|
{vs0,vsX,vs0}, // cube 4 | | | |
|
|
{vs0,vsX,vs1}, // cube 5 | | | 2 |
|
|
{vs1,vsX,vs0}, // cube 6 | 0 | | |
|
|
{vs1,vsX,vs1}, // cube 7 | 1 | | 3 |
|
|
|
|
{vs0,vs0,vsX}, // cube 8 | | | |
|
|
{vs0,vs1,vsX}, // cube 9 | | 2 | |
|
|
{vs1,vs0,vsX}, // cube 10 | 2 | | |
|
|
{vs1,vs1,vsX} // cube 11 | 3 | 3 | |
|
|
},
|
|
{ // ExorLink-4 Rules Generating Rules
|
|
// | 0 | 1 | 2 | 4 | - sections
|
|
// |---------------|
|
|
{vsX,vs0,vs0,vs0}, // cube 0 | | | | |
|
|
{vsX,vs0,vs0,vs1}, // cube 1 | | | | 0 |
|
|
{vsX,vs0,vs1,vs0}, // cube 2 | | | 0 | |
|
|
{vsX,vs0,vs1,vs1}, // cube 3 | | | 1 | 1 |
|
|
{vsX,vs1,vs0,vs0}, // cube 4 | | 0 | | |
|
|
{vsX,vs1,vs0,vs1}, // cube 5 | | 1 | | 2 |
|
|
{vsX,vs1,vs1,vs0}, // cube 6 | | 2 | 2 | |
|
|
{vsX,vs1,vs1,vs1}, // cube 7 | | 3 | 3 | 3 |
|
|
|
|
{vs0,vsX,vs0,vs0}, // cube 8 | | | | |
|
|
{vs0,vsX,vs0,vs1}, // cube 9 | | | | 4 |
|
|
{vs0,vsX,vs1,vs0}, // cube 10 | | | 4 | |
|
|
{vs0,vsX,vs1,vs1}, // cube 11 | | | 5 | 5 |
|
|
{vs1,vsX,vs0,vs0}, // cube 12 | 0 | | | |
|
|
{vs1,vsX,vs0,vs1}, // cube 13 | 1 | | | 6 |
|
|
{vs1,vsX,vs1,vs0}, // cube 14 | 2 | | 6 | |
|
|
{vs1,vsX,vs1,vs1}, // cube 15 | 3 | | 7 | 7 |
|
|
|
|
{vs0,vs0,vsX,vs0}, // cube 16 | | | | |
|
|
{vs0,vs0,vsX,vs1}, // cube 17 | | | | 8 |
|
|
{vs0,vs1,vsX,vs0}, // cube 18 | | 4 | | |
|
|
{vs0,vs1,vsX,vs1}, // cube 19 | | 5 | | 9 |
|
|
{vs1,vs0,vsX,vs0}, // cube 20 | 4 | | | |
|
|
{vs1,vs0,vsX,vs1}, // cube 21 | 5 | | | 10|
|
|
{vs1,vs1,vsX,vs0}, // cube 22 | 6 | 6 | | |
|
|
{vs1,vs1,vsX,vs1}, // cube 23 | 7 | 7 | | 11|
|
|
|
|
{vs0,vs0,vs0,vsX}, // cube 24 | | | | |
|
|
{vs0,vs0,vs1,vsX}, // cube 25 | | | 8 | |
|
|
{vs0,vs1,vs0,vsX}, // cube 26 | | 8 | | |
|
|
{vs0,vs1,vs1,vsX}, // cube 27 | | 9 | 9 | |
|
|
{vs1,vs0,vs0,vsX}, // cube 28 | 8 | | | |
|
|
{vs1,vs0,vs1,vsX}, // cube 29 | 9 | | 10| |
|
|
{vs1,vs1,vs0,vsX}, // cube 30 | 10| 10| | |
|
|
{vs1,vs1,vs1,vsX} // cube 31 | 11| 11| 11| |
|
|
}
|
|
};
|
|
|
|
// these cubes are combined into groups
|
|
static int s_ELGroupRules[3][24][4] = {
|
|
{ // ExorLink-2 Group Forming Rules
|
|
{0,3}, // group 0 - section 0
|
|
{2,1} // group 1 - section 1
|
|
},
|
|
{ // ExorLink-3 Group Forming Rules
|
|
{0,6,11}, // group 0 - section 0
|
|
{0,7,10}, // group 1
|
|
{4,2,11}, // group 2 - section 1
|
|
{4,3,9}, // group 3
|
|
{8,1,7}, // group 4 - section 2
|
|
{8,3,5} // group 5
|
|
},
|
|
{ // ExorLink-4 Group Forming Rules
|
|
// section 0: (0-12)(1-13)(2-14)(3-15)(4-20)(5-21)(6-22)(7-23)(8-28)(9-29)(10-30)(11-31)
|
|
{0,12,22,31}, // group 0 // {0,6,11}, // group 0 - section 0
|
|
{0,12,23,30}, // group 1 // {0,7,10}, // group 1
|
|
{0,20,14,31}, // group 2 // {4,2,11}, // group 2
|
|
{0,20,15,29}, // group 3 // {4,3,9}, // group 3
|
|
{0,28,13,23}, // group 4 // {8,1,7}, // group 4
|
|
{0,28,15,21}, // group 5 // {8,3,5} // group 5
|
|
// section 1: (0-4)(1-5)(2-6)(3-7)(4-18)(5-19)(6-22)(7-23)(8-26)(9-27)(10-30)(11-31)
|
|
{8,4,22,31}, // group 6
|
|
{8,4,23,30}, // group 7
|
|
{8,18,6,31}, // group 8
|
|
{8,18,7,27}, // group 9
|
|
{8,26,5,23}, // group 10
|
|
{8,26,7,19}, // group 11
|
|
// section 2: (0-2)(1-3)(2-6)(3-7)(4-10)(5-11)(6-14)(7-15)(8-25)(9-27)(10-29)(11-31)
|
|
{16,2,14,31}, // group 12
|
|
{16,2,15,29}, // group 13
|
|
{16,10,6,31}, // group 14
|
|
{16,10,7,27}, // group 15
|
|
{16,25,3,15}, // group 16
|
|
{16,25,7,11}, // group 17
|
|
// section 3: (0-1)(1-3)(2-5)(3-7)(4-9)(5-11)(6-13)(7-15)(8-17)(9-19)(10-21)(11-23)
|
|
{24,1,13,23}, // group 18
|
|
{24,1,15,21}, // group 19
|
|
{24,9, 5,23}, // group 20
|
|
{24,9, 7,19}, // group 21
|
|
{24,17,3,15}, // group 22
|
|
{24,17,7,11} // group 23
|
|
}
|
|
};
|
|
|
|
// it is assumed that if literals in the first cube, second cube
|
|
// and their EXOR are 0 or 1 (as opposed to -), they are written
|
|
// into a mask, which is used to count the number of literals in
|
|
// the cube groups cubes
|
|
//
|
|
// below is the set of masks selecting literals belonging
|
|
// to the given cube of the group
|
|
|
|
static drow s_CubeLitMasks[3][32] = {
|
|
{ // ExorLink-2 Literal Counting Masks
|
|
// v3 v2 v1 v0
|
|
// -xBA -xBA -xBA -xBA
|
|
// -------------------
|
|
0x14, // cube 0 <0000 0000 0001 0100> {vsX,vs0}
|
|
0x24, // cube 1 <0000 0000 0010 0100> {vsX,vs1}
|
|
0x41, // cube 2 <0000 0000 0100 0001> {vs0,vsX}
|
|
0x42, // cube 3 <0000 0000 0100 0010> {vs1,vsX}
|
|
},
|
|
{ // ExorLink-3 Literal Counting Masks
|
|
0x114, // cube 0 <0000 0001 0001 0100> {vsX,vs0,vs0}
|
|
0x214, // cube 1 <0000 0010 0001 0100> {vsX,vs0,vs1}
|
|
0x124, // cube 2 <0000 0001 0010 0100> {vsX,vs1,vs0}
|
|
0x224, // cube 3 <0000 0010 0010 0100> {vsX,vs1,vs1}
|
|
0x141, // cube 4 <0000 0001 0100 0001> {vs0,vsX,vs0}
|
|
0x241, // cube 5 <0000 0010 0100 0001> {vs0,vsX,vs1}
|
|
0x142, // cube 6 <0000 0001 0100 0010> {vs1,vsX,vs0}
|
|
0x242, // cube 7 <0000 0010 0100 0010> {vs1,vsX,vs1}
|
|
0x411, // cube 8 <0000 0100 0001 0001> {vs0,vs0,vsX}
|
|
0x421, // cube 9 <0000 0100 0010 0001> {vs0,vs1,vsX}
|
|
0x412, // cube 10 <0000 0100 0001 0010> {vs1,vs0,vsX}
|
|
0x422, // cube 11 <0000 0100 0010 0010> {vs1,vs1,vsX}
|
|
},
|
|
{ // ExorLink-4 Literal Counting Masks
|
|
0x1114, // cube 0 <0001 0001 0001 0100> {vsX,vs0,vs0,vs0}
|
|
0x2114, // cube 1 <0010 0001 0001 0100> {vsX,vs0,vs0,vs1}
|
|
0x1214, // cube 2 <0001 0010 0001 0100> {vsX,vs0,vs1,vs0}
|
|
0x2214, // cube 3 <0010 0010 0001 0100> {vsX,vs0,vs1,vs1}
|
|
0x1124, // cube 4 <0001 0001 0010 0100> {vsX,vs1,vs0,vs0}
|
|
0x2124, // cube 5 <0010 0001 0010 0100> {vsX,vs1,vs0,vs1}
|
|
0x1224, // cube 6 <0001 0010 0010 0100> {vsX,vs1,vs1,vs0}
|
|
0x2224, // cube 7 <0010 0010 0010 0100> {vsX,vs1,vs1,vs1}
|
|
0x1141, // cube 8 <0001 0001 0100 0001> {vs0,vsX,vs0,vs0}
|
|
0x2141, // cube 9 <0010 0001 0100 0001> {vs0,vsX,vs0,vs1}
|
|
0x1241, // cube 10 <0001 0010 0100 0001> {vs0,vsX,vs1,vs0}
|
|
0x2241, // cube 11 <0010 0010 0100 0001> {vs0,vsX,vs1,vs1}
|
|
0x1142, // cube 12 <0001 0001 0100 0010> {vs1,vsX,vs0,vs0}
|
|
0x2142, // cube 13 <0010 0001 0100 0010> {vs1,vsX,vs0,vs1}
|
|
0x1242, // cube 14 <0001 0010 0100 0010> {vs1,vsX,vs1,vs0}
|
|
0x2242, // cube 15 <0010 0010 0100 0010> {vs1,vsX,vs1,vs1}
|
|
0x1411, // cube 16 <0001 0100 0001 0001> {vs0,vs0,vsX,vs0}
|
|
0x2411, // cube 17 <0010 0100 0001 0001> {vs0,vs0,vsX,vs1}
|
|
0x1421, // cube 18 <0001 0100 0010 0001> {vs0,vs1,vsX,vs0}
|
|
0x2421, // cube 19 <0010 0100 0010 0001> {vs0,vs1,vsX,vs1}
|
|
0x1412, // cube 20 <0001 0100 0001 0010> {vs1,vs0,vsX,vs0}
|
|
0x2412, // cube 21 <0010 0100 0001 0010> {vs1,vs0,vsX,vs1}
|
|
0x1422, // cube 22 <0001 0100 0010 0010> {vs1,vs1,vsX,vs0}
|
|
0x2422, // cube 23 <0010 0100 0010 0010> {vs1,vs1,vsX,vs1}
|
|
0x4111, // cube 24 <0100 0001 0001 0001> {vs0,vs0,vs0,vsX}
|
|
0x4211, // cube 25 <0100 0010 0001 0001> {vs0,vs0,vs1,vsX}
|
|
0x4121, // cube 26 <0100 0001 0010 0001> {vs0,vs1,vs0,vsX}
|
|
0x4221, // cube 27 <0100 0010 0010 0001> {vs0,vs1,vs1,vsX}
|
|
0x4112, // cube 28 <0100 0001 0001 0010> {vs1,vs0,vs0,vsX}
|
|
0x4212, // cube 29 <0100 0010 0001 0010> {vs1,vs0,vs1,vsX}
|
|
0x4122, // cube 30 <0100 0001 0010 0010> {vs1,vs1,vs0,vsX}
|
|
0x4222, // cube 31 <0100 0010 0010 0010> {vs1,vs1,vs1,vsX}
|
|
}
|
|
};
|
|
|
|
static drow s_BitMasks[32] =
|
|
{
|
|
0x00000001,0x00000002,0x00000004,0x00000008,
|
|
0x00000010,0x00000020,0x00000040,0x00000080,
|
|
0x00000100,0x00000200,0x00000400,0x00000800,
|
|
0x00001000,0x00002000,0x00004000,0x00008000,
|
|
0x00010000,0x00020000,0x00040000,0x00080000,
|
|
0x00100000,0x00200000,0x00400000,0x00800000,
|
|
0x01000000,0x02000000,0x04000000,0x08000000,
|
|
0x10000000,0x20000000,0x40000000,0x80000000
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// STATIC VARIABLES ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// this flag is TRUE as long as the storage is allocated
|
|
static int fWorking;
|
|
|
|
// set these flags to have minimum literal groups generated first
|
|
static int fMinLitGroupsFirst[4] = { 0 /*dist2*/, 0 /*dist3*/, 0 /*dist4*/};
|
|
|
|
static int nDist;
|
|
static int nCubes;
|
|
static int nCubesInGroup;
|
|
static int nGroups;
|
|
static Cube *pCA, *pCB;
|
|
|
|
// storage for variable numbers that are different in the cubes
|
|
static int DiffVars[5];
|
|
static int* pDiffVars;
|
|
static int nDifferentVars;
|
|
|
|
// storage for the bits and words of different input variables
|
|
static int nDiffVarsIn;
|
|
static int DiffVarWords[5];
|
|
static int DiffVarBits[5];
|
|
|
|
// literal mask used to count the number of literals in the cubes
|
|
static drow MaskLiterals;
|
|
// the base for counting literals
|
|
static int StartingLiterals;
|
|
// the number of literals in each cube
|
|
static int CubeLiterals[32];
|
|
static int BitShift;
|
|
static int DiffVarValues[4][3];
|
|
static int Value;
|
|
|
|
// the sorted array of groups in the increasing order of costs
|
|
static int GroupCosts[32];
|
|
static int GroupCostBest;
|
|
static int GroupCostBestNum;
|
|
|
|
static int CubeNum;
|
|
static int NewZ;
|
|
static drow Temp;
|
|
|
|
// the cubes currently created
|
|
static Cube* ELCubes[32];
|
|
|
|
// the bit string with 1's corresponding to cubes in ELCubes[]
|
|
// that constitute the last group
|
|
static drow LastGroup;
|
|
|
|
static int GroupOrder[24];
|
|
static drow VisitedGroups;
|
|
static int nVisitedGroups;
|
|
|
|
//int RemainderBits = (nVars*2)%(sizeof(drow)*8);
|
|
//int TotalWords = (nVars*2)/(sizeof(drow)*8) + (RemainderBits > 0);
|
|
static drow DammyBitData[(MAXVARS*2)/(sizeof(drow)*8)+(MAXVARS*2)%(sizeof(drow)*8)];
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINTIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// IDEA! if we already used a cube to count distances and it did not improve
|
|
// there is no need to try it again with other group
|
|
// (this idea works only for ExorLink-2 and -3)
|
|
|
|
int ExorLinkCubeIteratorStart( Cube** pGroup, Cube* pC1, Cube* pC2, cubedist Dist )
|
|
// this function starts the Exor-Link iterator, which iterates
|
|
// through the cube groups starting from the group with min literals
|
|
// returns 1 on success, returns 0 if the cubes have wrong distance
|
|
{
|
|
int i, c;
|
|
|
|
// check that everything is okey
|
|
assert( pC1 != NULL );
|
|
assert( pC2 != NULL );
|
|
assert( !fWorking );
|
|
|
|
nDist = Dist;
|
|
nCubes = Dist + 2;
|
|
nCubesInGroup = s_ELnCubes[nDist];
|
|
nGroups = s_ELnGroups[Dist];
|
|
pCA = pC1;
|
|
pCB = pC2;
|
|
// find what variables are different in these two cubes
|
|
// FindDiffVars returns DiffVars[0] < 0, if the output is different
|
|
nDifferentVars = FindDiffVars( DiffVars, pCA, pCB );
|
|
if ( nCubes != nDifferentVars )
|
|
{
|
|
// cout << "ExorLinkCubeIterator(): Distance mismatch";
|
|
// cout << " nCubes = " << nCubes << " nDiffVars = " << nDifferentVars << endl;
|
|
fWorking = 0;
|
|
return 0;
|
|
}
|
|
|
|
// copy the input variable cube data into DammyBitData[]
|
|
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
|
|
DammyBitData[i] = pCA->pCubeDataIn[i];
|
|
|
|
// find the number of different input variables
|
|
nDiffVarsIn = ( DiffVars[0] >= 0 )? nCubes: nCubes-1;
|
|
// assign the pointer to the place where the number of diff input vars is stored
|
|
pDiffVars = ( DiffVars[0] >= 0 )? DiffVars: DiffVars+1;
|
|
// find the bit offsets and remove different variables
|
|
for ( i = 0; i < nDiffVarsIn; i++ )
|
|
{
|
|
DiffVarWords[i] = ((2*pDiffVars[i]) >> LOGBPI) ;
|
|
DiffVarBits[i] = ((2*pDiffVars[i]) & BPIMASK);
|
|
// clear this position
|
|
DammyBitData[ DiffVarWords[i] ] &= ~( 3 << DiffVarBits[i] );
|
|
}
|
|
|
|
// extract the values from the cubes and create the mask of literals
|
|
MaskLiterals = 0;
|
|
// initialize the base for literal counts
|
|
StartingLiterals = pCA->a;
|
|
for ( i = 0, BitShift = 0; i < nDiffVarsIn; i++, BitShift++ )
|
|
{
|
|
DiffVarValues[i][0] = ( pCA->pCubeDataIn[DiffVarWords[i]] >> DiffVarBits[i] ) & 3;
|
|
if ( DiffVarValues[i][0] != VAR_ABS )
|
|
{
|
|
MaskLiterals |= ( 1 << BitShift );
|
|
// update the base for literal counts
|
|
StartingLiterals--;
|
|
}
|
|
BitShift++;
|
|
|
|
DiffVarValues[i][1] = ( pCB->pCubeDataIn[DiffVarWords[i]] >> DiffVarBits[i] ) & 3;
|
|
if ( DiffVarValues[i][1] != VAR_ABS )
|
|
MaskLiterals |= ( 1 << BitShift );
|
|
BitShift++;
|
|
|
|
DiffVarValues[i][2] = DiffVarValues[i][0] ^ DiffVarValues[i][1];
|
|
if ( DiffVarValues[i][2] != VAR_ABS )
|
|
MaskLiterals |= ( 1 << BitShift );
|
|
BitShift++;
|
|
}
|
|
|
|
// count the number of additional literals in each cube of the group
|
|
for ( i = 0; i < nCubesInGroup; i++ )
|
|
CubeLiterals[i] = BitCount[ MaskLiterals & s_CubeLitMasks[Dist][i] ];
|
|
|
|
// compute the costs of all groups
|
|
for ( i = 0; i < nGroups; i++ )
|
|
// go over all cubes in the group
|
|
for ( GroupCosts[i] = 0, c = 0; c < nCubes; c++ )
|
|
GroupCosts[i] += CubeLiterals[ s_ELGroupRules[Dist][i][c] ];
|
|
|
|
// find the best cost group
|
|
if ( fMinLitGroupsFirst[Dist] )
|
|
{ // find the minimum cost group
|
|
GroupCostBest = LARGE_NUM;
|
|
for ( i = 0; i < nGroups; i++ )
|
|
if ( GroupCostBest > GroupCosts[i] )
|
|
{
|
|
GroupCostBest = GroupCosts[i];
|
|
GroupCostBestNum = i;
|
|
}
|
|
}
|
|
else
|
|
{ // find the maximum cost group
|
|
GroupCostBest = -1;
|
|
for ( i = 0; i < nGroups; i++ )
|
|
if ( GroupCostBest < GroupCosts[i] )
|
|
{
|
|
GroupCostBest = GroupCosts[i];
|
|
GroupCostBestNum = i;
|
|
}
|
|
}
|
|
|
|
// create the cubes with min number of literals needed for the group
|
|
LastGroup = 0;
|
|
for ( c = 0; c < nCubes; c++ )
|
|
{
|
|
CubeNum = s_ELGroupRules[Dist][GroupCostBestNum][c];
|
|
LastGroup |= s_BitMasks[CubeNum];
|
|
|
|
// bring a cube from the free cube list
|
|
ELCubes[CubeNum] = GetFreeCube();
|
|
|
|
// copy the input bit data into the cube
|
|
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
|
|
ELCubes[CubeNum]->pCubeDataIn[i] = DammyBitData[i];
|
|
|
|
// copy the output bit data into the cube
|
|
NewZ = 0;
|
|
if ( DiffVars[0] >= 0 ) // the output is not involved in ExorLink
|
|
{
|
|
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
|
|
ELCubes[CubeNum]->pCubeDataOut[i] = pCA->pCubeDataOut[i];
|
|
NewZ = pCA->z;
|
|
}
|
|
else // the output is involved
|
|
{ // determine where the output information comes from
|
|
Value = s_ELCubeRules[Dist][CubeNum][nDiffVarsIn];
|
|
if ( Value == vs0 )
|
|
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
|
|
{
|
|
Temp = pCA->pCubeDataOut[i];
|
|
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
|
|
NewZ += BIT_COUNT(Temp);
|
|
}
|
|
else if ( Value == vs1 )
|
|
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
|
|
{
|
|
Temp = pCB->pCubeDataOut[i];
|
|
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
|
|
NewZ += BIT_COUNT(Temp);
|
|
}
|
|
else if ( Value == vsX )
|
|
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
|
|
{
|
|
Temp = pCA->pCubeDataOut[i] ^ pCB->pCubeDataOut[i];
|
|
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
|
|
NewZ += BIT_COUNT(Temp);
|
|
}
|
|
}
|
|
|
|
// set the variables that should be there
|
|
for ( i = 0; i < nDiffVarsIn; i++ )
|
|
{
|
|
Value = DiffVarValues[i][ s_ELCubeRules[Dist][CubeNum][i] ];
|
|
ELCubes[CubeNum]->pCubeDataIn[ DiffVarWords[i] ] |= ( Value << DiffVarBits[i] );
|
|
}
|
|
|
|
// set the number of literals
|
|
ELCubes[CubeNum]->a = StartingLiterals + CubeLiterals[CubeNum];
|
|
ELCubes[CubeNum]->z = NewZ;
|
|
ELCubes[CubeNum]->q = ComputeQCostBits( ELCubes[CubeNum] );
|
|
|
|
// assign the ID
|
|
ELCubes[CubeNum]->ID = g_CoverInfo.cIDs++;
|
|
// skip through zero-ID
|
|
if ( g_CoverInfo.cIDs == 256 )
|
|
g_CoverInfo.cIDs = 1;
|
|
|
|
// prepare the return array
|
|
pGroup[c] = ELCubes[CubeNum];
|
|
}
|
|
|
|
// mark this group as visited
|
|
VisitedGroups |= s_BitMasks[ GroupCostBestNum ];
|
|
// set the first visited group number
|
|
GroupOrder[0] = GroupCostBestNum;
|
|
// increment the counter of visited groups
|
|
nVisitedGroups = 1;
|
|
fWorking = 1;
|
|
return 1;
|
|
}
|
|
|
|
int ExorLinkCubeIteratorNext( Cube** pGroup )
|
|
// give the next group in the decreasing order of sum of literals
|
|
// returns 1 on success, returns 0 if there are no more groups
|
|
{
|
|
int i, c;
|
|
|
|
// check that everything is okey
|
|
assert( fWorking );
|
|
|
|
if ( nVisitedGroups == nGroups )
|
|
// we have iterated through all groups
|
|
return 0;
|
|
|
|
// find the min/max cost group
|
|
if ( fMinLitGroupsFirst[nDist] )
|
|
// if ( nCubes == 4 )
|
|
{ // find the minimum cost
|
|
// go through all groups
|
|
GroupCostBest = LARGE_NUM;
|
|
for ( i = 0; i < nGroups; i++ )
|
|
if ( !(VisitedGroups & s_BitMasks[i]) && GroupCostBest > GroupCosts[i] )
|
|
{
|
|
GroupCostBest = GroupCosts[i];
|
|
GroupCostBestNum = i;
|
|
}
|
|
assert( GroupCostBest != LARGE_NUM );
|
|
}
|
|
else
|
|
{ // find the maximum cost
|
|
// go through all groups
|
|
GroupCostBest = -1;
|
|
for ( i = 0; i < nGroups; i++ )
|
|
if ( !(VisitedGroups & s_BitMasks[i]) && GroupCostBest < GroupCosts[i] )
|
|
{
|
|
GroupCostBest = GroupCosts[i];
|
|
GroupCostBestNum = i;
|
|
}
|
|
assert( GroupCostBest != -1 );
|
|
}
|
|
|
|
// create the cubes needed for the group, if they are not created already
|
|
LastGroup = 0;
|
|
for ( c = 0; c < nCubes; c++ )
|
|
{
|
|
CubeNum = s_ELGroupRules[nDist][GroupCostBestNum][c];
|
|
LastGroup |= s_BitMasks[CubeNum];
|
|
|
|
if ( ELCubes[CubeNum] == NULL ) // this cube does not exist
|
|
{
|
|
// bring a cube from the free cube list
|
|
ELCubes[CubeNum] = GetFreeCube();
|
|
|
|
// copy the input bit data into the cube
|
|
for ( i = 0; i < g_CoverInfo.nWordsIn; i++ )
|
|
ELCubes[CubeNum]->pCubeDataIn[i] = DammyBitData[i];
|
|
|
|
// copy the output bit data into the cube
|
|
NewZ = 0;
|
|
if ( DiffVars[0] >= 0 ) // the output is not involved in ExorLink
|
|
{
|
|
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
|
|
ELCubes[CubeNum]->pCubeDataOut[i] = pCA->pCubeDataOut[i];
|
|
NewZ = pCA->z;
|
|
}
|
|
else // the output is involved
|
|
{ // determine where the output information comes from
|
|
Value = s_ELCubeRules[nDist][CubeNum][nDiffVarsIn];
|
|
if ( Value == vs0 )
|
|
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
|
|
{
|
|
Temp = pCA->pCubeDataOut[i];
|
|
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
|
|
NewZ += BIT_COUNT(Temp);
|
|
}
|
|
else if ( Value == vs1 )
|
|
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
|
|
{
|
|
Temp = pCB->pCubeDataOut[i];
|
|
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
|
|
NewZ += BIT_COUNT(Temp);
|
|
}
|
|
else if ( Value == vsX )
|
|
for ( i = 0; i < g_CoverInfo.nWordsOut; i++ )
|
|
{
|
|
Temp = pCA->pCubeDataOut[i] ^ pCB->pCubeDataOut[i];
|
|
ELCubes[CubeNum]->pCubeDataOut[i] = Temp;
|
|
NewZ += BIT_COUNT(Temp);
|
|
}
|
|
}
|
|
|
|
// set the variables that should be there
|
|
for ( i = 0; i < nDiffVarsIn; i++ )
|
|
{
|
|
Value = DiffVarValues[i][ s_ELCubeRules[nDist][CubeNum][i] ];
|
|
ELCubes[CubeNum]->pCubeDataIn[ DiffVarWords[i] ] |= ( Value << DiffVarBits[i] );
|
|
}
|
|
|
|
// set the number of literals and output ones
|
|
ELCubes[CubeNum]->a = StartingLiterals + CubeLiterals[CubeNum];
|
|
ELCubes[CubeNum]->z = NewZ;
|
|
ELCubes[CubeNum]->q = ComputeQCostBits( ELCubes[CubeNum] );
|
|
assert( NewZ != 255 );
|
|
|
|
// assign the ID
|
|
ELCubes[CubeNum]->ID = g_CoverInfo.cIDs++;
|
|
// skip through zero-ID
|
|
if ( g_CoverInfo.cIDs == 256 )
|
|
g_CoverInfo.cIDs = 1;
|
|
|
|
}
|
|
// prepare the return array
|
|
pGroup[c] = ELCubes[CubeNum];
|
|
}
|
|
|
|
// mark this group as visited
|
|
VisitedGroups |= s_BitMasks[ GroupCostBestNum ];
|
|
// set the next visited group number and
|
|
// increment the counter of visited groups
|
|
GroupOrder[ nVisitedGroups++ ] = GroupCostBestNum;
|
|
return 1;
|
|
}
|
|
|
|
int ExorLinkCubeIteratorPick( Cube** pGroup, int g )
|
|
// gives the group #g in the order in which the groups were given
|
|
// during iteration
|
|
// returns 1 on success, returns 0 if something is wrong (g is too large)
|
|
{
|
|
int GroupNum, c;
|
|
|
|
assert( fWorking );
|
|
assert( g >= 0 && g < nGroups );
|
|
assert( VisitedGroups & s_BitMasks[g] );
|
|
|
|
GroupNum = GroupOrder[g];
|
|
// form the group
|
|
LastGroup = 0;
|
|
for ( c = 0; c < nCubes; c++ )
|
|
{
|
|
CubeNum = s_ELGroupRules[nDist][GroupNum][c];
|
|
|
|
// remember this group as the last one
|
|
LastGroup |= s_BitMasks[CubeNum];
|
|
|
|
assert( ELCubes[CubeNum] != NULL ); // this cube should exist
|
|
// prepare the return array
|
|
pGroup[c] = ELCubes[CubeNum];
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void ExorLinkCubeIteratorCleanUp( int fTakeLastGroup )
|
|
// removes the cubes from the store back into the list of free cubes
|
|
// if fTakeLastGroup is 0, removes all cubes
|
|
// if fTakeLastGroup is 1, does not store the last group
|
|
{
|
|
int c;
|
|
assert( fWorking );
|
|
|
|
// put cubes back
|
|
// set the cube pointers to zero
|
|
if ( fTakeLastGroup == 0 )
|
|
for ( c = 0; c < nCubesInGroup; c++ )
|
|
{
|
|
ELCubes[c]->fMark = 0;
|
|
AddToFreeCubes( ELCubes[c] );
|
|
ELCubes[c] = NULL;
|
|
}
|
|
else
|
|
for ( c = 0; c < nCubesInGroup; c++ )
|
|
if ( ELCubes[c] )
|
|
{
|
|
ELCubes[c]->fMark = 0;
|
|
if ( (LastGroup & s_BitMasks[c]) == 0 ) // does not belong to the last group
|
|
AddToFreeCubes( ELCubes[c] );
|
|
ELCubes[c] = NULL;
|
|
}
|
|
|
|
// set the cube groups to zero
|
|
VisitedGroups = 0;
|
|
// shut down the iterator
|
|
fWorking = 0;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//////////// End of File /////////////////
|
|
///////////////////////////////////////////////////////////////////
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|