OpenFPGA/abc/src/starter.c

191 lines
5.7 KiB
C

/**CFile****************************************************************
FileName [starter.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Wrapper for calling ABC.]
Synopsis [A demo program illustrating parallel execution of ABC.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - October 22, 2009.]
Revision [$Id: starter.c,v 1.00 2009/10/22 00:00:00 alanmi Exp $]
***********************************************************************/
// To compile on Linux run: gcc -pthread -o starter starter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef WIN32
#include "pthread.h"
#else
#include <pthread.h>
#include <unistd.h>
#endif
// the max number of commands to execute from the input file
#define MAX_COMM_NUM 1000
// time printing
#define ABC_PRT(a,t) (printf("%s = ", (a)), printf("%7.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)))
// the number of currently running threads
static int nThreadsRunning = 0;
// mutext to control access to the number of threads
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// procedure for duplicating strings
char * Abc_UtilStrsav( char * s ) { return s ? strcpy(malloc(strlen(s)+1), s) : NULL; }
/**Function*************************************************************
Synopsis [This procedures executes one call to system().]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void * Abc_RunThread( void * Command )
{
// perform the call
if ( system( (char *)Command ) )
{
assert(pthread_mutex_lock(&mutex) == 0);
fprintf( stderr, "The following command has returned non-zero exit status:\n" );
fprintf( stderr, "\"%s\"\n", (char *)Command );
fprintf( stderr, "Sorry for the inconvenience.\n" );
fflush( stdout );
assert(pthread_mutex_unlock(&mutex) == 0);
}
// decrement the number of threads runining
assert(pthread_mutex_lock(&mutex) == 0);
nThreadsRunning--;
assert(pthread_mutex_unlock(&mutex) == 0);
// quit this thread
//printf("...Finishing %s\n", (char *)Command);
free( Command );
pthread_exit( NULL );
assert(0);
return NULL;
}
/**Function*************************************************************
Synopsis [Takes file with commands to be executed and the number of CPUs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int main( int argc, char * argv[] )
{
FILE * pFile, * pOutput = stdout;
pthread_t ThreadIds[MAX_COMM_NUM];
char * pBufferCopy, Buffer[MAX_COMM_NUM];
int i, nCPUs = 0, nLines = 0, Counter;
clock_t clk = clock();
// check command line arguments
if ( argc != 3 )
{ fprintf( stderr, "Wrong number of command line arguments.\n" ); goto usage; }
// get the number of CPUs
nCPUs = atoi( argv[1] );
if ( nCPUs <= 0 )
{ fprintf( pOutput, "Cannot read an integer represting the number of CPUs.\n" ); goto usage; }
// open the file and make sure it is available
pFile = fopen( argv[2], "r" );
if ( pFile == NULL )
{ fprintf( pOutput, "Input file \"%s\" cannot be opened.\n", argv[2] ); goto usage; }
// read commands and execute at most <num> of them at a time
// assert(mutex == PTHREAD_MUTEX_INITIALIZER);
while ( fgets( Buffer, MAX_COMM_NUM, pFile ) != NULL )
{
// get the command from the file
if ( Buffer[0] == '\n' || Buffer[0] == '\r' || Buffer[0] == '\t' ||
Buffer[0] == ' ' || Buffer[0] == '#')
{
continue;
}
if ( Buffer[strlen(Buffer)-1] == '\n' )
Buffer[strlen(Buffer)-1] = 0;
if ( Buffer[strlen(Buffer)-1] == '\r' )
Buffer[strlen(Buffer)-1] = 0;
// wait till there is an empty thread
while ( 1 )
{
assert(pthread_mutex_lock(&mutex) == 0);
Counter = nThreadsRunning;
assert(pthread_mutex_unlock(&mutex) == 0);
if ( Counter < nCPUs - 1 )
break;
// Sleep( 100 );
}
// increament the number of threads running
assert(pthread_mutex_lock(&mutex) == 0);
nThreadsRunning++;
printf( "Calling: %s\n", (char *)Buffer );
fflush( stdout );
assert(pthread_mutex_unlock(&mutex) == 0);
// create thread to execute this command
pBufferCopy = Abc_UtilStrsav( Buffer );
assert(pthread_create( &ThreadIds[nLines], NULL, Abc_RunThread, (void *)pBufferCopy ) == 0);
if ( ++nLines == MAX_COMM_NUM )
{ fprintf( pOutput, "Cannot execute more than %d commands from file \"%s\".\n", nLines, argv[2] ); break; }
}
// wait for all the threads to finish
while ( 1 )
{
assert(pthread_mutex_lock(&mutex) == 0);
Counter = nThreadsRunning;
assert(pthread_mutex_unlock(&mutex) == 0);
if ( Counter == 0 )
break;
}
// cleanup
assert(pthread_mutex_destroy(&mutex) == 0);
// assert(mutex == NULL);
fclose( pFile );
printf( "Finished processing commands in file \"%s\". ", argv[2] );
ABC_PRT( "Total time", clock() - clk );
return 0;
usage:
// skip the path name till the binary name
for ( i = strlen(argv[0]) - 1; i > 0; i-- )
if ( argv[0][i-1] == '\\' || argv[0][i-1] == '/' )
break;
// print usage message
fprintf( pOutput, "usage: %s <num> <file>\n", argv[0]+i );
fprintf( pOutput, " executes command listed in <file> in parallel on <num> CPUs\n" );
fprintf( pOutput, "\n" );
return 1;
}