blob: d2ed3b753af1fb95a6998af6b2a5ef2cb3e8dc91 [file] [log] [blame]
/**CFile****************************************************************
FileName [satMem.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [SAT solver.]
Synopsis [Memory management.]
Author [Alan Mishchenko <alanmi@eecs.berkeley.edu>]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - January 1, 2004.]
Revision [$Id: satMem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $]
***********************************************************************/
#ifndef ABC__sat__bsat__satMem_h
#define ABC__sat__bsat__satMem_h
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include "misc/util/abc_global.h"
ABC_NAMESPACE_HEADER_START
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
//#define LEARNT_MAX_START_DEFAULT 0
#define LEARNT_MAX_START_DEFAULT 10000
#define LEARNT_MAX_INCRE_DEFAULT 1000
#define LEARNT_MAX_RATIO_DEFAULT 50
////////////////////////////////////////////////////////////////////////
/// STRUCTURE DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
//=================================================================================================
// Clause datatype + minor functions:
typedef struct clause_t clause;
struct clause_t
{
unsigned lrn : 1;
unsigned mark : 1;
unsigned partA : 1;
unsigned lbd : 8;
unsigned size : 21;
lit lits[0];
};
// learned clauses have "hidden" literal (c->lits[c->size]) to store clause ID
// data-structure for logging entries
// memory is allocated in 2^nPageSize word-sized pages
// the first 'word' of each page are stores the word limit
// although clause memory pieces are aligned to 64-bit words
// the integer clause handles are in terms of 32-bit unsigneds
// allowing for the first bit to be used for labeling 2-lit clauses
typedef struct Sat_Mem_t_ Sat_Mem_t;
struct Sat_Mem_t_
{
int nEntries[2]; // entry count
int BookMarkH[2]; // bookmarks for handles
int BookMarkE[2]; // bookmarks for entries
int iPage[2]; // current memory page
int nPageSize; // page log size in terms of ints
unsigned uPageMask; // page mask
unsigned uLearnedMask; // learned mask
int nPagesAlloc; // page count allocated
int ** pPages; // page pointers
};
static inline int Sat_MemLimit( int * p ) { return p[0]; }
static inline int Sat_MemIncLimit( int * p, int nInts ) { return p[0] += nInts; }
static inline void Sat_MemWriteLimit( int * p, int nInts ) { p[0] = nInts; }
static inline int Sat_MemHandPage( Sat_Mem_t * p, cla h ) { return h >> p->nPageSize; }
static inline int Sat_MemHandShift( Sat_Mem_t * p, cla h ) { return h & p->uPageMask; }
static inline int Sat_MemIntSize( int size, int lrn ) { return (size + 2 + lrn) & ~01; }
static inline int Sat_MemClauseSize( clause * p ) { return Sat_MemIntSize(p->size, p->lrn); }
static inline int Sat_MemClauseSize2( clause * p ) { return Sat_MemIntSize(p->size, 1); }
//static inline clause * Sat_MemClause( Sat_Mem_t * p, int i, int k ) { assert(i <= p->iPage[i&1] && k <= Sat_MemLimit(p->pPages[i])); return (clause *)(p->pPages[i] + k ); }
static inline clause * Sat_MemClause( Sat_Mem_t * p, int i, int k ) { assert( k ); return (clause *)(p->pPages[i] + k); }
//static inline clause * Sat_MemClauseHand( Sat_Mem_t * p, cla h ) { assert(Sat_MemHandPage(p, h) <= p->iPage[(h & p->uLearnedMask) > 0]); assert(Sat_MemHandShift(p, h) >= 2 && Sat_MemHandShift(p, h) < (int)p->uLearnedMask); return Sat_MemClause( p, Sat_MemHandPage(p, h), Sat_MemHandShift(p, h) ); }
static inline clause * Sat_MemClauseHand( Sat_Mem_t * p, cla h ) { return h ? Sat_MemClause( p, Sat_MemHandPage(p, h), Sat_MemHandShift(p, h) ) : NULL; }
static inline int Sat_MemEntryNum( Sat_Mem_t * p, int lrn ) { return p->nEntries[lrn]; }
static inline cla Sat_MemHand( Sat_Mem_t * p, int i, int k ) { return (i << p->nPageSize) | k; }
static inline cla Sat_MemHandCurrent( Sat_Mem_t * p, int lrn ) { return (p->iPage[lrn] << p->nPageSize) | Sat_MemLimit( p->pPages[p->iPage[lrn]] ); }
static inline int Sat_MemClauseUsed( Sat_Mem_t * p, cla h ) { return h < p->BookMarkH[(h & p->uLearnedMask) > 0]; }
static inline double Sat_MemMemoryHand( Sat_Mem_t * p, cla h ) { return 1.0 * ((Sat_MemHandPage(p, h) + 2)/2 * (1 << (p->nPageSize+2)) + Sat_MemHandShift(p, h) * 4); }
static inline double Sat_MemMemoryUsed( Sat_Mem_t * p, int lrn ) { return Sat_MemMemoryHand( p, Sat_MemHandCurrent(p, lrn) ); }
static inline double Sat_MemMemoryAllUsed( Sat_Mem_t * p ) { return Sat_MemMemoryUsed( p, 0 ) + Sat_MemMemoryUsed( p, 1 ); }
static inline double Sat_MemMemoryAll( Sat_Mem_t * p ) { return 1.0 * (p->iPage[0] + p->iPage[1] + 2) * (1 << (p->nPageSize+2)); }
// p is memory storage
// c is clause pointer
// i is page number
// k is page offset
// print problem clauses NOT in proof mode
#define Sat_MemForEachClause( p, c, i, k ) \
for ( i = 0; i <= p->iPage[0]; i += 2 ) \
for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize(c) ) if ( i == 0 && k == 2 ) {} else
// print problem clauses in proof mode
#define Sat_MemForEachClause2( p, c, i, k ) \
for ( i = 0; i <= p->iPage[0]; i += 2 ) \
for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize2(c) ) if ( i == 0 && k == 2 ) {} else
#define Sat_MemForEachLearned( p, c, i, k ) \
for ( i = 1; i <= p->iPage[1]; i += 2 ) \
for ( k = 2; k < Sat_MemLimit(p->pPages[i]) && ((c) = Sat_MemClause( p, i, k )); k += Sat_MemClauseSize(c) )
////////////////////////////////////////////////////////////////////////
/// GLOBAL VARIABLES ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// MACRO DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
static inline int clause_from_lit( lit l ) { return l + l + 1; }
static inline int clause_is_lit( cla h ) { return (h & 1); }
static inline lit clause_read_lit( cla h ) { return (lit)(h >> 1); }
static inline int clause_learnt_h( Sat_Mem_t * p, cla h ) { return (h & p->uLearnedMask) > 0; }
static inline int clause_learnt( clause * c ) { return c->lrn; }
static inline int clause_id( clause * c ) { return c->lits[c->size]; }
static inline void clause_set_id( clause * c, int id ) { c->lits[c->size] = id; }
static inline int clause_size( clause * c ) { return c->size; }
static inline lit * clause_begin( clause * c ) { return c->lits; }
static inline lit * clause_end( clause * c ) { return c->lits + c->size; }
static inline void clause_print_( clause * c )
{
int i;
printf( "{ " );
for ( i = 0; i < clause_size(c); i++ )
printf( "%d ", (clause_begin(c)[i] & 1)? -(clause_begin(c)[i] >> 1) : clause_begin(c)[i] >> 1 );
printf( "}\n" );
}
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocating vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Sat_MemCountL( Sat_Mem_t * p )
{
clause * c;
int i, k, Count = 0;
Sat_MemForEachLearned( p, c, i, k )
Count++;
return Count;
}
/**Function*************************************************************
Synopsis [Allocating vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Sat_MemAlloc_( Sat_Mem_t * p, int nPageSize )
{
assert( nPageSize > 8 && nPageSize < 32 );
memset( p, 0, sizeof(Sat_Mem_t) );
p->nPageSize = nPageSize;
p->uLearnedMask = (unsigned)(1 << nPageSize);
p->uPageMask = (unsigned)((1 << nPageSize) - 1);
p->nPagesAlloc = 256;
p->pPages = ABC_CALLOC( int *, p->nPagesAlloc );
p->pPages[0] = ABC_ALLOC( int, (int)(((word)1) << p->nPageSize) );
p->pPages[1] = ABC_ALLOC( int, (int)(((word)1) << p->nPageSize) );
p->iPage[0] = 0;
p->iPage[1] = 1;
Sat_MemWriteLimit( p->pPages[0], 2 );
Sat_MemWriteLimit( p->pPages[1], 2 );
}
static inline Sat_Mem_t * Sat_MemAlloc( int nPageSize )
{
Sat_Mem_t * p;
p = ABC_CALLOC( Sat_Mem_t, 1 );
Sat_MemAlloc_( p, nPageSize );
return p;
}
/**Function*************************************************************
Synopsis [Resetting vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Sat_MemRestart( Sat_Mem_t * p )
{
p->nEntries[0] = 0;
p->nEntries[1] = 0;
p->iPage[0] = 0;
p->iPage[1] = 1;
Sat_MemWriteLimit( p->pPages[0], 2 );
Sat_MemWriteLimit( p->pPages[1], 2 );
}
/**Function*************************************************************
Synopsis [Sets the bookmark.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Sat_MemBookMark( Sat_Mem_t * p )
{
p->BookMarkE[0] = p->nEntries[0];
p->BookMarkE[1] = p->nEntries[1];
p->BookMarkH[0] = Sat_MemHandCurrent( p, 0 );
p->BookMarkH[1] = Sat_MemHandCurrent( p, 1 );
}
static inline void Sat_MemRollBack( Sat_Mem_t * p )
{
p->nEntries[0] = p->BookMarkE[0];
p->nEntries[1] = p->BookMarkE[1];
p->iPage[0] = Sat_MemHandPage( p, p->BookMarkH[0] );
p->iPage[1] = Sat_MemHandPage( p, p->BookMarkH[1] );
Sat_MemWriteLimit( p->pPages[p->iPage[0]], Sat_MemHandShift( p, p->BookMarkH[0] ) );
Sat_MemWriteLimit( p->pPages[p->iPage[1]], Sat_MemHandShift( p, p->BookMarkH[1] ) );
}
/**Function*************************************************************
Synopsis [Freeing vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Sat_MemFree_( Sat_Mem_t * p )
{
int i;
for ( i = 0; i < p->nPagesAlloc; i++ )
ABC_FREE( p->pPages[i] );
ABC_FREE( p->pPages );
}
static inline void Sat_MemFree( Sat_Mem_t * p )
{
Sat_MemFree_( p );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Creates new clause.]
Description [The resulting clause is fully initialized.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Sat_MemAppend( Sat_Mem_t * p, int * pArray, int nSize, int lrn, int fPlus1 )
{
clause * c;
int * pPage = p->pPages[p->iPage[lrn]];
int nInts = Sat_MemIntSize( nSize, lrn | fPlus1 );
assert( nInts + 3 < (1 << p->nPageSize) );
// need two extra at the begining of the page and one extra in the end
if ( Sat_MemLimit(pPage) + nInts + 2 >= (1 << p->nPageSize) )
{
p->iPage[lrn] += 2;
if ( p->iPage[lrn] >= p->nPagesAlloc )
{
p->pPages = ABC_REALLOC( int *, p->pPages, p->nPagesAlloc * 2 );
memset( p->pPages + p->nPagesAlloc, 0, sizeof(int *) * p->nPagesAlloc );
p->nPagesAlloc *= 2;
}
if ( p->pPages[p->iPage[lrn]] == NULL )
p->pPages[p->iPage[lrn]] = ABC_ALLOC( int, (int)(((word)1) << p->nPageSize) );
pPage = p->pPages[p->iPage[lrn]];
Sat_MemWriteLimit( pPage, 2 );
}
pPage[Sat_MemLimit(pPage)] = 0;
c = (clause *)(pPage + Sat_MemLimit(pPage));
c->size = nSize;
c->lrn = lrn;
if ( pArray )
memcpy( c->lits, pArray, sizeof(int) * nSize );
if ( lrn | fPlus1 )
c->lits[c->size] = p->nEntries[lrn];
p->nEntries[lrn]++;
Sat_MemIncLimit( pPage, nInts );
return Sat_MemHandCurrent(p, lrn) - nInts;
}
/**Function*************************************************************
Synopsis [Shrinking vector size.]
Description []
SideEffects [This procedure does not update the number of entries.]
SeeAlso []
***********************************************************************/
static inline void Sat_MemShrink( Sat_Mem_t * p, int h, int lrn )
{
assert( clause_learnt_h(p, h) == lrn );
assert( h && h <= Sat_MemHandCurrent(p, lrn) );
p->iPage[lrn] = Sat_MemHandPage(p, h);
Sat_MemWriteLimit( p->pPages[p->iPage[lrn]], Sat_MemHandShift(p, h) );
}
/**Function*************************************************************
Synopsis [Compacts learned clauses by removing marked entries.]
Description [Returns the number of remaining entries.]
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Sat_MemCompactLearned( Sat_Mem_t * p, int fDoMove )
{
clause * c, * cPivot = NULL;
int i, k, iNew = 1, kNew = 2, nInts, fStartLooking, Counter = 0;
int hLimit = Sat_MemHandCurrent(p, 1);
if ( hLimit == Sat_MemHand(p, 1, 2) )
return 0;
if ( fDoMove && p->BookMarkH[1] )
{
// move the pivot
assert( p->BookMarkH[1] >= Sat_MemHand(p, 1, 2) && p->BookMarkH[1] <= hLimit );
// get the pivot and remember it may be pointed offlimit
cPivot = Sat_MemClauseHand( p, p->BookMarkH[1] );
if ( p->BookMarkH[1] < hLimit && !cPivot->mark )
{
p->BookMarkH[1] = cPivot->lits[cPivot->size];
cPivot = NULL;
}
// else find the next used clause after cPivot
}
// iterate through the learned clauses
fStartLooking = 0;
Sat_MemForEachLearned( p, c, i, k )
{
assert( c->lrn );
// skip marked entry
if ( c->mark )
{
// if pivot is a marked clause, start looking for the next non-marked one
if ( cPivot && cPivot == c )
{
fStartLooking = 1;
cPivot = NULL;
}
continue;
}
// if we started looking before, we found it!
if ( fStartLooking )
{
fStartLooking = 0;
p->BookMarkH[1] = c->lits[c->size];
}
// compute entry size
nInts = Sat_MemClauseSize(c);
assert( !(nInts & 1) );
// check if we need to scroll to the next page
if ( kNew + nInts >= (1 << p->nPageSize) )
{
// set the limit of the current page
if ( fDoMove )
Sat_MemWriteLimit( p->pPages[iNew], kNew );
// move writing position to the new page
iNew += 2;
kNew = 2;
}
if ( fDoMove )
{
// make sure the result is the same as previous dry run
assert( c->lits[c->size] == Sat_MemHand(p, iNew, kNew) );
// only copy the clause if it has changed
if ( i != iNew || k != kNew )
{
memmove( p->pPages[iNew] + kNew, c, sizeof(int) * nInts );
// c = Sat_MemClause( p, iNew, kNew ); // assersions do not hold during dry run
c = (clause *)(p->pPages[iNew] + kNew);
assert( nInts == Sat_MemClauseSize(c) );
}
// set the new ID value
c->lits[c->size] = Counter;
}
else // remember the address of the clause in the new location
c->lits[c->size] = Sat_MemHand(p, iNew, kNew);
// update writing position
kNew += nInts;
assert( iNew <= i && kNew < (1 << p->nPageSize) );
// update counter
Counter++;
}
if ( fDoMove )
{
// update the counter
p->nEntries[1] = Counter;
// update the page count
p->iPage[1] = iNew;
// set the limit of the last page
Sat_MemWriteLimit( p->pPages[iNew], kNew );
// check if the pivot need to be updated
if ( p->BookMarkH[1] )
{
if ( cPivot )
{
p->BookMarkH[1] = Sat_MemHandCurrent(p, 1);
p->BookMarkE[1] = p->nEntries[1];
}
else
p->BookMarkE[1] = clause_id(Sat_MemClauseHand( p, p->BookMarkH[1] ));
}
}
return Counter;
}
ABC_NAMESPACE_HEADER_END
#endif
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////