/**CFile****************************************************************

  FileName    [reoUnits.c]

  PackageName [REO: A specialized DD reordering engine.]

  Synopsis    [Procedures which support internal data structures.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - October 15, 2002.]

  Revision    [$Id: reoUnits.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $]

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

#include "reo.h"

////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

static void reoUnitsAddToFreeUnitList( reo_man * p );

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

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

  Synopsis    [Extract the next unit from the free unit list.]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
reo_unit * reoUnitsGetNextUnit(reo_man * p )
{
	reo_unit * pUnit;
	// check there are stil units to extract
	if ( p->pUnitFreeList == NULL )
		reoUnitsAddToFreeUnitList( p );
	// extract the next unit from the linked list
	pUnit            = p->pUnitFreeList;
	p->pUnitFreeList = pUnit->Next;
	p->nUnitsUsed++;
	return pUnit;
}

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

  Synopsis    [Returns the unit to the free unit list.]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit )
{
	pUnit->Next      = p->pUnitFreeList;
	p->pUnitFreeList = pUnit;
	p->nUnitsUsed--;
}

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

  Synopsis    [Returns the list of units to the free unit list.]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane )
{
	reo_unit * pUnit;
	reo_unit * pTail;

	if ( pPlane->pHead == NULL )
		return;

	// find the tail
	for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next )
		pTail = pUnit;
	pTail->Next = p->pUnitFreeList;
	p->pUnitFreeList    = pPlane->pHead;
	memset( pPlane, 0, sizeof(reo_plane) );
}

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

  Synopsis    [Stops the unit dispenser.]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
void reoUnitsStopDispenser( reo_man * p )
{
	int i;
	for ( i = 0; i < p->nMemChunks; i++ )
		free( p->pMemChunks[i] );
//	fprintf(outStream, "\nThe number of chunks used is %d, each of them %d units\n", p->nMemChunks, REO_CHUNK_SIZE );
	p->nMemChunks = 0;
}

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

  Synopsis    [Adds one unit to the list of units which constitutes the plane.]

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit )
{
	if ( pPlane->pHead == NULL )
	{
		pPlane->pHead = pUnit;
		pUnit->Next   = NULL;
	}
	else
	{
		pUnit->Next   = pPlane->pHead;
		pPlane->pHead = pUnit;
	}
	pPlane->statsNodes++;
}


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

  Synopsis    []

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
void reoUnitsAddToFreeUnitList( reo_man * p )
{
	int c;
	// check that we still have chunks left
	if ( p->nMemChunks == p->nMemChunksAlloc )
	{
		fprintf(outStream,  "reoUnitsAddToFreeUnitList(): Memory manager ran out of memory!\n" );
		fflush( outStream );
		return;
	}
	// allocate the next chunk
	assert( p->pUnitFreeList == NULL );
	p->pUnitFreeList = ALLOC( reo_unit, REO_CHUNK_SIZE );
	// split chunks into list-connected units
	for ( c = 0; c < REO_CHUNK_SIZE-1; c++ )
		(p->pUnitFreeList + c)->Next = p->pUnitFreeList + c + 1;
	// set the last pointer to NULL
	(p->pUnitFreeList + REO_CHUNK_SIZE-1)->Next = NULL;
	// add the chunk to the array of chunks
	p->pMemChunks[p->nMemChunks++] = p->pUnitFreeList;
}


////////////////////////////////////////////////////////////////////////
///                         END OF FILE                              ///
////////////////////////////////////////////////////////////////////////

