mem.c 17 KB
Newer Older
Alan Mishchenko committed
1 2
/**CFile****************************************************************

Alan Mishchenko committed
3
  FileName    [esopMem.c]
Alan Mishchenko committed
4 5 6

  SystemName  [ABC: Logic synthesis and verification system.]

Alan Mishchenko committed
7
  PackageName [Cover manipulation package.]
Alan Mishchenko committed
8 9 10 11 12 13 14

  Synopsis    [Memory managers.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

Alan Mishchenko committed
15
  Date        [Ver. 1.0. Started - June 20, 2005.]
Alan Mishchenko committed
16

Alan Mishchenko committed
17
  Revision    [$Id: esopMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
Alan Mishchenko committed
18 19 20

***********************************************************************/

Alan Mishchenko committed
21 22 23 24
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
25

Alan Mishchenko committed
26
#include "mem.h"
Alan Mishchenko committed
27

28 29 30
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
31 32 33 34
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

Alan Mishchenko committed
35
struct Mem_Fixed_t_
Alan Mishchenko committed
36 37 38 39 40 41
{
    // information about individual entries
    int           nEntrySize;    // the size of one entry
    int           nEntriesAlloc; // the total number of entries allocated
    int           nEntriesUsed;  // the number of entries in use
    int           nEntriesMax;   // the max number of entries in use
42
    char *        pEntriesFree;  // the linked list of free entries
Alan Mishchenko committed
43 44 45 46 47 48 49 50 51 52 53 54

    // this is where the memory is stored
    int           nChunkSize;    // the size of one chunk
    int           nChunksAlloc;  // the maximum number of memory chunks 
    int           nChunks;       // the current number of memory chunks 
    char **       pChunks;       // the allocated memory

    // statistics
    int           nMemoryUsed;   // memory used in the allocated entries
    int           nMemoryAlloc;  // memory allocated
};

Alan Mishchenko committed
55
struct Mem_Flex_t_
Alan Mishchenko committed
56 57 58
{
    // information about individual entries
    int           nEntriesUsed;  // the number of entries allocated
59 60
    char *        pCurrent;      // the current pointer to free memory
    char *        pEnd;          // the first entry outside the free memory
Alan Mishchenko committed
61 62 63 64 65 66 67 68 69 70 71 72

    // this is where the memory is stored
    int           nChunkSize;    // the size of one chunk
    int           nChunksAlloc;  // the maximum number of memory chunks 
    int           nChunks;       // the current number of memory chunks 
    char **       pChunks;       // the allocated memory

    // statistics
    int           nMemoryUsed;   // memory used in the allocated entries
    int           nMemoryAlloc;  // memory allocated
};

