home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * ir.c
- *
- * By: John A. Schlack
- * Dates: October 1994 - November 1994
- *
- * Description:
- *
- * This module contains the functions that convert the prime implicants
- * to irredundant form.
- *
- *
- * Release Notes:
- *
- * 1.10 10/28/94 Created functions to reduce complete list of
- * prime implicants to irredundant form.
- * 1.20 11/29/94 Fixed bug that sometimes prevented program from
- * obtaining irredundant form (entered loop that did
- * not progress to solution).
- *
- ****************************************************************************/
-
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include "qmPrime.h"
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- typedef struct funcData
- {
- short function; // output decimal function
- short matchCount; // number of prime implicants with matching decimal functions
- short matchIndex; // index of first match
- } funcData;
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /* Prototypes */
-
- static short irStripUnused( irredundant * ir, funcData * function, short funcLen );
- static void deleteIrredundantElem( irredundant * ir, short removeElem );
- static void makeIrredundant( irredundant * ir, funcData * fd, short fdlen );
- static void irSearchData( irredundant * ir, funcData * funcInfo, short fdlen );
- static int searchCompare( const void * a1, const void * a2 );
- static short irReduce( irredundant * ir, funcData * funcInfo, short * fdlen );
- static void printIrredundant( irredundant * ir, short * function, short funcLen, short actualVars );
- static void dumpIR( irredundant * ir, char * loc );
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- short irredundantForm( irredundant * ir, short * function, short funcLen,
- short actualVars )
-
- Description:
- Call this function to reduce the full list of prime implicants
- to irredundant form.
-
- Input:
- "ir" is the list of prime implicants returned from the Quine-McClusky
- code in "decimal.c". The format of this structure is already
- set up for reduction.
- "function" is a sorted list of decimals that define the function.
- "funcLen" is the number of entries in "function".
- "actualVars" is the number of variables the user chose.
-
- Output:
- "ir" is the minimized form of prime implicants that define the function.
-
- Globals Modified:
- none
-
- Returns:
- 1 on success and 0 on failure.
- */
-
-
- short irredundantForm( irredundant * ir, short * function, short funcLen,
- short actualVars )
- {
- irElement * elem;
- funcData * funcInfo;
- short i;
-
- if ((funcLen <= 0) || (ir->len <= 0))
- return 0;
-
- // make sure all elements marked as not in input
- for (i=0, elem=ir->irArray; i<ir->len; i++, elem++)
- elem->inOutput = 0;
-
- // create data storage for reduction
- funcInfo = (funcData *) calloc( funcLen, sizeof( funcData ) );
- if (funcInfo == NULL)
- lowMemory();
- for (i=0; i<funcLen; i++)
- funcInfo[i].function = function[i];
-
- // remove prime implicants that don't have elements in output (due to don't care conditions)
- if (!irStripUnused( ir, funcInfo, funcLen ))
- {
- printf( "\n*** ERROR! Prime implicants do not match desired output. ***\n" );
- return 0;
- }
-
- // reduce prime implicants to irredundant form
- makeIrredundant( ir, funcInfo, funcLen );
-
- // free memory after reduction
- free( funcInfo );
-
- // print results
- printIrredundant( ir, function, funcLen, actualVars );
- return 1;
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- static short irStripUnused( irredundant * ir, funcData * function, short funcLen )
-
- Description:
- This function removes all prime implicants that are not present in the
- current output list. This is useful for large variable equations since
- it greatly reduces the overall processing. One will take a big performance
- hit for small functions, however.
-
- Input:
- "ir" is the list of prime implicants.
- "function" is a sorted list of decimals that define the function. This
- data must be sorted into ascending decimal order.
- "funcLen" is the number of entries in "function".
-
- Output:
- "ir" is a reduced list of primes. All those entries that do not contribute
- to the current set of outputs are deleted (except those marked as in
- the final output).
-
- Globals Modified:
- none
-
- Returns:
- Number of remaining primes implicants in the array. If this value is
- ever 0, we had an error.
- */
-
-
- static short irStripUnused( irredundant * ir, funcData * function, short funcLen )
- {
- irElement * elem;
- funcData pfunc;
- size_t size;
- short i, j, decEntries, match, oldSize;
-
- if (funcLen <= 0)
- paramError( "irStripUnused", 3 );
-
- #if DEBUG
- dumpIR( ir, "before irStripUnused()" );
- #endif
-
- oldSize = ir->len;
-
- /* search each prime implicant */
- elem = ir->irArray;
- for (i=0; i<ir->len; i++, elem++)
- {
- if (elem->inOutput)
- continue;
-
- /* check to see if it is composed of any desired output (i.e. more than just don't cares) */
- match = 0;
- decEntries = 1 << (elem->level - 1);
- for (j=0; (j<decEntries) && (!match); j++)
- {
- pfunc.function = (short) elem->decimal[j];
- if (bsearch( &pfunc, function, (size_t) funcLen, sizeof( funcData ),
- searchCompare ) != NULL)
- {
- match = 1;
- break;
- }
- }
-
- /* remove prime implicant - only composed of don't cares */
- if (!match)
- {
- /* free sub-element space */
- if (elem->decimal != NULL)
- free( elem->decimal );
- if (elem->difference != NULL)
- free( elem->difference );
-
- /* delete element */
- deleteIrredundantElem( ir, i );
- i--; /* update loop counter */
- }
- }
-
- /* re-allocate array size to free up some space */
- if (ir->len && (oldSize != ir->len))
- {
- size = ir->len * sizeof( irElement );
- ir->irArray = realloc( ir->irArray, size );
- if (ir->irArray == NULL)
- lowMemory();
- }
-
- #if DEBUG
- dumpIR( ir, "after irStripUnused()" );
- fprintf( fp, "\n****************************************************\n" );
- #endif
-
- return (ir->len);
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- static void deleteIrredundantElem( irredundant * ir, short removeElem )
- {
- irElement * elem;
- size_t size;
-
- elem = &(ir->irArray[removeElem]);
- (ir->len)--; // update array size
- size = (ir->len - removeElem) * sizeof( irElement );
- if (size > 0)
- memcpy( elem, elem + 1, size );
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- static void makeIrredundant( irredundant * ir, funcData * fd, short fdlen )
-
- Description:
- This function governs the actual process of reducing the primes to
- a non-redundant set. The function iterates through the primes,
- searching for the best prime (one that uniquely covers the most decimal
- outputs). When one is found, that decimal is marked as part of the output.
- The set of output decimals is reduced by the matches in the selected
- prime. In addition, all remaining primes that do not correspond to
- remaining outputs are deleted.
-
- Input:
- "ir" is the list of prime implicants.
- "fd" is a sorted list of decimals that define the function. This
- data must be sorted into ascending decimal order.
- "fdlen" is the number of entries in "function".
-
- Output:
- "ir" is a reduced list of primes. All those entries that do not contribute
- to the current set of outputs are deleted (except those marked as in
- the final output).
-
- Globals Modified:
- none
-
- Returns:
- none
- */
-
-
- static void makeIrredundant( irredundant * ir, funcData * fd, short fdlen )
- {
- short reduced, limitCount;
-
- limitCount = 0;
-
- // loop until all output is accounted (but be careful of infinite loops due to errors)
- while( fdlen && (limitCount++ < MAX_COMBOS) )
- {
- // update function info from remaining prime implicants
- irSearchData( ir, fd, fdlen );
-
- // locate required prime implicant and reduce remaining function data
- reduced = irReduce( ir, fd, &fdlen );
-
- // we must make progress each time through the loop
- if (!reduced)
- {
- printf( "\n*** ERROR! Reduction failed. ***\n" );
- break;
- }
- }
-
- if (limitCount >= MAX_COMBOS)
- printf( "\nERROR! Iterations did not sufficiently reduce primes.\n" );
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- static void irSearchData( irredundant * ir, funcData * funcInfo, short fdlen )
-
- Description:
- This function scans the primes for entries that match the remaining
- output functions. The number of matches is updated so that a "best"
- prime can be selected later.
-
- Input:
- "ir" is the list of prime implicants.
- "funcInfo" is a sorted list of decimals that define the function. This
- data must be sorted into ascending decimal order.
- "fdlen" is the number of entries in "function".
-
- Output:
- "ir" and "fd" are updated with data to select a best prime.
-
- Globals Modified:
- none
-
- Returns:
- none
- */
-
-
- static void irSearchData( irredundant * ir, funcData * funcInfo, short fdlen )
- {
- funcData * fd, pfunc;
- irElement * elem;
- short i, j, decCount;
-
- // zero old data
- for (i=0, fd=funcInfo; i<fdlen; i++, fd++)
- {
- fd->matchCount = 0;
- fd->matchIndex = -1;
- }
-
- // count number of prime implicants that match each output
- elem = ir->irArray;
- for (i=0; i<ir->len; i++, elem++)
- {
- elem->uniqueCount = 0;
- elem->amtInOutput = 0;
-
- // skip entries that are already part of final output
- if (elem->inOutput)
- continue;
-
- decCount = 1 << (elem->level - 1);
- for (j=0; j<decCount; j++)
- {
- pfunc.function = (short) elem->decimal[j];
- fd = bsearch( &pfunc, funcInfo, (size_t) fdlen, sizeof( funcData ),
- searchCompare );
- if (fd != NULL)
- {
- (elem->amtInOutput)++;
- (fd->matchCount)++;
- if (fd->matchIndex < 0)
- fd->matchIndex = i;
- }
- }
- }
-
- // update unique count of prime implicants */
- fd = funcInfo;
- elem = ir->irArray;
- for (i=0; i<fdlen; i++, fd++)
- if (fd->matchCount == 1)
- (elem[fd->matchIndex].uniqueCount)++;
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- static int searchCompare( const void * a1, const void * a2 )
- {
- short v1, v2;
-
- v1 = ((funcData *) a1)->function;
- v2 = ((funcData *) a2)->function;
- if (v1 < v2)
- return -1;
- if (v1 > v2)
- return 1;
- return 0;
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- static short irReduce( irredundant * ir, funcData * funcInfo, short * fdlen )
-
- Description:
- This function selects the best prime implicant, marks it as a member of
- the output, and reduces the entries in the output function list and
- prime implicant list.
-
- Input:
- "ir" is the list of prime implicants.
- "funcInfo" is a sorted list of decimals that define the function. This
- data must be sorted into ascending decimal order.
- "fdlen" is the number of entries in "function".
-
- Output:
- "ir" and "fd" are reduced after an output prime is selected.
-
- Globals Modified:
- none
-
- Returns:
- 1 if process was successful or 0 on error.
- */
-
-
- static short irReduce( irredundant * ir, funcData * funcInfo, short * fdlen )
- {
- unsigned char * p;
- funcData * fd, pdata;
- irElement * elem, * olde, * newe;
- size_t size, loc;
- short i, uniqueIndex, bestIndex, count;
-
- elem = ir->irArray;
-
- // locate any unique columns and track largest set
- fd = funcInfo;
- uniqueIndex = bestIndex = -1;
- for (i=0; i<(*fdlen); i++, fd++)
- {
- // we have unmatched output function - big error
- if (fd->matchCount == 0)
- return 0;
-
- // unique match
- else if (fd->matchCount == 1)
- {
- // if first unique column found, mark it
- if (uniqueIndex < 0)
- uniqueIndex = fd->matchIndex;
-
- // had previous unique column, take one with best output funcs
- else if (uniqueIndex != fd->matchIndex)
- {
- olde = &(elem[uniqueIndex]);
- newe = &(elem[fd->matchIndex]);
- if (newe->uniqueCount > olde->uniqueCount)
- uniqueIndex = fd->matchIndex;
- else if ((newe->uniqueCount == olde->uniqueCount) &&
- (newe->amtInOutput > olde->amtInOutput))
- uniqueIndex = fd->matchIndex;
- }
- }
- }
-
- // always choose to process best match
- if (uniqueIndex >= 0)
- bestIndex = uniqueIndex;
- else
- {
- // find prime implicant with most decimals in output
- bestIndex = 0;
- olde = ir->irArray;
- newe = olde + 1;
- for (i=1; i<(ir->len); i++, newe++)
- {
- if (newe->amtInOutput > olde->amtInOutput)
- {
- bestIndex = i;
- olde = newe;
- }
- }
-
- // verify that we have a valid prime
- if (olde->amtInOutput <= 0)
- printf( "\nERROR! Best match non-existant.\n" );
- }
-
- // mark unique column
- elem = &(ir->irArray[bestIndex]);
- elem->inOutput = 1;
-
- // remove entries from output that are "covered" by match
- count = 1 << (elem->level - 1);
- p = elem->decimal;
- for (i=0; i<count; i++, p++)
- {
- pdata.function = (short) *p;
- fd = bsearch( &pdata, funcInfo, (size_t) *fdlen, sizeof( funcData ),
- searchCompare );
- if (fd != NULL)
- {
- loc = fd - funcInfo; // pointer subtraction already reduces byte difference by element size
- (*fdlen)--;
- size = ((size_t) *fdlen - loc) * sizeof( funcData );
- if (size > 0)
- memcpy( funcInfo + loc, funcInfo + loc + 1, size );
- }
- }
-
- // compress prime implicants
- if (*fdlen > 0)
- irStripUnused( ir, funcInfo, *fdlen );
-
- // process went normally
- return 1;
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- static void printIrredundant( irredundant * ir, short * function, short funcLen, short actualVars )
- {
- irElement * elem;
- short i, cols;
-
- printf( "\n\n====================================================\n\n" );
-
- printf( "Desired Function:\n" );
- for (i=0, cols=0; i<funcLen; i++, cols++)
- {
- if (cols >= 16)
- {
- putc( '\n', stdout );
- cols = 0;
- }
- printf( "%3d ", function[i] );
- }
-
- printf( "\n\nIrredundant Form (x%d is MSB, x0 is LSB):\n\n", actualVars - 1 );
-
- elem = ir->irArray;
- for (i=0; i<ir->len; i++, elem++)
- {
- if (elem->inOutput)
- printEntry( elem->decimal, elem->difference, elem->level, actualVars, NULL );
- }
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- #if DEBUG
- static void dumpIR( irredundant * ir, char * loc )
- {
- irElement * elem;
- short i, j, count;
-
- fprintf( fp, "\n ---------------- Dump IR = %.40s ----------------\n", loc );
-
- elem = ir->irArray;
- for (i=0; i<ir->len; i++, elem++)
- {
- count = 1 << (elem->level - 1);
- for (j=0; j<count; j++)
- fprintf( fp, "%3d ", (short) (elem->decimal[j]) );
- if (elem->inOutput)
- fprintf( fp, " <output>" );
- fputc( '\n', fp );
- }
- }
- #endif
-