mirror of https://github.com/YosysHQ/abc.git
446 lines
14 KiB
C
446 lines
14 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [vecMem.h]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Resizable arrays.]
|
|
|
|
Synopsis [Resizable array of memory pieces.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - July 20, 2012.]
|
|
|
|
Revision [$Id: vecMem.h,v 1.00 2012/07/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#ifndef ABC__misc__vec__vecMem_h
|
|
#define ABC__misc__vec__vecMem_h
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// INCLUDES ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <stdio.h>
|
|
|
|
ABC_NAMESPACE_HEADER_START
|
|
|
|
/*
|
|
This vector stores pieces of memory of the given size.
|
|
It is useful for representing truth tables and any other objects
|
|
of the fixed size. It is better that Extra_MmFixed because the
|
|
entry IDs can be used as handles to retrieve memory pieces without
|
|
the need for an array of pointers from entry IDs into memory pieces
|
|
(this can save 8(4) bytes per object on a 64(32)-bit platform).
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// PARAMETERS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// BASIC TYPES ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct Vec_Mem_t_ Vec_Mem_t;
|
|
struct Vec_Mem_t_
|
|
{
|
|
int nEntrySize; // entry size (in terms of 8-byte words)
|
|
int nEntries; // number of entries currently used
|
|
int LogPageSze; // log2 of page size (in terms of entries)
|
|
int PageMask; // page mask
|
|
int nPageAlloc; // number of pages currently allocated
|
|
int iPage; // the number of a page currently used
|
|
word ** ppPages; // memory pages
|
|
Vec_Int_t * vTable; // hash table
|
|
Vec_Int_t * vNexts; // next pointers
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// MACRO DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#define Vec_MemForEachEntry( p, pEntry, i ) \
|
|
for ( i = 0; (i < Vec_MemEntryNum(p)) && ((pEntry) = Vec_MemReadEntry(p, i)); i++ )
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Allocates a memory vector.]
|
|
|
|
Description [Entry size is in terms of 8-byte words. Page size is log2
|
|
of the number of entries on one page.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Vec_MemAlloc_( Vec_Mem_t * p, int nEntrySize, int LogPageSze )
|
|
{
|
|
memset( p, 0, sizeof(Vec_Mem_t) );
|
|
p->nEntrySize = nEntrySize;
|
|
p->LogPageSze = LogPageSze;
|
|
p->PageMask = (1 << p->LogPageSze) - 1;
|
|
p->iPage = -1;
|
|
}
|
|
static inline Vec_Mem_t * Vec_MemAlloc( int nEntrySize, int LogPageSze )
|
|
{
|
|
Vec_Mem_t * p;
|
|
p = ABC_CALLOC( Vec_Mem_t, 1 );
|
|
p->nEntrySize = nEntrySize;
|
|
p->LogPageSze = LogPageSze;
|
|
p->PageMask = (1 << p->LogPageSze) - 1;
|
|
p->iPage = -1;
|
|
return p;
|
|
}
|
|
static inline void Vec_MemFree( Vec_Mem_t * p )
|
|
{
|
|
int i;
|
|
for ( i = 0; i <= p->iPage; i++ )
|
|
ABC_FREE( p->ppPages[i] );
|
|
ABC_FREE( p->ppPages );
|
|
ABC_FREE( p );
|
|
}
|
|
static inline void Vec_MemFreeP( Vec_Mem_t ** p )
|
|
{
|
|
if ( *p == NULL )
|
|
return;
|
|
Vec_MemFree( *p );
|
|
*p = NULL;
|
|
}
|
|
static inline Vec_Mem_t * Vec_MemDup( Vec_Mem_t * pVec )
|
|
{
|
|
Vec_Mem_t * p = NULL;
|
|
return p;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Duplicates the integer array.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Vec_MemFill( Vec_Mem_t * pVec, int nEntries )
|
|
{
|
|
}
|
|
static inline void Vec_MemClean( Vec_Mem_t * pVec, int nEntries )
|
|
{
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline int Vec_MemEntrySize( Vec_Mem_t * p )
|
|
{
|
|
return p->nEntrySize;
|
|
}
|
|
static inline int Vec_MemEntryNum( Vec_Mem_t * p )
|
|
{
|
|
return p->nEntries;
|
|
}
|
|
static inline int Vec_MemPageSize( Vec_Mem_t * p )
|
|
{
|
|
return p->LogPageSze;
|
|
}
|
|
static inline int Vec_MemPageNum( Vec_Mem_t * p )
|
|
{
|
|
return p->iPage+1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline double Vec_MemMemory( Vec_Mem_t * p )
|
|
{
|
|
return (double)sizeof(word) * p->nEntrySize * (1 << p->LogPageSze) * (p->iPage + 1) + (double)sizeof(word *) * p->nPageAlloc + (double)sizeof(Vec_Mem_t);
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline word * Vec_MemReadEntry( Vec_Mem_t * p, int i )
|
|
{
|
|
assert( i >= 0 && i < p->nEntries );
|
|
return p->ppPages[i >> p->LogPageSze] + p->nEntrySize * (i & p->PageMask);
|
|
}
|
|
static inline word * Vec_MemReadEntryLast( Vec_Mem_t * p )
|
|
{
|
|
assert( p->nEntries > 0 );
|
|
return Vec_MemReadEntry( p, p->nEntries-1 );
|
|
}
|
|
static inline void Vec_MemWriteEntry( Vec_Mem_t * p, int i, word * pEntry )
|
|
{
|
|
word * pPlace = Vec_MemReadEntry( p, i );
|
|
memmove( pPlace, pEntry, sizeof(word) * p->nEntrySize );
|
|
}
|
|
static inline word * Vec_MemGetEntry( Vec_Mem_t * p, int i )
|
|
{
|
|
assert( i >= 0 );
|
|
if ( i >= p->nEntries )
|
|
{
|
|
int k, iPageNew = (i >> p->LogPageSze);
|
|
if ( p->iPage < iPageNew )
|
|
{
|
|
// realloc page pointers if needed
|
|
if ( iPageNew >= p->nPageAlloc )
|
|
p->ppPages = ABC_REALLOC( word *, p->ppPages, (p->nPageAlloc = p->nPageAlloc ? 2 * p->nPageAlloc : iPageNew + 32) );
|
|
// allocate new pages if needed
|
|
for ( k = p->iPage + 1; k <= iPageNew; k++ )
|
|
p->ppPages[k] = ABC_ALLOC( word, p->nEntrySize * (1 << p->LogPageSze) );
|
|
// update page counter
|
|
p->iPage = iPageNew;
|
|
}
|
|
// update entry counter
|
|
p->nEntries = i + 1;
|
|
}
|
|
return Vec_MemReadEntry( p, i );
|
|
}
|
|
static inline void Vec_MemSetEntry( Vec_Mem_t * p, int i, word * pEntry )
|
|
{
|
|
word * pPlace = Vec_MemGetEntry( p, i );
|
|
memmove( pPlace, pEntry, sizeof(word) * (size_t)p->nEntrySize );
|
|
}
|
|
static inline void Vec_MemPush( Vec_Mem_t * p, word * pEntry )
|
|
{
|
|
word * pPlace = Vec_MemGetEntry( p, p->nEntries );
|
|
memmove( pPlace, pEntry, sizeof(word) * (size_t)p->nEntrySize );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Vec_MemShrink( Vec_Mem_t * p, int nEntriesNew )
|
|
{
|
|
int i, iPageOld = p->iPage;
|
|
assert( nEntriesNew <= p->nEntries );
|
|
p->nEntries = nEntriesNew;
|
|
p->iPage = (nEntriesNew >> p->LogPageSze);
|
|
for ( i = p->iPage + 1; i <= iPageOld; i++ )
|
|
ABC_FREE( p->ppPages[i] );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Vec_MemDumpDigit( FILE * pFile, int HexDigit )
|
|
{
|
|
assert( HexDigit >= 0 && HexDigit < 16 );
|
|
if ( HexDigit < 10 )
|
|
fprintf( pFile, "%d", HexDigit );
|
|
else
|
|
fprintf( pFile, "%c", 'A' + HexDigit-10 );
|
|
}
|
|
static inline void Vec_MemDump( FILE * pFile, Vec_Mem_t * pVec )
|
|
{
|
|
word * pEntry;
|
|
int i, w, d;
|
|
if ( pFile == stdout )
|
|
printf( "Memory vector has %d entries: \n", Vec_MemEntryNum(pVec) );
|
|
Vec_MemForEachEntry( pVec, pEntry, i )
|
|
{
|
|
for ( w = pVec->nEntrySize - 1; w >= 0; w-- )
|
|
for ( d = 15; d >= 0; d-- )
|
|
Vec_MemDumpDigit( pFile, (int)(pEntry[w] >> (d<<2)) & 15 );
|
|
fprintf( pFile, "\n" );
|
|
}
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Hashing entries in the memory vector.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline void Vec_MemHashAlloc( Vec_Mem_t * p, int nTableSize )
|
|
{
|
|
assert( p->vTable == NULL && p->vNexts == NULL );
|
|
p->vTable = Vec_IntStartFull( Abc_PrimeCudd(nTableSize) );
|
|
p->vNexts = Vec_IntAlloc( nTableSize );
|
|
}
|
|
static inline void Vec_MemHashFree( Vec_Mem_t * p )
|
|
{
|
|
if ( p == NULL )
|
|
return;
|
|
Vec_IntFreeP( &p->vTable );
|
|
Vec_IntFreeP( &p->vNexts );
|
|
}
|
|
static inline unsigned Vec_MemHashKey( Vec_Mem_t * p, word * pEntry )
|
|
{
|
|
static int s_Primes[8] = { 1699, 4177, 5147, 5647, 6343, 7103, 7873, 8147 };
|
|
int i, nData = 2 * p->nEntrySize;
|
|
unsigned * pData = (unsigned *)pEntry;
|
|
unsigned uHash = 0;
|
|
for ( i = 0; i < nData; i++ )
|
|
uHash += pData[i] * s_Primes[i & 0x7];
|
|
return uHash % Vec_IntSize(p->vTable);
|
|
}
|
|
static int * Vec_MemHashLookup( Vec_Mem_t * p, word * pEntry )
|
|
{
|
|
int * pSpot = Vec_IntEntryP( p->vTable, Vec_MemHashKey(p, pEntry) );
|
|
for ( ; *pSpot != -1; pSpot = Vec_IntEntryP(p->vNexts, *pSpot) )
|
|
if ( !memcmp( Vec_MemReadEntry(p, *pSpot), pEntry, sizeof(word) * p->nEntrySize ) ) // equal
|
|
return pSpot;
|
|
return pSpot;
|
|
}
|
|
static void Vec_MemHashProfile( Vec_Mem_t * p )
|
|
{
|
|
int e;
|
|
for ( e = 0; e < 1000; e++ )
|
|
{
|
|
int Count = 0;
|
|
int * pSpot = Vec_IntEntryP( p->vTable, e );
|
|
for ( ; *pSpot != -1; pSpot = Vec_IntEntryP(p->vNexts, *pSpot) )
|
|
Count++;
|
|
printf( "%d ", Count );
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
static void Vec_MemHashResize( Vec_Mem_t * p )
|
|
{
|
|
word * pEntry;
|
|
int i, * pSpot;
|
|
//Vec_MemHashProfile( p );
|
|
Vec_IntFill( p->vTable, Abc_PrimeCudd(2 * Vec_IntSize(p->vTable)), -1 );
|
|
Vec_IntClear( p->vNexts );
|
|
Vec_MemForEachEntry( p, pEntry, i )
|
|
{
|
|
pSpot = Vec_MemHashLookup( p, pEntry );
|
|
assert( *pSpot == -1 );
|
|
*pSpot = Vec_IntSize(p->vNexts);
|
|
Vec_IntPush( p->vNexts, -1 );
|
|
}
|
|
assert( p->nEntries == Vec_IntSize(p->vNexts) );
|
|
}
|
|
static int Vec_MemHashInsert( Vec_Mem_t * p, word * pEntry )
|
|
{
|
|
int * pSpot;
|
|
if ( p->nEntries > Vec_IntSize(p->vTable) )
|
|
Vec_MemHashResize( p );
|
|
pSpot = Vec_MemHashLookup( p, pEntry );
|
|
if ( *pSpot != -1 )
|
|
return *pSpot;
|
|
*pSpot = Vec_IntSize(p->vNexts);
|
|
Vec_IntPush( p->vNexts, -1 );
|
|
Vec_MemPush( p, pEntry );
|
|
assert( p->nEntries == Vec_IntSize(p->vNexts) );
|
|
return Vec_IntSize(p->vNexts) - 1;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Allocates memory vector for storing truth tables.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
static inline Vec_Mem_t * Vec_MemAllocForTT( int nVars, int fCompl )
|
|
{
|
|
int Value, nWords = (nVars <= 6 ? 1 : (1 << (nVars - 6)));
|
|
word * uTruth = ABC_ALLOC( word, nWords );
|
|
Vec_Mem_t * vTtMem = Vec_MemAlloc( nWords, 12 );
|
|
Vec_MemHashAlloc( vTtMem, 10000 );
|
|
memset( uTruth, 0x00, sizeof(word) * nWords );
|
|
Value = Vec_MemHashInsert( vTtMem, uTruth ); assert( Value == 0 );
|
|
if ( fCompl )
|
|
memset( uTruth, 0x55, sizeof(word) * nWords );
|
|
else
|
|
memset( uTruth, 0xAA, sizeof(word) * nWords );
|
|
Value = Vec_MemHashInsert( vTtMem, uTruth ); assert( Value == 1 );
|
|
ABC_FREE( uTruth );
|
|
return vTtMem;
|
|
}
|
|
static inline void Vec_MemAddMuxTT( Vec_Mem_t * p, int nVars )
|
|
{
|
|
int Value, nWords = (nVars <= 6 ? 1 : (1 << (nVars - 6)));
|
|
word * uTruth = ABC_ALLOC( word, nWords );
|
|
memset( uTruth, 0xCA, sizeof(word) * nWords );
|
|
Value = Vec_MemHashInsert( p, uTruth ); assert( Value == 2 );
|
|
ABC_FREE( uTruth );
|
|
}
|
|
static inline void Vec_MemDumpTruthTables( Vec_Mem_t * p, char * pName, int nLutSize )
|
|
{
|
|
FILE * pFile;
|
|
char pFileName[1000];
|
|
sprintf( pFileName, "tt_%s_%02d.txt", pName ? pName : NULL, nLutSize );
|
|
pFile = pName ? fopen( pFileName, "wb" ) : stdout;
|
|
Vec_MemDump( pFile, p );
|
|
if ( pFile != stdout )
|
|
fclose( pFile );
|
|
printf( "Dumped %d %d-var truth tables into file \"%s\" (%.2f MB).\n",
|
|
Vec_MemEntryNum(p), nLutSize, pName ? pFileName : "stdout",
|
|
8.0 * Vec_MemEntryNum(p) * Vec_MemEntrySize(p) / (1 << 20) );
|
|
}
|
|
|
|
ABC_NAMESPACE_HEADER_END
|
|
|
|
#endif
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|