Alan Mishchenko committed
73
struct Mem_Step_t_
Alan Mishchenko committed
74
{
75 76 77 78 79 80 81
    int             nMems;              // the number of fixed memory managers employed
    Mem_Fixed_t **  pMems;              // memory managers: 2^1 words, 2^2 words, etc
    int             nMapSize;           // the size of the memory array
    Mem_Fixed_t **  pMap;               // maps the number of bytes into its memory manager
    int             nLargeChunksAlloc;  // the maximum number of large memory chunks
    int             nLargeChunks;       // the current number of large memory chunks
    void **         pLargeChunks;       // the allocated large memory chunks
Alan Mishchenko committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
};

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Allocates memory pieces of fixed size.]

  Description [The size of the chunk is computed as the minimum of
  1024 entries and 64K. Can only work with entry size at least 4 byte long.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
100
Mem_Fixed_t * Mem_FixedStart( int nEntrySize )
Alan Mishchenko committed
101
{
Alan Mishchenko committed
102
    Mem_Fixed_t * p;
Alan Mishchenko committed
103

Alan Mishchenko committed
104
    p = ABC_ALLOC( Mem_Fixed_t, 1 );
Alan Mishchenko committed
105
    memset( p, 0, sizeof(Mem_Fixed_t) );
Alan Mishchenko committed
106 107 108 109 110 111

    p->nEntrySize    = nEntrySize;
    p->nEntriesAlloc = 0;
    p->nEntriesUsed  = 0;
    p->pEntriesFree  = NULL;

Alan Mishchenko committed
112 113 114 115
    if ( nEntrySize * (1 << 10) < (1<<16) )
        p->nChunkSize = (1 << 10);
    else
        p->nChunkSize = (1<<16) / nEntrySize;
Alan Mishchenko committed
116 117 118 119 120
    if ( p->nChunkSize < 8 )
        p->nChunkSize = 8;

    p->nChunksAlloc  = 64;
    p->nChunks       = 0;
Alan Mishchenko committed
121
    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
Alan Mishchenko committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

    p->nMemoryUsed   = 0;
    p->nMemoryAlloc  = 0;
    return p;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
139
void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose )
Alan Mishchenko committed
140 141 142 143 144 145 146 147 148 149 150 151
{
    int i;
    if ( p == NULL )
        return;
    if ( fVerbose )
    {
        printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n",
            p->nEntrySize, p->nChunkSize, p->nChunks );
        printf( "   Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n",
            p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc );
    }
    for ( i = 0; i < p->nChunks; i++ )
Alan Mishchenko committed
152 153 154
        ABC_FREE( p->pChunks[i] );
    ABC_FREE( p->pChunks );
    ABC_FREE( p );
Alan Mishchenko committed
155 156 157 158 159 160 161 162 163 164 165 166 167
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
168
char * Mem_FixedEntryFetch( Mem_Fixed_t * p )
Alan Mishchenko committed
169 170 171 172
{
    char * pTemp;
    int i;

173
    // check if there are still free entries
Alan Mishchenko committed
174 175 176 177 178 179
    if ( p->nEntriesUsed == p->nEntriesAlloc )
    { // need to allocate more entries
        assert( p->pEntriesFree == NULL );
        if ( p->nChunks == p->nChunksAlloc )
        {
            p->nChunksAlloc *= 2;
Alan Mishchenko committed
180
            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
Alan Mishchenko committed
181
        }
Alan Mishchenko committed
182
        p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize );
Alan Mishchenko committed
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
        p->nMemoryAlloc += p->nEntrySize * p->nChunkSize;
        // transform these entries into a linked list
        pTemp = p->pEntriesFree;
        for ( i = 1; i < p->nChunkSize; i++ )
        {
            *((char **)pTemp) = pTemp + p->nEntrySize;
            pTemp += p->nEntrySize;
        }
        // set the last link
        *((char **)pTemp) = NULL;
        // add the chunk to the chunk storage
        p->pChunks[ p->nChunks++ ] = p->pEntriesFree;
        // add to the number of entries allocated
        p->nEntriesAlloc += p->nChunkSize;
    }
    // incrememt the counter of used entries
    p->nEntriesUsed++;
    if ( p->nEntriesMax < p->nEntriesUsed )
        p->nEntriesMax = p->nEntriesUsed;
202
    // return the first entry in the free entry list
Alan Mishchenko committed
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
    pTemp = p->pEntriesFree;
    p->pEntriesFree = *((char **)pTemp);
    return pTemp;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
219
void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry )
Alan Mishchenko committed
220 221 222
{
    // decrement the counter of used entries
    p->nEntriesUsed--;
223
    // add the entry to the linked list of free entries
Alan Mishchenko committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    *((char **)pEntry) = p->pEntriesFree;
    p->pEntriesFree = pEntry;
}

/**Function*************************************************************

  Synopsis    []

  Description [Relocates all the memory except the first chunk.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
239
void Mem_FixedRestart( Mem_Fixed_t * p )
Alan Mishchenko committed
240 241 242
{
    int i;
    char * pTemp;
Alan Mishchenko committed
243

Alan Mishchenko committed
244 245
    // deallocate all chunks except the first one
    for ( i = 1; i < p->nChunks; i++ )
Alan Mishchenko committed
246
        ABC_FREE( p->pChunks[i] );
Alan Mishchenko committed
247 248 249 250 251 252 253 254 255 256
    p->nChunks = 1;
    // transform these entries into a linked list
    pTemp = p->pChunks[0];
    for ( i = 1; i < p->nChunkSize; i++ )
    {
        *((char **)pTemp) = pTemp + p->nEntrySize;
        pTemp += p->nEntrySize;
    }
    // set the last link
    *((char **)pTemp) = NULL;
257
    // set the free entry list
Alan Mishchenko committed
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
    p->pEntriesFree  = p->pChunks[0];
    // set the correct statistics
    p->nMemoryAlloc  = p->nEntrySize * p->nChunkSize;
    p->nMemoryUsed   = 0;
    p->nEntriesAlloc = p->nChunkSize;
    p->nEntriesUsed  = 0;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
277
int Mem_FixedReadMemUsage( Mem_Fixed_t * p )
Alan Mishchenko committed
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
{
    return p->nMemoryAlloc;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
293
int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p )
Alan Mishchenko committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
{
    return p->nEntriesMax;
}



/**Function*************************************************************

  Synopsis    [Allocates entries of flexible size.]

  Description [Can only work with entry size at least 4 byte long.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
311
Mem_Flex_t * Mem_FlexStart()
Alan Mishchenko committed
312
{
Alan Mishchenko committed
313
    Mem_Flex_t * p;
Alan Mishchenko committed
314

Alan Mishchenko committed
315
    p = ABC_ALLOC( Mem_Flex_t, 1 );
Alan Mishchenko committed
316
    memset( p, 0, sizeof(Mem_Flex_t) );
Alan Mishchenko committed
317 318 319 320 321

    p->nEntriesUsed  = 0;
    p->pCurrent      = NULL;
    p->pEnd          = NULL;

322
    p->nChunkSize    = (1 << 12);
Alan Mishchenko committed
323 324
    p->nChunksAlloc  = 64;
    p->nChunks       = 0;
Alan Mishchenko committed
325
    p->pChunks       = ABC_ALLOC( char *, p->nChunksAlloc );
Alan Mishchenko committed
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342

    p->nMemoryUsed   = 0;
    p->nMemoryAlloc  = 0;
    return p;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
343
void Mem_FlexStop( Mem_Flex_t * p, int fVerbose )
Alan Mishchenko committed
344 345 346 347 348 349 350 351 352 353 354 355
{
    int i;
    if ( p == NULL )
        return;
    if ( fVerbose )
    {
        printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n",
            p->nChunkSize, p->nChunks );
        printf( "   Entries used = %d. Memory used = %d. Memory alloc = %d.\n",
            p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc );
    }
    for ( i = 0; i < p->nChunks; i++ )
Alan Mishchenko committed
356 357 358
        ABC_FREE( p->pChunks[i] );
    ABC_FREE( p->pChunks );
    ABC_FREE( p );
Alan Mishchenko committed
359 360 361 362 363 364 365 366 367 368 369 370 371
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
372
char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes )
Alan Mishchenko committed
373 374
{
    char * pTemp;
375
    // check if there are still free entries
Alan Mishchenko committed
376 377 378 379 380
    if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd )
    { // need to allocate more entries
        if ( p->nChunks == p->nChunksAlloc )
        {
            p->nChunksAlloc *= 2;
Alan Mishchenko committed
381
            p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); 
Alan Mishchenko committed
382 383 384 385 386 387 388
        }
        if ( nBytes > p->nChunkSize )
        {
            // resize the chunk size if more memory is requested than it can give
            // (ideally, this should never happen)
            p->nChunkSize = 2 * nBytes;
        }
Alan Mishchenko committed
389
        p->pCurrent = ABC_ALLOC( char, p->nChunkSize );
Alan Mishchenko committed
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
        p->pEnd     = p->pCurrent + p->nChunkSize;
        p->nMemoryAlloc += p->nChunkSize;
        // add the chunk to the chunk storage
        p->pChunks[ p->nChunks++ ] = p->pCurrent;
    }
    assert( p->pCurrent + nBytes <= p->pEnd );
    // increment the counter of used entries
    p->nEntriesUsed++;
    // keep track of the memory used
    p->nMemoryUsed += nBytes;
    // return the next entry
    pTemp = p->pCurrent;
    p->pCurrent += nBytes;
    return pTemp;
}

/**Function*************************************************************

  Synopsis    []

  Description [Relocates all the memory except the first chunk.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
417
void Mem_FlexRestart( Mem_Flex_t * p )
Alan Mishchenko committed
418 419 420 421 422 423
{
    int i;
    if ( p->nChunks == 0 )
        return;
    // deallocate all chunks except the first one
    for ( i = 1; i < p->nChunks; i++ )
Alan Mishchenko committed
424
        ABC_FREE( p->pChunks[i] );
Alan Mishchenko committed
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
    p->nChunks  = 1;
    p->nMemoryAlloc = p->nChunkSize;
    // transform these entries into a linked list
    p->pCurrent = p->pChunks[0];
    p->pEnd     = p->pCurrent + p->nChunkSize;
    p->nEntriesUsed = 0;
    p->nMemoryUsed = 0;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
445
int Mem_FlexReadMemUsage( Mem_Flex_t * p )
Alan Mishchenko committed
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
{
    return p->nMemoryUsed;
}





/**Function*************************************************************

  Synopsis    [Starts the hierarchical memory manager.]

  Description [This manager can allocate entries of any size.
  Iternally they are mapped into the entries with the number of bytes
  equal to the power of 2. The smallest entry size is 8 bytes. The
  next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 
  8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc.
  The input parameters "nSteps" says how many fixed memory managers
  are employed internally. Calling this procedure with nSteps equal
  to 10 results in 10 hierarchically arranged internal memory managers, 
  which can allocate up to 4096 (1Kb) entries. Requests for larger 
Alan Mishchenko committed
467
  entries are handed over to malloc() and then ABC_FREE()ed.]
Alan Mishchenko committed
468 469 470 471 472 473
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
474
Mem_Step_t * Mem_StepStart( int nSteps )
Alan Mishchenko committed
475
{
Alan Mishchenko committed
476
    Mem_Step_t * p;
Alan Mishchenko committed
477
    int i, k;
Alan Mishchenko committed
478
    p = ABC_ALLOC( Mem_Step_t, 1 );
Alan Mishchenko committed
479
    memset( p, 0, sizeof(Mem_Step_t) );
Alan Mishchenko committed
480 481
    p->nMems = nSteps;
    // start the fixed memory managers
Alan Mishchenko committed
482
    p->pMems = ABC_ALLOC( Mem_Fixed_t *, p->nMems );
Alan Mishchenko committed
483
    for ( i = 0; i < p->nMems; i++ )
Alan Mishchenko committed
484
        p->pMems[i] = Mem_FixedStart( (8<<i) );
Alan Mishchenko committed
485 486
    // set up the mapping of the required memory size into the corresponding manager
    p->nMapSize = (4<<p->nMems);
Alan Mishchenko committed
487
    p->pMap = ABC_ALLOC( Mem_Fixed_t *, p->nMapSize+1 );
Alan Mishchenko committed
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
    p->pMap[0] = NULL;
    for ( k = 1; k <= 4; k++ )
        p->pMap[k] = p->pMems[0];
    for ( i = 0; i < p->nMems; i++ )
        for ( k = (4<<i)+1; k <= (8<<i); k++ )
            p->pMap[k] = p->pMems[i];
//for ( i = 1; i < 100; i ++ )
//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize );
    return p;
}

/**Function*************************************************************

  Synopsis    [Stops the memory manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
510
void Mem_StepStop( Mem_Step_t * p, int fVerbose )
Alan Mishchenko committed
511 512 513
{
    int i;
    for ( i = 0; i < p->nMems; i++ )
Alan Mishchenko committed
514
        Mem_FixedStop( p->pMems[i], fVerbose );
515 516 517 518 519 520
    if ( p->pLargeChunks ) 
    {
        for ( i = 0; i < p->nLargeChunks; i++ )
            ABC_FREE( p->pLargeChunks[i] );
        ABC_FREE( p->pLargeChunks );
    }
Alan Mishchenko committed
521 522 523
    ABC_FREE( p->pMems );
    ABC_FREE( p->pMap );
    ABC_FREE( p );
Alan Mishchenko committed
524 525 526 527 528 529 530 531 532 533 534 535 536
}

/**Function*************************************************************

  Synopsis    [Creates the entry.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
537
char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes )
Alan Mishchenko committed
538 539 540 541 542 543
{
    if ( nBytes == 0 )
        return NULL;
    if ( nBytes > p->nMapSize )
    {
//        printf( "Allocating %d bytes.\n", nBytes );
544
//        return ABC_ALLOC( char, nBytes );
Alan Mishchenko committed
545 546 547
        if ( p->nLargeChunks == p->nLargeChunksAlloc )
        {
            if ( p->nLargeChunksAlloc == 0 )
548
                p->nLargeChunksAlloc = 32;
Alan Mishchenko committed
549
            p->nLargeChunksAlloc *= 2;
550
            p->pLargeChunks = (void **)ABC_REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); 
Alan Mishchenko committed
551
        }
Alan Mishchenko committed
552
        p->pLargeChunks[ p->nLargeChunks++ ] = ABC_ALLOC( char, nBytes );
553
        return (char *)p->pLargeChunks[ p->nLargeChunks - 1 ];
Alan Mishchenko committed
554
    }
Alan Mishchenko committed
555
    return Mem_FixedEntryFetch( p->pMap[nBytes] );
Alan Mishchenko committed
556 557 558 559 560 561 562 563 564 565 566 567 568 569
}


/**Function*************************************************************

  Synopsis    [Recycles the entry.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
570
void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes )
Alan Mishchenko committed
571 572 573 574 575
{
    if ( nBytes == 0 )
        return;
    if ( nBytes > p->nMapSize )
    {
Alan Mishchenko committed
576
//        ABC_FREE( pEntry );
Alan Mishchenko committed
577 578
        return;
    }
Alan Mishchenko committed
579
    Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry );
Alan Mishchenko committed
580 581 582 583 584 585 586 587 588 589 590 591 592
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
593
int Mem_StepReadMemUsage( Mem_Step_t * p )
Alan Mishchenko committed
594 595 596 597 598 599 600 601 602 603
{
    int i, nMemTotal = 0;
    for ( i = 0; i < p->nMems; i++ )
        nMemTotal += p->pMems[i]->nMemoryAlloc;
    return nMemTotal;
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////
604 605
ABC_NAMESPACE_IMPL_END