comb.c File Reference

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include "codegen.h"
#include "comb.h"
#include "defines.h"
#include "db.h"
#include "exclude.h"
#include "expr.h"
#include "func_unit.h"
#include "link.h"
#include "obfuscate.h"
#include "ovl.h"
#include "util.h"
#include "vector.h"

Functions

static int combination_calc_depth (expression *exp, unsigned int curr_depth, bool left)
static bool combination_does_multi_exp_need_ul (expression *exp)
static void combination_multi_expr_calc (expression *exp, int *ulid, bool ul, bool excluded, unsigned int *hit, unsigned int *excludes, unsigned int *total)
static bool combination_is_expr_multi_node (expression *exp)
void combination_get_tree_stats (expression *exp, int *ulid, unsigned int curr_depth, bool excluded, unsigned int *hit, unsigned int *excludes, unsigned int *total)
 Calculates combination logic statistics for a single expression tree.
static void combination_reset_counted_exprs (func_unit *funit)
void combination_reset_counted_expr_tree (expression *exp)
 Resets combination counted bits in expression tree.
void combination_get_stats (func_unit *funit, unsigned int *hit, unsigned int *excluded, unsigned int *total)
 Calculates combination logic statistics for summary output.
void combination_get_funit_summary (func_unit *funit, unsigned int *hit, unsigned int *excluded, unsigned int *total)
 Gets combinational logic summary statistics for specified functional unit.
void combination_get_inst_summary (funit_inst *inst, unsigned int *hit, unsigned int *excluded, unsigned int *total)
 Gets combinational logic summary statistics for specified functional unit instance.
static bool combination_display_instance_summary (FILE *ofile, char *name, int hits, int total)
static bool combination_instance_summary (FILE *ofile, funit_inst *root, char *parent, int *hits, int *total)
static bool combination_display_funit_summary (FILE *ofile, const char *name, const char *fname, int hits, int total)
static bool combination_funit_summary (FILE *ofile, funit_link *head, int *hits, int *total)
static void combination_draw_line (char *line, int size, int exp_id)
static void combination_draw_centered_line (char *line, int size, int exp_id, bool left_bar, bool right_bar)
static void combination_parenthesize (bool parenthesis, const char *pre_code_format, char **new_code_format, unsigned int *code_format_size)
static void combination_underline_tree (expression *exp, unsigned int curr_depth, char ***lines, unsigned int *depth, unsigned int *size, exp_op_type parent_op, bool center, func_unit *funit)
static char * combination_prep_line (char *line, int start, int len)
static void combination_underline (FILE *ofile, char **code, unsigned int code_depth, expression *exp, func_unit *funit)
static void combination_unary (char ***info, int *info_size, expression *exp, bool show_excluded)
static void combination_event (char ***info, int *info_size, expression *exp, bool show_excluded)
static void combination_two_vars (char ***info, int *info_size, expression *exp, bool show_excluded)
static void combination_multi_var_exprs (char **line1, char **line2, char **line3, expression *exp)
static int combination_multi_expr_output_length (char *line1)
static void combination_multi_expr_output (char **info, char *line1, char *line2, char *line3)
static void combination_multi_vars (char ***info, int *info_size, expression *exp, bool show_excluded)
static void combination_get_missed_expr (char ***info, int *info_size, expression *exp, unsigned int curr_depth, bool show_excluded)
static void combination_list_missed (FILE *ofile, expression *exp, unsigned int curr_depth, func_unit *funit, bool show_exclusions)
static void combination_output_expr (expression *expr, unsigned int curr_depth, int *any_missed, int *any_measurable, int *any_excluded, int *all_excluded)
static void combination_display_verbose (FILE *ofile, func_unit *funit, rpt_type rtype)
static void combination_instance_verbose (FILE *ofile, funit_inst *root, char *parent)
static void combination_funit_verbose (FILE *ofile, funit_link *head)
void combination_collect (func_unit *funit, int cov, expression ***exprs, unsigned int *exp_cnt, int **excludes)
 Collects all toggle expressions that match the specified coverage indication.
static void combination_get_exclude_list (expression *exp, func_unit *funit, int **excludes, char ***reasons, unsigned int *exclude_size)
void combination_get_expression (int expr_id, char ***code, int **uline_groups, unsigned int *code_size, char ***ulines, unsigned int *uline_size, int **excludes, char ***reasons, unsigned int *exclude_size)
 Gets output for specified expression including underlines and code.
void combination_get_coverage (int exp_id, int uline_id, char ***info, int *info_size)
 Gets output for specified expression including coverage information.
void combination_report (FILE *ofile, bool verbose)
 Generates report output for combinational logic coverage.

Variables

db ** db_list
unsigned int curr_db
bool report_covered
unsigned int report_comb_depth
bool report_instance
bool report_bitwise
int line_width
char user_msg [USER_MSG_LENGTH]
const exp_info exp_op_info [EXP_OP_NUM]
isuppl info_suppl
bool report_exclusions
bool flag_output_exclusion_ids
bool allow_multi_expr = TRUE

Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
3/31/2002
The functions in this file are used by the report command to calculate and display all report output for combination logic coverage. Combinational logic coverage is calculated solely from the list of expression trees in the scored design. For each module or instance, the expression list is passed to the calculation routine which iterates through each expression tree, tallying the total number of expression values and the total number of expression values reached.
Every expression contains two possible expression values during simulation: 0 and 1. If an expression evaluated to some unknown value, this is not recorded by Covered. If an expression has evaluated to 0, the WAS_FALSE bit of the expression's supplemental field will be set. If the expression has evaluated to 1 or a value greater than 1, the WAS_TRUE bit of the expression's supplemental field will be set. If both the WAS_FALSE and the WAS_TRUE bits are set after scoring, the expression is considered to be fully covered.
If the expression is an event type, only the WAS_TRUE bit is examined. It it was set during simulation, the event is completely covered; otherwise, the event was not covered during simulation.
For combinational logic, four other expression supplemental bits are used to determine which logical combinations of its two children have occurred during simulation. These four bits are EVAL_A, EVAL_B, EVAL_C, and EVAL_D. If the left and right expressions simultaneously evaluated to 0 during simulation, the EVAL_00 bit is set. If the left and right expressions simultaneously evaluated to 0 and 1, respectively, the EVAL_01 bit is set. If the left and right expressions simultaneously evaluated to 1 and 0, respectively, the EVAL_10 bit is set. If the left and right expression simultaneously evaluated to 1 during simulation, the EVAL_11 bit is set. For an AND-type operation, full coverage is achieved if (EVAL_00 || EVAL_01) && (EVAL_00 || EVAL10) && EVAL_11. For an OR-type operation, full coverage is achieved if (EVAL_10 || EVAL_11) && (EVAL_01 || EVAL11) && EVAL_00. For any other combinational expression (where both the left and right expression trees are non-NULL), full coverage is achieved if all four EVAL_xx bits are set.

Function Documentation

static int combination_calc_depth ( expression exp,
unsigned int  curr_depth,
bool  left 
) [static]
Returns:
Returns new depth value for specified child expression.

Based on the current point in the expression tree, calculates the left or right child's curr_depth value.

Parameters:
exp Pointer to current expression
curr_depth Current depth in expression tree
left TRUE if evaluating for left child

References expression_s::left, expression_s::op, PROFILE, PROFILE_END, report_comb_depth, REPORT_DETAILED, REPORT_VERBOSE, and expression_s::right.

Referenced by combination_get_tree_stats(), combination_list_missed(), combination_output_expr(), and combination_underline_tree().

00111   { PROFILE(COMBINATION_CALC_DEPTH);
00112 
00113   int our_depth;  /* Return value for this function */
00114 
00115   if( ((report_comb_depth == REPORT_DETAILED) && ((curr_depth + 1) <= report_comb_depth)) ||
00116        (report_comb_depth == REPORT_VERBOSE) ) {
00117 
00118     if( left ) {
00119 
00120       if( (exp->left != NULL) && (exp->op == exp->left->op) ) {
00121         our_depth = curr_depth;
00122       } else {
00123         our_depth = curr_depth + 1;
00124       }
00125 
00126     } else {
00127 
00128       if( (exp->right != NULL) && (exp->op == exp->right->op) ) {
00129         our_depth = curr_depth;
00130       } else {
00131         our_depth = curr_depth + 1;
00132       }
00133 
00134     }
00135 
00136   } else {
00137 
00138     our_depth = curr_depth + 1;
00139 
00140   }
00141 
00142   PROFILE_END;
00143 
00144   return( our_depth );
00145 
00146 }

void combination_collect ( func_unit funit,
int  cov,
expression ***  exprs,
unsigned int *  exp_cnt,
int **  excludes 
)

Collects all toggle expressions that match the specified coverage indication.

Gathers the covered or uncovered combinational logic information, storing their expressions in the exprs expression arrays. Used by the GUI for verbose combinational logic output.

Parameters:
funit Pointer to functional unit
cov Specifies the coverage type to find
exprs Pointer to an array of expression pointers that contain all fully covered/uncovered expressions
exp_cnt Pointer to a value that will be set to indicate the number of expressions in covs array
excludes Pointer to an array of integers indicating exclusion property of each uncovered expression

References esuppl_u::comb_cntd, combination_output_expr(), combination_reset_counted_exprs(), statement_s::exp, FALSE, func_iter_dealloc(), func_iter_get_next_statement(), func_iter_init(), expression_s::line, esuppl_u::part, PROFILE, PROFILE_END, realloc_safe, expression_s::suppl, and TRUE.

02792   { PROFILE(COMBINATION_COLLECT);
02793 
02794   func_iter  fi;              /* Functional unit iterator */
02795   statement* stmt;            /* Pointer to current statement */
02796  
02797   /* Reset combination counted bits */
02798   combination_reset_counted_exprs( funit );
02799 
02800   /* Create an array that will hold the number of uncovered combinations */
02801   *exp_cnt  = 0;
02802   *exprs    = NULL;
02803   *excludes = NULL;
02804 
02805   func_iter_init( &fi, funit, TRUE, FALSE );
02806 
02807   stmt = func_iter_get_next_statement( &fi );
02808   while( stmt != NULL ) {
02809 
02810     int any_missed     = 0;
02811     int any_measurable = 0;
02812     int any_excluded   = 0;
02813     int all_excluded   = 0;
02814 
02815     combination_output_expr( stmt->exp, 0, &any_missed, &any_measurable, &any_excluded, &all_excluded );
02816 
02817     /* Check for uncovered statements */
02818     if( ((cov == 0) && (any_missed == 1)) ||
02819         ((cov == 1) && (any_missed == 0) && (any_measurable == 1)) ) {
02820       if( stmt->exp->line != 0 ) {
02821         *exprs    = (expression**)realloc_safe( *exprs,    (sizeof( expression* ) * (*exp_cnt)), (sizeof( expression* ) * (*exp_cnt + 1)) );
02822         *excludes =         (int*)realloc_safe( *excludes, (sizeof( int* )        * (*exp_cnt)), (sizeof( int* )        * (*exp_cnt + 1)) );
02823 
02824         (*exprs)[(*exp_cnt)]    = stmt->exp;
02825         (*excludes)[(*exp_cnt)] = all_excluded ? 1 : 0;
02826         (*exp_cnt)++;
02827       }
02828       stmt->exp->suppl.part.comb_cntd = 0;
02829     }
02830 
02831     stmt = func_iter_get_next_statement( &fi );
02832 
02833   }
02834 
02835   func_iter_dealloc( &fi );
02836 
02837   PROFILE_END;
02838 
02839 }

static bool combination_display_funit_summary ( FILE *  ofile,
const char *  name,
const char *  fname,
int  hits,
int  total 
) [static]
Returns:
Returns TRUE if at least one logic combination was found to not be hit; otherwise, returns FALSE.

Outputs the summary combinational logic information for the specified functional unit to the given output stream.

Parameters:
ofile Pointer to file to output functional unit summary information to
name Name of functional unit being reported
fname Filename that contains the functional unit being reported
hits Number of logic combinations that were hit during simulation
total Number of total logic combinations that exist in the given functional unit

References calc_miss_percent(), PROFILE, and PROFILE_END.

Referenced by combination_funit_summary(), and combination_report().

00701   { PROFILE(COMBINATION_DISPLAY_FUNIT_SUMMARY);
00702 
00703   float percent;  /* Percentage of lines hit */
00704   int   miss;     /* Number of lines missed */
00705 
00706   calc_miss_percent( hits, total, &miss, &percent );
00707 
00708   fprintf( ofile, "  %-30.30s    %-30.30s   %4d/%4d/%4d      %3.0f%%\n",
00709            name, fname, hits, miss, total, percent );
00710 
00711   PROFILE_END;
00712 
00713   return( miss > 0 );
00714 
00715 }

static bool combination_display_instance_summary ( FILE *  ofile,
char *  name,
int  hits,
int  total 
) [static]

Outputs the instance combinational logic summary information to the given output file.

Parameters:
ofile Pointer to file to output instance summary to
name Name of instance to display
hits Number of combinations hit in instance
total Total number of logic combinations in instance

References calc_miss_percent(), PROFILE, and PROFILE_END.

Referenced by combination_instance_summary(), and combination_report().

00605   { PROFILE(COMBINATION_DISPLAY_INSTANCE_SUMMARY);
00606 
00607   float percent;  /* Percentage of lines hit */
00608   int   miss;     /* Number of lines missed */
00609 
00610   calc_miss_percent( hits, total, &miss, &percent );
00611 
00612   fprintf( ofile, "  %-63.63s    %4d/%4d/%4d      %3.0f%%\n",
00613            name, hits, miss, total, percent );
00614 
00615   PROFILE_END;
00616 
00617   return( miss > 0 );
00618 
00619 }

static void combination_display_verbose ( FILE *  ofile,
func_unit funit,
rpt_type  rtype 
) [static]
Exceptions:
anonymous combination_underline

Displays the expressions (and groups of expressions) that were considered to be measurable (evaluates to a value of TRUE (1) or FALSE (0) but were not hit during simulation. The entire Verilog expression is displayed to the specified output stream with each of its measured expressions being underlined and numbered. The missed combinations are then output below the Verilog code, showing those logical combinations that were not hit during simulation.

Parameters:
ofile Pointer to file to output results to
funit Pointer to functional unit to display verbose combinational logic output for
rtype Specifies the type of report to display

References codegen_gen_expr(), esuppl_u::comb_cntd, combination_list_missed(), combination_output_expr(), combination_underline(), statement_s::exp, FALSE, func_iter_dealloc(), func_iter_get_next_statement(), func_iter_init(), expression_s::op, esuppl_u::part, PROFILE, PROFILE_END, RPT_TYPE_EXCL, RPT_TYPE_HIT, RPT_TYPE_MISS, expression_s::suppl, and TRUE.

Referenced by combination_funit_verbose(), and combination_instance_verbose().

02587   { PROFILE(COMBINATION_DISPLAY_VERBOSE);
02588 
02589   func_iter    fi;          /* Functional unit iterator */
02590   statement*   stmt;        /* Pointer to current statement */
02591   char**       code;        /* Code string from code generator */
02592   unsigned int code_depth;  /* Depth of code array */
02593 
02594   switch( rtype ) {
02595     case RPT_TYPE_HIT  :  fprintf( ofile, "    Hit Combinations\n\n" );                         break;
02596     case RPT_TYPE_MISS :  fprintf( ofile, "    Missed Combinations  (* = missed value)\n\n" );  break;
02597     case RPT_TYPE_EXCL :  fprintf( ofile, "    Excluded Combinations\n\n" );                    break;
02598   }
02599 
02600   /* Initialize functional unit iterator */
02601   func_iter_init( &fi, funit, TRUE, FALSE );
02602 
02603   /* Display missed combinations */
02604   stmt = func_iter_get_next_statement( &fi );
02605   while( stmt != NULL ) {
02606 
02607     int any_missed     = 0;
02608     int any_measurable = 0;
02609     int any_excluded   = 0;
02610     int all_excluded   = 0;
02611 
02612     combination_output_expr( stmt->exp, 0, &any_missed, &any_measurable, &any_excluded, &all_excluded );
02613 
02614     if( ((rtype == RPT_TYPE_MISS) && (any_missed == 1) && (all_excluded == 0) && (any_measurable == 1)) ||
02615         ((rtype == RPT_TYPE_HIT)  && (any_missed == 0) && (any_measurable == 1)) ||
02616         ((rtype == RPT_TYPE_EXCL) && (any_excluded == 1)) ) {
02617 
02618       stmt->exp->suppl.part.comb_cntd = 0;
02619 
02620       fprintf( ofile, "      =========================================================================================================\n" );
02621       fprintf( ofile, "       Line #     Expression\n" );
02622       fprintf( ofile, "      =========================================================================================================\n" );
02623 
02624       /* Generate line of code that missed combinational coverage */
02625       codegen_gen_expr( stmt->exp, stmt->exp->op, &code, &code_depth, funit );
02626 
02627       /* Output underlining feature for missed expressions */
02628       combination_underline( ofile, code, code_depth, stmt->exp, funit );
02629       fprintf( ofile, "\n" );
02630 
02631       /* Output logical combinations that missed complete coverage */
02632       combination_list_missed( ofile, stmt->exp, 0, funit, (rtype == RPT_TYPE_EXCL) );
02633 
02634     }
02635     
02636     stmt = func_iter_get_next_statement( &fi );
02637 
02638   }
02639 
02640   /* Deallocate functional unit iterator */
02641   func_iter_dealloc( &fi );
02642 
02643   PROFILE_END;
02644 
02645 }

static bool combination_does_multi_exp_need_ul ( expression exp  )  [static]
Returns:
Returns TRUE if the given expression multi-expression tree needs to be underlined
Parameters:
exp Pointer to expression to check for multi-expression underlines

References ESUPPL_WAS_FALSE, ESUPPL_WAS_TRUE, esuppl_u::eval_00, esuppl_u::eval_11, EXP_OP_AND, EXP_OP_LAND, FALSE, expression_s::left, expression_s::op, esuppl_u::part, PROFILE, PROFILE_END, expression_s::right, and expression_s::suppl.

Referenced by combination_multi_expr_calc().

00153   { PROFILE(COMBINATION_DOES_MULTI_EXP_NEED_UL);
00154 
00155   bool ul = FALSE;  /* Return value for this function */
00156   bool and_op;      /* Specifies if current expression is an AND or LAND operation */
00157 
00158   if( exp != NULL ) {
00159 
00160     /* Figure out if this is an AND/LAND operation */
00161     and_op = (exp->op == EXP_OP_AND) || (exp->op == EXP_OP_LAND);
00162 
00163     /* Decide if our expression requires that this sequence gets underlined */
00164     if( and_op ) {
00165       ul = (exp->suppl.part.eval_11 == 0) || (ESUPPL_WAS_FALSE( exp->left->suppl ) == 0) || (ESUPPL_WAS_FALSE( exp->right->suppl ) == 0);
00166     } else {
00167       ul = (exp->suppl.part.eval_00 == 0) || (ESUPPL_WAS_TRUE( exp->left->suppl )  == 0) || (ESUPPL_WAS_TRUE( exp->right->suppl )  == 0);
00168     }
00169 
00170     /* If we did not require underlining, check our left child */
00171     if( !ul && ((exp->left == NULL) || (exp->op == exp->left->op)) ) {
00172       ul = combination_does_multi_exp_need_ul( exp->left );
00173     }
00174 
00175     /* If we still have not found a reason to underline, check our right child */
00176     if( !ul && ((exp->right == NULL) || (exp->op == exp->right->op)) ) {
00177       ul = combination_does_multi_exp_need_ul( exp->right );
00178     }
00179 
00180   }
00181 
00182   PROFILE_END;
00183 
00184   return( ul );
00185 
00186 }

static void combination_draw_centered_line ( char *  line,
int  size,
int  exp_id,
bool  left_bar,
bool  right_bar 
) [static]

Draws an underline containing the specified expression ID to the specified line. The expression ID will be placed in the center of the generated underline.

Parameters:
line Pointer to line to create line onto
size Number of characters long line is
exp_id ID to place in underline
left_bar If set to TRUE, draws a vertical bar at the beginning of the underline
right_bar If set to TRUE, draws a vertical bar at the end of the underline

References PROFILE, and PROFILE_END.

Referenced by combination_prep_line(), and combination_underline_tree().

00808   { PROFILE(COMBINATION_DRAW_CENTERED_LINE);
00809 
00810   char         str_exp_id[12];   /* String containing value of exp_id */
00811   int          exp_id_size;      /* Number of characters exp_id is in length */
00812   int          i;                /* Loop iterator */
00813   unsigned int rv;               /* Return value from snprintf call */
00814 
00815   /* Calculate size of expression ID */
00816   rv = snprintf( str_exp_id, 12, "%d", exp_id );
00817   assert( rv < 12 );
00818   exp_id_size = strlen( str_exp_id );
00819 
00820   if( left_bar ) {
00821     line[0] = '|';
00822   } else {
00823     line[0] = '-';
00824   }
00825 
00826   for( i=1; i<((size - exp_id_size) / 2); i++ ) {
00827     line[i] = '-';
00828   }
00829 
00830   line[i] = '\0';
00831   strcat( line, str_exp_id );
00832 
00833   for( i=(i + exp_id_size); i<(size - 1); i++ ) {
00834     line[i] = '-';
00835   }
00836 
00837   if( right_bar ) {
00838     line[i] = '|';
00839   } else {
00840     line[i] = '-';
00841   }
00842   line[i+1] = '\0';
00843 
00844   PROFILE_END;
00845 
00846 }

static void combination_draw_line ( char *  line,
int  size,
int  exp_id 
) [static]

Draws an underline containing the specified expression ID to the specified line. The expression ID will be placed immediately following the beginning vertical bar.

Parameters:
line Pointer to line to create line onto
size Number of characters long line is
exp_id ID to place in underline

References PROFILE, and PROFILE_END.

Referenced by combination_underline_tree().

00771   { PROFILE(COMBINATION_DRAW_LINE);
00772 
00773   char         str_exp_id[12];  /* String containing value of exp_id */
00774   int          exp_id_size;     /* Number of characters exp_id is in length */
00775   int          i;               /* Loop iterator */
00776   unsigned int rv;              /* Return value from calls to snprintf */
00777 
00778   /* Calculate size of expression ID */
00779   rv = snprintf( str_exp_id, 12, "%d", exp_id );
00780   assert( rv < 12 );
00781   exp_id_size = strlen( str_exp_id );
00782 
00783   line[0] = '|';
00784   line[1] = '\0';
00785   strcat( line, str_exp_id );
00786 
00787   for( i=(exp_id_size + 1); i<(size - 1); i++ ) {
00788     line[i] = '-';
00789   }
00790 
00791   line[i]   = '|';
00792   line[i+1] = '\0';
00793 
00794   PROFILE_END;
00795 
00796 }

static void combination_event ( char ***  info,
int *  info_size,
expression exp,
bool  show_excluded 
) [static]

Displays the missed unary combination(s) that keep the combination coverage for the specified expression from achieving 100% coverage.

Parameters:
info Pointer to array of strings that will contain the coverage information for this expression
info_size Pointer to integer containing number of elements in info array
exp Pointer to expression to evaluate
show_excluded Set to TRUE to output the expression if it is excluded

References db_gen_exclusion_id(), db_get_exclusion_id_size(), ESUPPL_EXCLUDED, ESUPPL_WAS_TRUE, flag_output_exclusion_ids, gen_char_string(), expression_s::id, malloc_safe, expression_s::op, exp_info_s::op_str, PROFILE, PROFILE_END, expression_s::suppl, and expression_s::ulid.

Referenced by combination_get_missed_expr().

01681   { PROFILE(COMBINATION_EVENT);
01682 
01683   char         tmp[20];
01684   unsigned int length;
01685   char*        op = exp_op_info[exp->op].op_str;  /* Operation string */
01686 
01687   assert( exp != NULL );
01688 
01689   if( (!ESUPPL_WAS_TRUE( exp->suppl ) && !ESUPPL_EXCLUDED( exp->suppl )) ||
01690       (ESUPPL_EXCLUDED( exp->suppl ) && show_excluded) ) {
01691 
01692     char         spaces[30];
01693     unsigned int rv;
01694     unsigned int eid_size;
01695 
01696     if( flag_output_exclusion_ids ) {
01697       eid_size = db_get_exclusion_id_size();
01698     }
01699 
01700     spaces[0] = '\0';
01701 
01702     assert( exp->ulid != -1 );
01703 
01704     /* Allocate memory for info array */
01705     *info_size = 3;
01706     *info      = (char**)malloc_safe( sizeof( char* ) * (*info_size) );
01707 
01708     /* Allocate lines and assign values */
01709     length = 28;  rv = snprintf( tmp, 20, "%d", exp->ulid );  assert( rv < 20 );  length += strlen( tmp );
01710     if( flag_output_exclusion_ids ) {
01711       length += (eid_size - 1) + 4;
01712       gen_char_string( spaces, ' ', ((eid_size - 1) + 4) );
01713     }
01714     (*info)[0] = (char*)malloc_safe( length );
01715     if( flag_output_exclusion_ids ) {
01716       rv = snprintf( (*info)[0], length, "        (%s)  Expression %d   (0/1)", db_gen_exclusion_id( 'E', exp->id ), exp->ulid );
01717     } else {
01718       rv = snprintf( (*info)[0], length, "        Expression %d   (0/1)", exp->ulid );
01719     }
01720     assert( rv < length );
01721 
01722     length = 25 + strlen( op ) + strlen( spaces );
01723     (*info)[1] = (char*)malloc_safe( length );  rv = snprintf( (*info)[1], length, "%s        ^^^^^^^^^^^^^ - %s", spaces, op );  assert( rv < length );
01724     length = 31 + strlen( spaces );
01725     (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s         * Event did not occur", spaces );  assert( rv < length );
01726 
01727   }
01728 
01729   PROFILE_END;
01730 
01731 }

static bool combination_funit_summary ( FILE *  ofile,
funit_link head,
int *  hits,
int *  total 
) [static]
Returns:
Returns TRUE if combinations were found to be missed; otherwise, returns FALSE.

Outputs summarized results of the combinational logic coverage per functional unit to the specified output stream. Summarized results are printed as percentages based on the number of combinations hit during simulation divided by the total number of expression combinations possible in the design. An expression is said to be measurable for combinational coverage if it evaluates to a value of 0 or 1.

Parameters:
ofile Pointer to file to output results to
head Pointer to link in current functional unit list to evaluate
hits Pointer to number of combinations hit in all functional units
total Pointer to total number of combinations found in all functional units

References isuppl_u::assert_ovl, statistic_s::comb_hit, statistic_s::comb_total, combination_display_funit_summary(), FALSE, func_unit_s::filename, funit_link_s::funit, funit_flatten_name(), funit_is_unnamed(), get_basename(), funit_link_s::next, obf_file, obf_funit, ovl_is_assertion_module(), isuppl_u::part, PROFILE, PROFILE_END, statistic_s::show, and func_unit_s::stat.

Referenced by combination_report().

00733   { PROFILE(COMBINATION_FUNIT_SUMMARY);
00734 
00735   bool miss_found = FALSE;  /* Set to TRUE if missing combinations were found */
00736 
00737   while( head != NULL ) {
00738 
00739     /* If this is an assertion module, don't output any further */
00740     if( head->funit->stat->show && !funit_is_unnamed( head->funit ) &&
00741         ((info_suppl.part.assert_ovl == 0) || !ovl_is_assertion_module( head->funit )) ) {
00742 
00743       miss_found |= combination_display_funit_summary( ofile, obf_funit( funit_flatten_name( head->funit ) ), get_basename( obf_file( head->funit->filename ) ),
00744                                                        head->funit->stat->comb_hit, head->funit->stat->comb_total );
00745 
00746       /* Update accumulated information */
00747       *hits  += head->funit->stat->comb_hit;
00748       *total += head->funit->stat->comb_total;
00749 
00750     }
00751 
00752     head = head->next;
00753 
00754   }
00755 
00756   PROFILE_END;
00757 
00758   return( miss_found );
00759 
00760 }

static void combination_funit_verbose ( FILE *  ofile,
funit_link head 
) [static]
Exceptions:
anonymous combination_display_verbose

Outputs the verbose coverage report for the specified functional unit to the specified output stream.

Parameters:
ofile Pointer to file to output results to
head Pointer to current functional unit to evaluate

References statistic_s::comb_excluded, statistic_s::comb_hit, statistic_s::comb_total, combination_display_verbose(), combination_reset_counted_exprs(), func_unit_s::filename, free_safe, funit_link_s::funit, FUNIT_AFUNCTION, FUNIT_ANAMED_BLOCK, FUNIT_ATASK, funit_flatten_name(), FUNIT_FUNCTION, funit_is_unnamed(), FUNIT_MODULE, FUNIT_NAMED_BLOCK, FUNIT_TASK, funit_link_s::next, obf_file, PROFILE, PROFILE_END, report_covered, report_exclusions, RPT_TYPE_EXCL, RPT_TYPE_HIT, RPT_TYPE_MISS, scope_gen_printable(), func_unit_s::stat, and func_unit_s::type.

Referenced by combination_report().

02733   { PROFILE(COMBINATION_FUNIT_VERBOSE);
02734 
02735   char* pname;  /* Printable version of functional unit name */
02736 
02737   while( head != NULL ) {
02738 
02739     if( !funit_is_unnamed( head->funit ) &&
02740         (((head->funit->stat->comb_hit < head->funit->stat->comb_total) && !report_covered) ||
02741          ((head->funit->stat->comb_hit > 0) && report_covered) ||
02742          ((head->funit->stat->comb_excluded > 0) && report_exclusions)) ) {
02743 
02744       /* Get printable version of functional unit name */
02745       pname = scope_gen_printable( funit_flatten_name( head->funit ) );
02746 
02747       fprintf( ofile, "\n" );
02748       switch( head->funit->type ) {
02749         case FUNIT_MODULE       :  fprintf( ofile, "    Module: " );       break;
02750         case FUNIT_ANAMED_BLOCK :
02751         case FUNIT_NAMED_BLOCK  :  fprintf( ofile, "    Named Block: " );  break;
02752         case FUNIT_AFUNCTION    :
02753         case FUNIT_FUNCTION     :  fprintf( ofile, "    Function: " );     break;
02754         case FUNIT_ATASK        :
02755         case FUNIT_TASK         :  fprintf( ofile, "    Task: " );         break;
02756         default                 :  fprintf( ofile, "    UNKNOWN: " );      break;
02757       }
02758       fprintf( ofile, "%s, File: %s\n", pname, obf_file( head->funit->filename ) );
02759       fprintf( ofile, "    -------------------------------------------------------------------------------------------------------------\n" );
02760 
02761       free_safe( pname, (strlen( pname ) + 1) );
02762 
02763       if( ((head->funit->stat->comb_hit < head->funit->stat->comb_total) && !report_covered) ||
02764           ((head->funit->stat->comb_hit > 0) && report_covered && (!report_exclusions || (head->funit->stat->comb_hit > head->funit->stat->comb_excluded))) ) {
02765         combination_display_verbose( ofile, head->funit, (report_covered ? RPT_TYPE_HIT : RPT_TYPE_MISS) );
02766       }
02767       if( (head->funit->stat->comb_excluded > 0) && report_exclusions ) {
02768         combination_reset_counted_exprs( head->funit );
02769         combination_display_verbose( ofile, head->funit, RPT_TYPE_EXCL );
02770       }
02771 
02772     }
02773 
02774     head = head->next;
02775 
02776   }
02777 
02778   PROFILE_END;
02779 
02780 }

void combination_get_coverage ( int  exp_id,
int  uline_id,
char ***  info,
int *  info_size 
)

Gets output for specified expression including coverage information.

Returns:
Returns TRUE if we were successful in obtaining coverage detail for the specified information; otherwise, returns FALSE to indicate an error.

Calculates the coverage detail for the specified subexpression and stores this in string format in the info and info_size arguments. The coverage detail created matches the coverage detail output format that is used in the ASCII reports.

Parameters:
exp_id Expression ID of statement containing subexpression to get coverage detail for
uline_id Underline ID of subexpression to get coverage detail for
info Pointer to string array that will be populated with the coverage detail
info_size Number of entries in info array

References combination_get_missed_expr(), exp_link_s::exp, func_unit_s::exp_head, exp_link_find(), expression_find_uline_id(), funit_find_by_id(), PROFILE, PROFILE_END, and TRUE.

03016   { PROFILE(COMBINATION_GET_COVERAGE);
03017 
03018   func_unit*  funit;  /* Pointer to found functional unit */
03019   exp_link*   expl;   /* Pointer to current expression link */
03020   expression* exp;    /* Pointer to found expression */
03021 
03022   /* Find the functional unit that contains this expression */
03023   funit = funit_find_by_id( exp_id );
03024   assert( funit != NULL );
03025 
03026   /* Find statement containing this expression */
03027   expl = exp_link_find( exp_id, funit->exp_head );
03028   assert( expl != NULL );
03029 
03030   /* Now find the subexpression that matches the given underline ID */
03031   exp = expression_find_uline_id( expl->exp, uline_id );
03032   assert( exp != NULL );
03033 
03034   combination_get_missed_expr( info, info_size, exp, 0, TRUE );
03035 
03036   PROFILE_END;
03037 
03038 }

static void combination_get_exclude_list ( expression exp,
func_unit funit,
int **  excludes,
char ***  reasons,
unsigned int *  exclude_size 
) [static]

Recursively iterates through the specified expression tree, storing the exclude values for each underlined expression within the tree. The values are stored in the excludes parameter and its size is stored in the exclude_size parameter.

Parameters:
exp Pointer to current expression
funit Pointer to functional unit containing the exclude reasons for this expression tree
excludes Array of exclude values for each underlined expression in this tree
reasons Array of exclude reasons for each underlined expression in this tree
exclude_size Number of elements in the excludes array

References ESUPPL_EXCLUDED, exclude_find_exclude_reason(), expression_s::id, expression_s::left, PROFILE, PROFILE_END, realloc_safe, exclude_reason_s::reason, expression_s::right, strdup_safe, expression_s::suppl, and expression_s::ulid.

Referenced by combination_get_expression().

02852   { PROFILE(COMBINATION_GET_EXCLUDE_LIST);
02853 
02854   if( exp != NULL ) {
02855 
02856     /* Store the exclude value for this expression */
02857     if( exp->ulid != -1 ) {
02858 
02859       exclude_reason* er;
02860      
02861       if( (exp->ulid > 0) && ((unsigned int)exp->ulid >= *exclude_size) ) {
02862         int i;
02863         *excludes     = (int*)realloc_safe( *excludes, (sizeof( int ) * exp->ulid), (sizeof( int ) * (exp->ulid + 1)) );
02864         *reasons      = (char**)realloc_safe( *reasons, (sizeof( char* ) * exp->ulid), (sizeof( char* ) * (exp->ulid + 1)) );
02865         for( i=*exclude_size; i<=exp->ulid; i++ ) {
02866           (*excludes)[i] = 0;
02867           (*reasons)[i]  = NULL;
02868         }
02869         *exclude_size = exp->ulid + 1;
02870       }
02871 
02872       (*excludes)[exp->ulid] = ESUPPL_EXCLUDED( exp->suppl );
02873 
02874       /* If the expression is currently excluded, check to see if there's a reason associated with it */
02875       if( (ESUPPL_EXCLUDED( exp->suppl ) == 1) && ((er = exclude_find_exclude_reason( 'E', exp->id, funit )) != NULL) ) {
02876         (*reasons)[exp->ulid] = strdup_safe( er->reason );
02877       } else {
02878         (*reasons)[exp->ulid] = NULL;
02879       }
02880 
02881     }
02882 
02883     /* Get exclude values for children */
02884     combination_get_exclude_list( exp->left,  funit, excludes, reasons, exclude_size );
02885     combination_get_exclude_list( exp->right, funit, excludes, reasons, exclude_size );
02886 
02887   }
02888 
02889   PROFILE_END;
02890 
02891 }

void combination_get_expression ( int  expr_id,
char ***  code,
int **  uline_groups,
unsigned int *  code_size,
char ***  ulines,
unsigned int *  uline_size,
int **  excludes,
char ***  reasons,
unsigned int *  exclude_size 
)

Gets output for specified expression including underlines and code.

Exceptions:
anonymous Throw combination_underline_tree

Gets the combinational logic coverage information for the specified expression ID, storing the output in the code and ulines arrays. Used by the GUI for displaying an expression's coverage information.

Parameters:
expr_id Expression ID to retrieve information for
code Pointer to an array of strings containing generated code for this expression
uline_groups Pointer to an array of integers used for underlined missed subexpressions in this expression
code_size Pointer to value that will be set to indicate the number of elements in the code array
ulines Pointer to an array of strings that contain underlines of missed subexpressions
uline_size Pointer to value that will be set to indicate the number of elements in the ulines array
excludes Pointer to an array of values that determine if the associated subexpression is currently excluded or not from coverage
reasons Pointer to an array of strings that specify the reason for exclusion
exclude_size Pointer to value that will be set to indicate the number of elements in excludes

References Catch_anonymous, codegen_gen_expr(), combination_get_exclude_list(), combination_prep_line(), combination_underline_tree(), exp_link_s::exp, func_unit_s::exp_head, exp_link_find(), free_safe, funit_find_by_id(), funit_get_curr_module(), malloc_safe, expression_s::op, PROFILE, PROFILE_END, realloc_safe, Throw, and Try.

02910   { PROFILE(COMBINATION_GET_EXPRESSION);
02911 
02912   exp_link*    expl;              /* Pointer to found signal link */
02913   unsigned int tmp;               /* Temporary integer (unused) */
02914   unsigned int i, j;              /* Loop iterators */
02915   char**       tmp_ulines;
02916   unsigned int tmp_uline_size;
02917   int          start     = 0;
02918   unsigned int uline_max = 20;
02919   func_unit*   funit;
02920 
02921   /* Find functional unit that contains this expression */
02922   funit = funit_find_by_id( expr_id );
02923   assert( funit != NULL );
02924 
02925   /* Find the expression itself */
02926   expl = exp_link_find( expr_id, funit->exp_head );
02927   assert( expl != NULL );
02928 
02929   /* Generate line of code that missed combinational coverage */
02930   codegen_gen_expr( expl->exp, expl->exp->op, code, code_size, funit );
02931   *uline_groups = (int*)malloc_safe( sizeof( int ) * (*code_size) );
02932 
02933   /* Generate exclude information */
02934   *excludes     = NULL;
02935   *reasons      = NULL;
02936   *exclude_size = 0;
02937   combination_get_exclude_list( expl->exp, funit_get_curr_module( funit ), excludes, reasons, exclude_size );
02938 
02939   Try {
02940 
02941     /* Output underlining feature for missed expressions */
02942     combination_underline_tree( expl->exp, 0, &tmp_ulines, &tmp_uline_size, &tmp, expl->exp->op, (*code_size == 1), funit );
02943   
02944   } Catch_anonymous {
02945     unsigned int i;
02946     free_safe( *uline_groups, (sizeof( int ) * (*code_size)) );
02947     *uline_groups = NULL;
02948     for( i=0; i<*code_size; i++ ) {
02949       free_safe( (*code)[i], (strlen( (*code)[i] ) + 1) );
02950     }
02951     free_safe( *code, (sizeof( char* ) * *code_size) );
02952     *code      = NULL;
02953     *code_size = 0;
02954     free_safe( *excludes, (sizeof( int* ) * *exclude_size) );
02955     *excludes     = NULL;
02956     *exclude_size = 0;
02957     Throw 0;
02958   }
02959 
02960   *ulines     = (char**)malloc_safe( sizeof( char* ) * uline_max );
02961   *uline_size = 0;
02962 
02963   for( i=0; i<*code_size; i++ ) {
02964 
02965     assert( (*code)[i] != NULL );
02966 
02967     (*uline_groups)[i] = 0;
02968 
02969     if( *code_size == 1 ) {
02970       *ulines            = tmp_ulines;
02971       *uline_size        = tmp_uline_size;
02972       (*uline_groups)[0] = tmp_uline_size;
02973       tmp_uline_size     = 0;
02974     } else {
02975       for( j=0; j<tmp_uline_size; j++ ) {
02976         if( ((*ulines)[*uline_size] = combination_prep_line( tmp_ulines[j], start, strlen( (*code)[i] ) )) != NULL ) {
02977           ((*uline_groups)[i])++;
02978           (*uline_size)++;
02979           if( *uline_size == uline_max ) {
02980             uline_max += 20;
02981             *ulines    = (char**)realloc_safe( *ulines, (sizeof( char* ) * (uline_max - 20)), (sizeof( char* ) * uline_max) );
02982           }
02983         }
02984       }
02985     }
02986 
02987     start += strlen( (*code)[i] );
02988 
02989   }
02990 
02991   for( i=0; i<tmp_uline_size; i++ ) {
02992     free_safe( tmp_ulines[i], (strlen( tmp_ulines[i] ) + 1) );
02993   }
02994 
02995   if( tmp_uline_size > 0 ) {
02996     free_safe( tmp_ulines, (sizeof( char* ) * tmp_uline_size) );
02997   }
02998 
02999   PROFILE_END;
03000 
03001 }

void combination_get_funit_summary ( func_unit funit,
unsigned int *  hit,
unsigned int *  excluded,
unsigned int *  total 
)

Gets combinational logic summary statistics for specified functional unit.

Retrieves the combinational logic summary information for the specified functional unit

Parameters:
funit Pointer to functional unit
hit Pointer to location to store the number of hit combinations for the specified functional unit
excluded Pointer to number of excluded logical combinations
total Pointer to location to store the total number of combinations for the specified functional unit

References statistic_s::comb_excluded, statistic_s::comb_hit, statistic_s::comb_total, PROFILE, PROFILE_END, and func_unit_s::stat.

00569   { PROFILE(COMBINATION_GET_FUNIT_SUMMARY);
00570 
00571   *hit      = funit->stat->comb_hit;
00572   *excluded = funit->stat->comb_excluded;
00573   *total    = funit->stat->comb_total;
00574 
00575   PROFILE_END;
00576 
00577 }

void combination_get_inst_summary ( funit_inst inst,
unsigned int *  hit,
unsigned int *  excluded,
unsigned int *  total 
)

Gets combinational logic summary statistics for specified functional unit instance.

Retrieves the combinational logic summary information for the specified functional unit instance

Parameters:
inst Pointer to functional unit instance
hit Pointer to location to store the number of hit combinations for the specified functional unit instance
excluded Pointer to number of excluded logical combinations
total Pointer to location to store the total number of combinations for the specified functional unit instance

References statistic_s::comb_excluded, statistic_s::comb_hit, statistic_s::comb_total, PROFILE, PROFILE_END, and funit_inst_s::stat.

00587   { PROFILE(COMBINATION_GET_INST_SUMMARY);
00588   
00589   *hit      = inst->stat->comb_hit;
00590   *excluded = inst->stat->comb_excluded;
00591   *total    = inst->stat->comb_total;
00592             
00593   PROFILE_END;
00594   
00595 }

static void combination_get_missed_expr ( char ***  info,
int *  info_size,
expression exp,
unsigned int  curr_depth,
bool  show_excluded 
) [static]

Calculates the missed coverage detail output for the given expression, placing the output to the info array. This array can then be sent to an ASCII report file or the GUI.

Parameters:
info Pointer to an array of strings containing expression coverage detail
info_size Pointer to a value that will be set to indicate the number of valid elements in the info array
exp Pointer to the expression to get the coverage detail for
curr_depth Current expression depth (used to figure out when to stop getting coverage information -- if the user has specified a maximum depth)
show_excluded Set to TRUE if excluded expressions should be output

References combination_event(), combination_multi_vars(), combination_two_vars(), combination_unary(), ESUPPL_IS_ROOT, EXP_OP_AND, EXP_OP_LAND, EXP_OP_LOR, EXP_OP_OR, expr_stmt_u::expr, EXPR_COMB_MISSED, EXPR_IS_COMB, EXPR_IS_EVENT, expression_s::left, expression_s::op, expression_s::parent, PROFILE, PROFILE_END, report_comb_depth, REPORT_DETAILED, REPORT_VERBOSE, expression_s::right, and expression_s::suppl.

Referenced by combination_get_coverage(), and combination_list_missed().

02418   { PROFILE(COMBINATION_GET_MISSED_EXPR);
02419 
02420   assert( exp != NULL );
02421 
02422   *info_size = 0;
02423 
02424   if( EXPR_COMB_MISSED( exp ) &&
02425       (((report_comb_depth == REPORT_DETAILED) && (curr_depth <= report_comb_depth)) ||
02426         (report_comb_depth == REPORT_VERBOSE)) ) {
02427  
02428     if( (ESUPPL_IS_ROOT( exp->suppl ) == 1) || (exp->op != exp->parent->expr->op) ||
02429         ((exp->op != EXP_OP_AND)  &&
02430          (exp->op != EXP_OP_LAND) &&
02431          (exp->op != EXP_OP_OR)   &&
02432          (exp->op != EXP_OP_LOR)) ) {
02433 
02434       if( (((exp->left != NULL) &&
02435             (exp->op == exp->left->op)) ||
02436            ((exp->right != NULL) &&
02437             (exp->op == exp->right->op))) &&
02438           ((exp->op == EXP_OP_AND)  ||
02439            (exp->op == EXP_OP_OR)   ||
02440            (exp->op == EXP_OP_LAND) ||
02441            (exp->op == EXP_OP_LOR)) ) {
02442 
02443         combination_multi_vars( info, info_size, exp, show_excluded );
02444 
02445       } else {
02446 
02447         /* Create combination table */
02448         if( EXPR_IS_COMB( exp ) ) {
02449           combination_two_vars( info, info_size, exp, show_excluded );
02450         } else if( EXPR_IS_EVENT( exp ) ) {
02451           combination_event( info, info_size, exp, show_excluded );
02452         } else {
02453           combination_unary( info, info_size, exp, show_excluded );
02454         }
02455 
02456       }
02457 
02458     }
02459 
02460   }
02461 
02462   PROFILE_END;
02463 
02464 }

void combination_get_stats ( func_unit funit,
unsigned int *  hit,
unsigned int *  excluded,
unsigned int *  total 
)

Calculates combination logic statistics for summary output.

Iterates through specified expression list and finds all root expressions. For each root expression, the combination_get_tree_stats function is called to generate the coverage numbers for the specified expression tree. Called by report function.

Parameters:
funit Pointer to functional unit to search
hit Pointer to number of logical combinations hit during simulation
excluded Pointer to number of excluded logical combinations
total Pointer to total number of logical combinations

References combination_get_tree_stats(), statement_s::exp, FALSE, func_iter_dealloc(), func_iter_get_next_statement(), func_iter_init(), funit_is_unnamed(), statement_s::part, PROFILE, PROFILE_END, statement_s::suppl, and TRUE.

Referenced by report_gather_funit_stats(), and report_gather_instance_stats().

00534   { PROFILE(COMBINATION_GET_STATS);
00535 
00536   func_iter  fi;    /* Functional unit iterator */
00537   statement* stmt;  /* Pointer to current statement being examined */
00538   int        ulid;  /* Current underline ID for this expression */
00539   
00540   /* If the given functional unit is not an unnamed scope, traverse it now */
00541   if( !funit_is_unnamed( funit ) ) {
00542 
00543     /* Initialize functional unit iterator */
00544     func_iter_init( &fi, funit, TRUE, FALSE );
00545 
00546     /* Traverse statements in the given functional unit */
00547     while( (stmt = func_iter_get_next_statement( &fi )) != NULL ) {
00548       ulid = 1;
00549       combination_get_tree_stats( stmt->exp, &ulid, 0, stmt->suppl.part.excluded, hit, excluded, total );
00550     }
00551 
00552     /* Deallocate functional unit iterator */
00553     func_iter_dealloc( &fi );
00554 
00555   }
00556 
00557   PROFILE_END;
00558 
00559 }

void combination_get_tree_stats ( expression exp,
int *  ulid,
unsigned int  curr_depth,
bool  excluded,
unsigned int *  hit,
unsigned int *  excludes,
unsigned int *  total 
)

Calculates combination logic statistics for a single expression tree.

Recursively traverses the specified expression tree, recording the total number of logical combinations in the expression list and the number of combinations hit during the course of simulation. An expression can be considered for combinational coverage if the "measured" bit is set in the expression.

Parameters:
exp Pointer to expression tree to traverse
ulid Pointer to current underline ID
curr_depth Current search depth in given expression tree
excluded Specifies that this expression should be excluded for hit information because one or more of its parent expressions have been excluded
hit Pointer to number of logical combinations hit during simulation
excludes Pointer to number of excluded logical combinations
total Pointer to total number of logical combinations

References allow_multi_expr, AND_COMB, esuppl_u::comb_cntd, combination_calc_depth(), combination_get_tree_stats(), combination_is_expr_multi_node(), combination_multi_expr_calc(), ESUPPL_EXCLUDED, ESUPPL_IS_ROOT, ESUPPL_WAS_COMB_COUNTED, ESUPPL_WAS_FALSE, ESUPPL_WAS_TRUE, esuppl_u::eval_00, esuppl_u::eval_01, esuppl_u::eval_10, esuppl_u::eval_11, EXP_OP_AND, EXP_OP_EXPAND, EXP_OP_LAND, EXP_OP_LOR, EXP_OP_OR, expr_stmt_u::expr, EXPR_IS_COMB, EXPR_IS_EVENT, EXPR_IS_MEASURABLE, expression_is_static_only(), FALSE, exp_info_s::is_comb, expression_s::left, expression_s::op, OR_COMB, expression_s::parent, esuppl_u::part, PROFILE, PROFILE_END, report_bitwise, report_comb_depth, REPORT_DETAILED, REPORT_SUMMARY, REPORT_VERBOSE, expression_s::right, exp_info_s::suppl, expression_s::suppl, TRUE, expression_s::ulid, expression_s::value, vector_get_eval_ab_count(), vector_get_eval_abc_count(), vector_get_eval_abcd_count(), and vector_s::width.

Referenced by combination_get_stats(), combination_get_tree_stats(), and exclude_expr_assign_and_recalc().

00333   { PROFILE(COMBINATION_GET_TREE_STATS);
00334 
00335   int num_hit = 0;  /* Number of expression value hits for the current expression */
00336   int tot_num;      /* Total number of combinations for the current expression */
00337 
00338   if( exp != NULL ) {
00339 
00340     /* Calculate excluded value for this expression */
00341     excluded |= ESUPPL_EXCLUDED( exp->suppl );
00342 
00343     /* Calculate children */
00344     combination_get_tree_stats( exp->left,  ulid, combination_calc_depth( exp, curr_depth, TRUE ),  excluded, hit, excludes, total );
00345     combination_get_tree_stats( exp->right, ulid, combination_calc_depth( exp, curr_depth, FALSE ), excluded, hit, excludes, total );
00346 
00347     if( ((report_comb_depth == REPORT_DETAILED) && (curr_depth <= report_comb_depth)) ||
00348          (report_comb_depth == REPORT_VERBOSE) ||
00349          (report_comb_depth == REPORT_SUMMARY) ) {
00350 
00351       if( (EXPR_IS_MEASURABLE( exp ) == 1) && (ESUPPL_WAS_COMB_COUNTED( exp->suppl ) == 0) ) {
00352 
00353         if( (ESUPPL_IS_ROOT( exp->suppl ) == 1) || (exp->op != exp->parent->expr->op) ||
00354             ((exp->op != EXP_OP_AND) &&
00355              (exp->op != EXP_OP_LAND) &&
00356              (exp->op != EXP_OP_OR)   &&
00357              (exp->op != EXP_OP_LOR)) ||
00358              !allow_multi_expr ) {
00359 
00360           /* Calculate current expression combination coverage */
00361           if( (((exp->left != NULL) &&
00362                 (exp->op == exp->left->op)) ||
00363                ((exp->right != NULL) &&
00364                 (exp->op == exp->right->op))) &&
00365               ((exp->op == EXP_OP_AND)  ||
00366                (exp->op == EXP_OP_OR)   ||
00367                (exp->op == EXP_OP_LAND) ||
00368                (exp->op == EXP_OP_LOR)) && allow_multi_expr ) {
00369             combination_multi_expr_calc( exp, ulid, FALSE, excluded, hit, excludes, total );
00370           } else {
00371             if( !expression_is_static_only( exp ) ) {
00372               if( EXPR_IS_COMB( exp ) == 1 ) {
00373                 if( exp_op_info[exp->op].suppl.is_comb == AND_COMB ) {
00374                   if( report_bitwise ) {
00375                     tot_num = 3 * exp->value->width;
00376                     num_hit = vector_get_eval_abc_count( exp->value );
00377                   } else {
00378                     tot_num = 3;
00379                     num_hit = ESUPPL_WAS_FALSE( exp->left->suppl )  + 
00380                               ESUPPL_WAS_FALSE( exp->right->suppl ) +
00381                               exp->suppl.part.eval_11;
00382                   }
00383                 } else if( exp_op_info[exp->op].suppl.is_comb == OR_COMB ) {
00384                   if( report_bitwise ) {
00385                     tot_num = 3 * exp->value->width;
00386                     num_hit = vector_get_eval_abc_count( exp->value );
00387                   } else {
00388                     tot_num = 3;
00389                     num_hit = ESUPPL_WAS_TRUE( exp->left->suppl )  +
00390                               ESUPPL_WAS_TRUE( exp->right->suppl ) +
00391                               exp->suppl.part.eval_00;
00392                   }
00393                 } else {
00394                   if( report_bitwise ) {
00395                     tot_num = 4 * exp->value->width;
00396                     num_hit = vector_get_eval_abcd_count( exp->value );
00397                   } else {
00398                     tot_num = 4;
00399                     num_hit = exp->suppl.part.eval_00 +
00400                               exp->suppl.part.eval_01 +
00401                               exp->suppl.part.eval_10 +
00402                               exp->suppl.part.eval_11;
00403                   }
00404                 }
00405                 *total += tot_num;
00406                 if( excluded ) {
00407                   *hit      += tot_num;
00408                   *excludes += tot_num;
00409                 } else {
00410                   *hit += num_hit;
00411                 }
00412                 if( (num_hit != tot_num) && (exp->ulid == -1) && !combination_is_expr_multi_node( exp ) ) {
00413                   exp->ulid = *ulid;
00414                   (*ulid)++;
00415                 }
00416               } else if( EXPR_IS_EVENT( exp ) == 1 ) {
00417                 (*total)++;
00418                 num_hit = ESUPPL_WAS_TRUE( exp->suppl );
00419                 if( excluded ) {
00420                   (*hit)++;
00421                   (*excludes)++;
00422                 } else {
00423                   *hit += num_hit;
00424                 }
00425                 if( (num_hit != 1) && (exp->ulid == -1) && !combination_is_expr_multi_node( exp ) ) {
00426                   exp->ulid = *ulid;
00427                   (*ulid)++;
00428                 }
00429               } else {
00430                 if( (exp->op != EXP_OP_EXPAND) || (exp->value->width > 0) ) {
00431                   if( report_bitwise ) {
00432                     *total  = *total + (2 * exp->value->width);
00433                     num_hit = vector_get_eval_ab_count( exp->value );
00434                   } else {
00435                     *total  = *total + 2;
00436                     num_hit = ESUPPL_WAS_TRUE( exp->suppl ) + ESUPPL_WAS_FALSE( exp->suppl );
00437                   }
00438                   if( excluded ) {
00439                     *hit      += 2;
00440                     *excludes += 2;
00441                   } else {
00442                     *hit += num_hit;
00443                   }
00444                   if( (num_hit != 2) && (exp->ulid == -1) && !combination_is_expr_multi_node( exp ) ) {
00445                     exp->ulid = *ulid;
00446                     (*ulid)++;
00447                   }
00448                 }
00449               }
00450             }
00451           }
00452 
00453         }
00454 
00455       }
00456 
00457     }
00458 
00459     /* Consider this expression to be counted */
00460     exp->suppl.part.comb_cntd = 1;
00461 
00462   }
00463 
00464   PROFILE_END;
00465 
00466 }

static bool combination_instance_summary ( FILE *  ofile,
funit_inst root,
char *  parent,
int *  hits,
int *  total 
) [static]
Returns:
Returns TRUE if combinations were found to be missed; otherwise, returns FALSE.

Outputs summarized results of the combinational logic coverage per functional unit instance to the specified output stream. Summarized results are printed as percentages based on the number of combinations hit during simulation divided by the total number of expression combinations possible in the design. An expression is said to be measurable for combinational coverage if it evaluates to a value of 0 or 1.

Parameters:
ofile Pointer to file to output results to
root Pointer to node in instance tree to evaluate
parent Name of parent instance name
hits Pointer to accumulated number of combinations hit
total Pointer to accumulated number of total combinations in design

References isuppl_u::assert_ovl, funit_inst_s::child_head, statistic_s::comb_hit, statistic_s::comb_total, combination_display_instance_summary(), db_is_unnamed_scope(), FALSE, free_safe, funit_inst_s::funit, funit_is_unnamed(), funit_inst_s::name, funit_inst_s::name_diff, funit_inst_s::next, obf_inst, ovl_is_assertion_module(), isuppl_u::part, PROFILE, PROFILE_END, scope_gen_printable(), statistic_s::show, funit_inst_s::stat, and funit_inst_s::suppl.

Referenced by combination_report().

00638   { PROFILE(COMBINATION_INSTANCE_SUMMARY);
00639 
00640   funit_inst* curr;                /* Pointer to current child functional unit instance of this node */
00641   char        tmpname[4096];       /* Temporary name holder of instance */
00642   char*       pname;               /* Printable version of instance name */
00643   bool        miss_found = FALSE;  /* Set to TRUE if a logical combination was missed */
00644 
00645   assert( root != NULL );
00646   assert( root->stat != NULL );
00647 
00648   /* Generate printable version of instance name */
00649   pname = scope_gen_printable( root->name );
00650 
00651   if( db_is_unnamed_scope( pname ) || root->suppl.name_diff ) {
00652     strcpy( tmpname, parent );
00653   } else if( strcmp( parent, "*" ) == 0 ) {
00654     strcpy( tmpname, pname );
00655   } else {
00656     unsigned int rv = snprintf( tmpname, 4096, "%s.%s", parent, obf_inst( pname ) );
00657     assert( rv < 4096 );
00658   }
00659 
00660   free_safe( pname, (strlen( pname ) + 1) );
00661 
00662   if( (root->funit != NULL) && root->stat->show && !funit_is_unnamed( root->funit ) &&
00663       ((info_suppl.part.assert_ovl == 0) || !ovl_is_assertion_module( root->funit )) ) {
00664 
00665     miss_found |= combination_display_instance_summary( ofile, tmpname, root->stat->comb_hit, root->stat->comb_total );
00666 
00667     /* Update accumulated information */
00668     *hits  += root->stat->comb_hit;
00669     *total += root->stat->comb_total;
00670 
00671   }
00672 
00673   /* If this is an assertion module, don't output any further */
00674   if( (info_suppl.part.assert_ovl == 0) || !ovl_is_assertion_module( root->funit ) ) {
00675 
00676     curr = root->child_head;
00677     while( curr != NULL ) {
00678       miss_found |= combination_instance_summary( ofile, curr, tmpname, hits, total );
00679       curr = curr->next;
00680     }
00681 
00682   }
00683 
00684   PROFILE_END;
00685 
00686   return( miss_found );
00687 
00688 }

static void combination_instance_verbose ( FILE *  ofile,
funit_inst root,
char *  parent 
) [static]
Exceptions:
anonymous combination_display_verbose combination_instance_verbose

Outputs the verbose coverage report for the specified functional unit instance to the specified output stream.

Parameters:
ofile Pointer to file to output results to
root Pointer to current functional unit instance to evaluate
parent Name of parent instance

References funit_inst_s::child_head, statistic_s::comb_excluded, statistic_s::comb_hit, statistic_s::comb_total, combination_display_verbose(), combination_reset_counted_exprs(), db_is_unnamed_scope(), func_unit_s::filename, free_safe, funit_inst_s::funit, FUNIT_AFUNCTION, FUNIT_ANAMED_BLOCK, FUNIT_ATASK, funit_flatten_name(), FUNIT_FUNCTION, funit_is_unnamed(), FUNIT_MODULE, FUNIT_NAMED_BLOCK, FUNIT_TASK, funit_inst_s::name, funit_inst_s::name_diff, funit_inst_s::next, obf_file, PROFILE, PROFILE_END, report_covered, report_exclusions, RPT_TYPE_EXCL, RPT_TYPE_HIT, RPT_TYPE_MISS, scope_gen_printable(), funit_inst_s::stat, funit_inst_s::suppl, and func_unit_s::type.

Referenced by combination_report().

02657   { PROFILE(COMBINATION_INSTANCE_VERBOSE);
02658 
02659   funit_inst* curr_inst;      /* Pointer to current instance being evaluated */
02660   char        tmpname[4096];  /* Temporary name holder of instance */
02661   char*       pname;          /* Printable version of instance name */
02662 
02663   assert( root != NULL );
02664 
02665   /* Get printable version of instance name */
02666   pname = scope_gen_printable( root->name );
02667 
02668   if( db_is_unnamed_scope( pname ) || root->suppl.name_diff ) {
02669     strcpy( tmpname, parent );
02670   } else if( strcmp( parent, "*" ) == 0 ) {
02671     strcpy( tmpname, pname );
02672   } else {
02673     unsigned int rv = snprintf( tmpname, 4096, "%s.%s", parent, pname );
02674     assert( rv < 4096 );
02675   }
02676 
02677   free_safe( pname, (strlen( pname ) + 1) );
02678 
02679   if( (root->funit != NULL) && !funit_is_unnamed( root->funit ) &&
02680       (((root->stat->comb_hit < root->stat->comb_total) && !report_covered) ||
02681        ((root->stat->comb_hit > 0) && report_covered) ||
02682        ((root->stat->comb_excluded > 0) && report_exclusions)) ) {
02683 
02684     /* Get printable version of functional unit name */
02685     pname = scope_gen_printable( funit_flatten_name( root->funit ) );
02686 
02687     fprintf( ofile, "\n" );
02688     switch( root->funit->type ) {
02689       case FUNIT_MODULE       :  fprintf( ofile, "    Module: " );       break;
02690       case FUNIT_ANAMED_BLOCK :
02691       case FUNIT_NAMED_BLOCK  :  fprintf( ofile, "    Named Block: " );  break;
02692       case FUNIT_AFUNCTION    :
02693       case FUNIT_FUNCTION     :  fprintf( ofile, "    Function: " );     break;
02694       case FUNIT_ATASK        :
02695       case FUNIT_TASK         :  fprintf( ofile, "    Task: " );         break;
02696       default                 :  fprintf( ofile, "    UNKNOWN: " );      break;
02697     }
02698     fprintf( ofile, "%s, File: %s, Instance: %s\n", pname, obf_file( root->funit->filename ), tmpname );
02699     fprintf( ofile, "    -------------------------------------------------------------------------------------------------------------\n" );
02700 
02701     free_safe( pname, (strlen( pname ) + 1) );
02702 
02703     if( ((root->stat->comb_hit < root->stat->comb_total) && !report_covered) ||
02704         ((root->stat->comb_hit > 0) && report_covered && (!report_exclusions || (root->stat->comb_hit > root->stat->comb_excluded))) ) {
02705       combination_display_verbose( ofile, root->funit, (report_covered ? RPT_TYPE_HIT : RPT_TYPE_MISS) );
02706     }
02707     if( report_exclusions && (root->stat->comb_excluded > 0) ) {
02708       combination_reset_counted_exprs( root->funit );
02709       combination_display_verbose( ofile, root->funit, RPT_TYPE_EXCL );
02710     }
02711 
02712   }
02713 
02714   curr_inst = root->child_head;
02715   while( curr_inst != NULL ) {
02716     combination_instance_verbose( ofile, curr_inst, tmpname );
02717     curr_inst = curr_inst->next;
02718   }
02719 
02720   PROFILE_END;
02721 
02722 }

static bool combination_is_expr_multi_node ( expression exp  )  [static]
Returns:
Returns TRUE if the specified expression is part of a multi-value expression tree; otherwise, returns FALSE.

Checks the specified expression to see if it is a part of a multi-value expression tree. If the expression is part of a tree, returns a value of TRUE; otherwise, returns a value of FALSE. This function is used when determining if a non-multi-value expression should be assigned an underline ID (it should if the expression is not part of a multi-value expression tree) or be assigned one later (if the expression is part of a multi-value expression tree -- the ID will be assigned to it when the multi-value expression tree is assigned underline IDs.

Parameters:
exp Pointer to expression to evaluate

References ESUPPL_IS_ROOT, EXP_OP_AND, EXP_OP_LAND, EXP_OP_LOR, EXP_OP_OR, expr_stmt_u::expr, expression_s::id, expression_s::left, expression_s::op, expression_s::parent, PROFILE, PROFILE_END, expression_s::right, expression_s::suppl, and expression_s::ulid.

Referenced by combination_get_tree_stats().

00295   { PROFILE(COMBINATION_IS_EXPR_MULTI_NODE);
00296 
00297   bool retval = (exp != NULL) &&
00298                 (ESUPPL_IS_ROOT( exp->suppl ) == 0) && 
00299                 (exp->parent->expr->left  != NULL) &&
00300                 (exp->parent->expr->right != NULL) &&
00301                 ( ( (exp->parent->expr->right->id == exp->id) &&
00302                     (exp->parent->expr->left->ulid == -1) ) ||
00303                   (exp->parent->expr->left->id == exp->id) ) &&
00304                 ( (exp->parent->expr->op == EXP_OP_AND)  ||
00305                   (exp->parent->expr->op == EXP_OP_LAND) ||
00306                   (exp->parent->expr->op == EXP_OP_OR)   ||
00307                   (exp->parent->expr->op == EXP_OP_LOR) ) &&
00308                 ( ( (ESUPPL_IS_ROOT( exp->parent->expr->suppl ) == 0) &&
00309                     (exp->parent->expr->op == exp->parent->expr->parent->expr->op) ) ||
00310                   (exp->parent->expr->left->op == exp->parent->expr->op) );
00311 
00312   PROFILE_END;
00313 
00314   return( retval );
00315 
00316 }

static void combination_list_missed ( FILE *  ofile,
expression exp,
unsigned int  curr_depth,
func_unit funit,
bool  show_exclusions 
) [static]

Describe which combinations were not hit for all subexpressions in the specified expression tree. We display the value of missed combinations by displaying the combinations of the children expressions that were not run during simulation.

Parameters:
ofile Pointer to file to output results to
exp Pointer to expression tree to evaluate
curr_depth Specifies current depth of expression tree
funit Pointer to current functional unit
show_exclusions Set to TRUE to display exclusions

References combination_calc_depth(), combination_get_missed_expr(), db_get_exclusion_id_size(), exclude_find_exclude_reason(), FALSE, flag_output_exclusion_ids, free_safe, expression_s::id, expression_s::left, PROFILE, PROFILE_END, exclude_reason_s::reason, report_exclusions, report_output_exclusion_reason(), expression_s::right, and TRUE.

Referenced by combination_display_verbose().

02478   { PROFILE(COMBINATION_LIST_MISSED);
02479 
02480   char** info;       /* String array containing combination coverage information for this expression */
02481   int    info_size;  /* Specifies the number of valid entries in the info array */
02482   int    i;          /* Loop iterator */
02483   
02484   if( exp != NULL ) {
02485 
02486     exclude_reason* er;
02487     
02488     combination_list_missed( ofile, exp->left,  combination_calc_depth( exp, curr_depth, TRUE ),  funit, show_exclusions );
02489     combination_list_missed( ofile, exp->right, combination_calc_depth( exp, curr_depth, FALSE ), funit, show_exclusions );
02490 
02491     /* Get coverage information for this expression */
02492     combination_get_missed_expr( &info, &info_size, exp, curr_depth, show_exclusions );
02493 
02494     /* If there was any coverage information for this expression, output it to the specified output stream */
02495     if( info_size > 0 ) {
02496 
02497       for( i=0; i<info_size; i++ ) {
02498 
02499         fprintf( ofile, "%s\n", info[i] );
02500         free_safe( info[i], (strlen( info[i] ) + 1) );
02501 
02502       }
02503 
02504       /* Output the exclusion reason information, if it exists */
02505       if( report_exclusions && (er = exclude_find_exclude_reason( 'E', exp->id, funit )) != NULL ) {
02506         if( flag_output_exclusion_ids ) {
02507           report_output_exclusion_reason( ofile, (14 + (db_get_exclusion_id_size() - 1)), er->reason, TRUE );
02508         } else {
02509           report_output_exclusion_reason( ofile, 10, er->reason, TRUE );
02510         }
02511       }
02512 
02513       fprintf( ofile, "\n" );
02514 
02515       free_safe( info, (sizeof( char* ) * info_size) );
02516 
02517     }
02518 
02519   }
02520 
02521   PROFILE_END;
02522 
02523 }

static void combination_multi_expr_calc ( expression exp,
int *  ulid,
bool  ul,
bool  excluded,
unsigned int *  hit,
unsigned int *  excludes,
unsigned int *  total 
) [static]

Parses the specified expression tree, calculating the hit and total values of all sub-expressions that are the same operation types as their left children.

Parameters:
exp Pointer to expression to calculate hit and total of multi-expression subtrees
ulid Pointer to current underline ID
ul If TRUE, parent expressions were found to be missing so force the underline
excluded If TRUE, parent expressions were found to be excluded
hit Pointer to value containing number of hit expression values in this expression
excludes Pointer to value containing number of excluded combinational expressions
total Pointer to value containing total number of expression values in this expression

References combination_does_multi_exp_need_ul(), ESUPPL_EXCLUDED, ESUPPL_IS_ROOT, ESUPPL_WAS_FALSE, ESUPPL_WAS_TRUE, esuppl_u::eval_00, esuppl_u::eval_11, EXP_OP_AND, EXP_OP_LAND, expr_stmt_u::expr, expression_s::left, expression_s::op, expression_s::parent, esuppl_u::part, PROFILE, PROFILE_END, expression_s::right, expression_s::suppl, and expression_s::ulid.

Referenced by combination_get_tree_stats(), and combination_multi_vars().

00200   { PROFILE(COMBINATION_MULTI_EXPR_CALC);
00201 
00202   bool and_op;  /* Specifies if current expression is an AND or LAND operation */
00203 
00204   if( exp != NULL ) {
00205 
00206     /* Calculate this expression's exclusion */
00207     excluded |= ESUPPL_EXCLUDED( exp->suppl );
00208 
00209     /* Figure out if this is an AND/LAND operation */
00210     and_op = (exp->op == EXP_OP_AND) || (exp->op == EXP_OP_LAND);
00211 
00212     /* Decide if our expression requires that this sequence gets underlined */
00213     if( !ul ) {
00214       ul = combination_does_multi_exp_need_ul( exp );
00215     }
00216 
00217     if( (exp->left != NULL) && (exp->op != exp->left->op) ) {
00218       if( excluded ) {
00219         (*hit)++;
00220         (*excludes)++;
00221       } else {
00222         if( and_op ) {
00223           *hit += ESUPPL_WAS_FALSE( exp->left->suppl );
00224         } else {
00225           *hit += ESUPPL_WAS_TRUE( exp->left->suppl );
00226         }
00227       }
00228       if( (exp->left->ulid == -1) && ul ) { 
00229         exp->left->ulid = *ulid;
00230         (*ulid)++;
00231       }
00232       (*total)++;
00233     } else {
00234       combination_multi_expr_calc( exp->left, ulid, ul, excluded, hit, excludes, total );
00235     }
00236 
00237     if( (exp->right != NULL) && (exp->op != exp->right->op) ) {
00238       if( excluded ) {
00239         (*hit)++;
00240         (*excludes)++;
00241       } else {
00242         if( and_op ) {
00243           *hit += ESUPPL_WAS_FALSE( exp->right->suppl );
00244         } else {
00245           *hit += ESUPPL_WAS_TRUE( exp->right->suppl );
00246         }
00247       }
00248       if( (exp->right->ulid == -1) && ul ) {
00249         exp->right->ulid = *ulid;
00250         (*ulid)++;
00251       }
00252       (*total)++;
00253     } else {
00254       combination_multi_expr_calc( exp->right, ulid, ul, excluded, hit, excludes, total );
00255     }
00256 
00257     if( (ESUPPL_IS_ROOT( exp->suppl ) == 1) || (exp->op != exp->parent->expr->op) ) {
00258       if( excluded ) {
00259         (*hit)++;
00260         (*excludes)++;
00261       } else {
00262         if( and_op ) {
00263           *hit += exp->suppl.part.eval_11;
00264         } else {
00265           *hit += exp->suppl.part.eval_00;
00266         }
00267       }
00268       if( (exp->ulid == -1) && ul ) {
00269         exp->ulid = *ulid;
00270         (*ulid)++;
00271       }
00272       (*total)++;
00273     }
00274 
00275   }
00276 
00277   PROFILE_END;
00278 
00279 }

static void combination_multi_expr_output ( char **  info,
char *  line1,
char *  line2,
char *  line3 
) [static]

Stores the information from line1, line2 and line3 in the string array info.

Parameters:
info Pointer string to output report contents to
line1 First line of multi-variable expression output
line2 Second line of multi-variable expression output
line3 Third line of multi-variable expression output

References db_get_exclusion_id_size(), flag_output_exclusion_ids, gen_char_string(), line_width, malloc_safe, PROFILE, and PROFILE_END.

Referenced by combination_multi_vars().

02190   { PROFILE(COMBINATION_MULTI_EXPR_OUTPUT);
02191 
02192   int          start      = 0;
02193   int          i;
02194   int          len        = strlen( line1 );
02195   int          info_index = 2;
02196   unsigned int eid_size;
02197 
02198   if( flag_output_exclusion_ids ) {
02199     eid_size = db_get_exclusion_id_size();
02200   }
02201 
02202   for( i=0; i<len; i++ ) {
02203 
02204     if( (i + 1) == len ) {
02205 
02206       unsigned int rv;
02207       unsigned int slen1 = strlen( line1 + start ) + 9;
02208       unsigned int slen2 = strlen( line2 + start ) + 9;
02209       unsigned int slen3 = strlen( line3 + start ) + 9;
02210 
02211       if( flag_output_exclusion_ids ) {
02212         slen1 += (eid_size - 1) + 4;
02213         slen2 += (eid_size - 1) + 4;
02214         slen3 += (eid_size - 1) + 4;
02215       }
02216 
02217       info[info_index+0] = (char*)malloc_safe( slen1 );
02218       info[info_index+1] = (char*)malloc_safe( slen2 );
02219       info[info_index+2] = (char*)malloc_safe( slen3 );
02220 
02221       if( flag_output_exclusion_ids ) {
02222         char tmp[30];
02223         gen_char_string( tmp, ' ', ((eid_size - 1) + 4) );
02224         rv = snprintf( info[info_index+0], slen1, "%s        %s", tmp, (line1 + start) );
02225         assert( rv < slen1 );
02226         rv = snprintf( info[info_index+1], slen2, "%s        %s", tmp, (line2 + start) );
02227         assert( rv < slen2 );
02228         rv = snprintf( info[info_index+2], slen3, "%s        %s", tmp, (line3 + start) );
02229         assert( rv < slen3 );
02230       } else {
02231         rv = snprintf( info[info_index+0], slen1, "        %s", (line1 + start) );
02232         assert( rv < slen1 );
02233         rv = snprintf( info[info_index+1], slen2, "        %s", (line2 + start) );
02234         assert( rv < slen2 );
02235         rv = snprintf( info[info_index+2], slen3, "        %s", (line3 + start) );
02236         assert( rv < slen3 );
02237       }
02238 
02239     } else if( (line1[i] == '|') && ((i - start) >= line_width) ) {
02240 
02241       unsigned int rv;
02242       unsigned int slen1;
02243       unsigned int slen2;
02244       unsigned int slen3;
02245 
02246       line1[i] = '\0';
02247       line2[i] = '\0';
02248       line3[i] = '\0';
02249 
02250       slen1 = strlen( line1 + start ) + 10;
02251       slen2 = strlen( line2 + start ) + 10;
02252       slen3 = strlen( line3 + start ) + 11;
02253 
02254       if( flag_output_exclusion_ids ) {
02255         slen1 += (eid_size - 1) + 4;
02256         slen2 += (eid_size - 1) + 4;
02257         slen3 += (eid_size - 1) + 4;
02258       }
02259 
02260       info[info_index+0] = (char*)malloc_safe( slen1 );
02261       info[info_index+1] = (char*)malloc_safe( slen2 );
02262       info[info_index+2] = (char*)malloc_safe( slen3 );
02263 
02264       if( flag_output_exclusion_ids ) {
02265         char tmp[30];
02266         gen_char_string( tmp, ' ', ((eid_size - 1) + 4) );
02267         rv = snprintf( info[info_index+0], slen1, "%s        %s|",   tmp, (line1 + start) );
02268         assert( rv < slen1 );
02269         rv = snprintf( info[info_index+1], slen2, "%s        %s|",   tmp, (line2 + start) );
02270         assert( rv < slen2 );
02271         rv = snprintf( info[info_index+2], slen3, "%s        %s \n", tmp, (line3 + start) );
02272         assert( rv < slen3 );
02273       } else {
02274         rv = snprintf( info[info_index+0], slen1, "        %s|",   (line1 + start) );
02275         assert( rv < slen1 );
02276         rv = snprintf( info[info_index+1], slen2, "        %s|",   (line2 + start) );
02277         assert( rv < slen2 );
02278         rv = snprintf( info[info_index+2], slen3, "        %s \n", (line3 + start) );
02279         assert( rv < slen3 );
02280       }
02281 
02282       start       = i + 1;
02283       info_index += 3;
02284 
02285     }
02286 
02287   }
02288 
02289   PROFILE_END;
02290 
02291 }

static int combination_multi_expr_output_length ( char *  line1  )  [static]
Returns:
Returns the number of lines required to store the multi-variable expression output contained in line1, line2, and line3.
Parameters:
line1 First line of multi-variable expression output

References line_width, PROFILE, and PROFILE_END.

Referenced by combination_multi_vars().

02160   { PROFILE(COMBINATION_MULTI_EXPR_OUTPUT_LENGTH);
02161 
02162   int start  = 0;
02163   int i;
02164   int len    = strlen( line1 );
02165   int length = 0;
02166 
02167   for( i=0; i<len; i++ ) {
02168     if( (i + 1) == len ) {
02169       length += 3;
02170     } else if( (line1[i] == '|') && ((i - start) >= line_width) ) {
02171       length += 3;
02172       start   = i + 1;
02173     }
02174   }
02175 
02176   PROFILE_END;
02177 
02178   return( length );
02179 
02180 }

static void combination_multi_var_exprs ( char **  line1,
char **  line2,
char **  line3,
expression exp 
) [static]

Creates the verbose report information for a multi-variable expression, storing its output in the line1, line2, and line3 strings.

Parameters:
line1 Pointer to first line of multi-variable expression output
line2 Pointer to second line of multi-variable expression output
line3 Pointer to third line of multi-variable expression output
exp Pointer to current expression to output

References ESUPPL_IS_ROOT, ESUPPL_WAS_FALSE, ESUPPL_WAS_TRUE, esuppl_u::eval_00, esuppl_u::eval_11, EXP_OP_AND, EXP_OP_LAND, expr_stmt_u::expr, free_safe, expression_s::left, malloc_safe, expression_s::op, expression_s::parent, esuppl_u::part, PROFILE, PROFILE_END, expression_s::right, expression_s::suppl, and expression_s::ulid.

Referenced by combination_multi_vars().

01985   { PROFILE(COMBINATION_MULTI_VAR_EXPRS);
01986 
01987   char*        left_line1  = NULL;
01988   char*        left_line2  = NULL;
01989   char*        left_line3  = NULL;
01990   char*        right_line1 = NULL;
01991   char*        right_line2 = NULL;
01992   char*        right_line3 = NULL;
01993   char         curr_id_str[20];
01994   unsigned int curr_id_str_len;
01995   unsigned int i;
01996   bool         and_op;
01997   unsigned int rv;                  /* Return value from snprintf calls */
01998 
01999   if( exp != NULL ) {
02000 
02001     and_op = (exp->op == EXP_OP_AND) || (exp->op == EXP_OP_LAND);
02002 
02003     /* If we have hit the left-most expression, start creating string here */
02004     if( (exp->left != NULL) && (exp->op != exp->left->op) ) {
02005 
02006       assert( exp->left->ulid != -1 );
02007       rv = snprintf( curr_id_str, 20, "%d", exp->left->ulid );
02008       assert( rv < 20 );
02009       curr_id_str_len = strlen( curr_id_str );
02010       left_line1 = (char*)malloc_safe( curr_id_str_len + 4 );
02011       left_line2 = (char*)malloc_safe( curr_id_str_len + 4 );
02012       left_line3 = (char*)malloc_safe( curr_id_str_len + 4 );
02013       rv = snprintf( left_line1, (curr_id_str_len + 4), " %s |", curr_id_str );
02014       assert( rv < (curr_id_str_len + 4) );
02015       for( i=0; i<(curr_id_str_len-1); i++ ) {
02016         curr_id_str[i] = '=';
02017       }
02018       curr_id_str[i] = '\0'; 
02019       if( and_op ) { 
02020         rv = snprintf( left_line2, (curr_id_str_len + 4), "=0%s=|", curr_id_str );
02021         assert( rv < (curr_id_str_len + 4) );
02022       } else { 
02023         rv = snprintf( left_line2, (curr_id_str_len + 4), "=1%s=|", curr_id_str );
02024         assert( rv < (curr_id_str_len + 4) );
02025       }
02026       for( i=0; i<(curr_id_str_len - 1); i++ ) {
02027         curr_id_str[i] = ' ';
02028       }
02029       curr_id_str[i] = '\0';
02030       if( and_op ) {
02031         rv = snprintf( left_line3, (curr_id_str_len + 4), " %c%s  ", ((ESUPPL_WAS_FALSE( exp->left->suppl ) == 1) ? ' ' : '*'), curr_id_str );
02032         assert( rv < (curr_id_str_len + 4) );
02033       } else {
02034         rv = snprintf( left_line3, (curr_id_str_len + 4), " %c%s  ", ((ESUPPL_WAS_TRUE( exp->left->suppl )  == 1) ? ' ' : '*'), curr_id_str );
02035         assert( rv < (curr_id_str_len + 4) );
02036       }
02037 
02038     } else {
02039 
02040       combination_multi_var_exprs( &left_line1, &left_line2, &left_line3, exp->left );
02041 
02042     }
02043 
02044     /* Get right-side information */
02045     if( (exp->right != NULL) && (exp->op != exp->right->op) ) {
02046 
02047       assert( exp->right->ulid != -1 );
02048       rv = snprintf( curr_id_str, 20, "%d", exp->right->ulid );
02049       assert( rv < 20 );
02050       curr_id_str_len = strlen( curr_id_str );
02051       right_line1 = (char*)malloc_safe( curr_id_str_len + 4 );
02052       right_line2 = (char*)malloc_safe( curr_id_str_len + 4 );
02053       right_line3 = (char*)malloc_safe( curr_id_str_len + 4 );
02054       rv = snprintf( right_line1, (curr_id_str_len + 4), " %s |", curr_id_str );
02055       assert( rv < (curr_id_str_len + 4) );
02056       for( i=0; i<(curr_id_str_len-1); i++ ) {
02057         curr_id_str[i] = '=';
02058       }
02059       curr_id_str[i] = '\0';
02060       if( and_op ) {
02061         rv = snprintf( right_line2, (curr_id_str_len + 4), "=0%s=|", curr_id_str );
02062         assert( rv < (curr_id_str_len + 4) );
02063       } else {
02064         rv = snprintf( right_line2, (curr_id_str_len + 4), "=1%s=|", curr_id_str );
02065         assert( rv < (curr_id_str_len + 4) );
02066       }
02067       for( i=0; i<(curr_id_str_len - 1); i++ ) {
02068         curr_id_str[i] = ' ';
02069       }
02070       curr_id_str[i] = '\0';
02071       if( and_op ) {
02072         rv = snprintf( right_line3, (curr_id_str_len + 4), " %c%s  ", ((ESUPPL_WAS_FALSE( exp->right->suppl ) == 1) ? ' ' : '*'), curr_id_str );
02073         assert( rv < (curr_id_str_len + 4) );
02074       } else {
02075         rv = snprintf( right_line3, (curr_id_str_len + 4), " %c%s  ", ((ESUPPL_WAS_TRUE( exp->right->suppl )  == 1) ? ' ' : '*'), curr_id_str );
02076         assert( rv < (curr_id_str_len + 4) );
02077       }
02078 
02079     } else {
02080 
02081       combination_multi_var_exprs( &right_line1, &right_line2, &right_line3, exp->right );
02082 
02083     }
02084 
02085     if( left_line1 != NULL ) {
02086       if( right_line1 != NULL ) {
02087         unsigned int slen1 = strlen( left_line1 ) + strlen( right_line1 ) + 1;
02088         unsigned int slen2 = strlen( left_line2 ) + strlen( right_line2 ) + 1;
02089         unsigned int slen3 = strlen( left_line3 ) + strlen( right_line3 ) + 1;
02090         *line1 = (char*)malloc_safe( slen1 );
02091         *line2 = (char*)malloc_safe( slen2 );
02092         *line3 = (char*)malloc_safe( slen3 );
02093         rv = snprintf( *line1, slen1, "%s%s", left_line1, right_line1 );
02094         assert( rv < slen1 );
02095         rv = snprintf( *line2, slen2, "%s%s", left_line2, right_line2 );
02096         assert( rv < slen2 );
02097         rv = snprintf( *line3, slen3, "%s%s", left_line3, right_line3 );
02098         assert( rv < slen3 );
02099         free_safe( left_line1, (strlen( left_line1 ) + 1) );
02100         free_safe( left_line2, (strlen( left_line2 ) + 1) );
02101         free_safe( left_line3, (strlen( left_line3 ) + 1) );
02102         free_safe( right_line1, (strlen( right_line1 ) + 1) );
02103         free_safe( right_line2, (strlen( right_line2 ) + 1) );
02104         free_safe( right_line3, (strlen( right_line3 ) + 1) );
02105       } else {
02106         *line1 = left_line1;
02107         *line2 = left_line2;
02108         *line3 = left_line3;
02109       }
02110     } else {
02111       assert( right_line1 != NULL );
02112       *line1 = right_line1;
02113       *line2 = right_line2;
02114       *line3 = right_line3;
02115     }
02116 
02117     /* If we are the root, output all value */
02118     if( (ESUPPL_IS_ROOT( exp->suppl ) == 1) || (exp->op != exp->parent->expr->op) ) {
02119       unsigned int slen1 = strlen( *line1 ) + 5;
02120       unsigned int slen2 = strlen( *line2 ) + 6;
02121       unsigned int slen3 = strlen( *line3 ) + 6;
02122       left_line1 = *line1;
02123       left_line2 = *line2;
02124       left_line3 = *line3;
02125       *line1     = (char*)malloc_safe( slen1 );
02126       *line2     = (char*)malloc_safe( slen2 );
02127       *line3     = (char*)malloc_safe( slen3 );
02128       if( and_op ) {
02129         rv = snprintf( *line1, slen1, "%s All",   left_line1 );
02130         assert( rv < slen1 );
02131         rv = snprintf( *line2, slen2, "%s==1==",  left_line2 );
02132         assert( rv < slen2 );
02133         rv = snprintf( *line3, slen3, "%s  %c  ", left_line3, ((exp->suppl.part.eval_11 == 1) ? ' ' : '*') );
02134         assert( rv < slen3 );
02135       } else {
02136         rv = snprintf( *line1, slen1, "%s All",   left_line1 );
02137         assert( rv < slen1 );
02138         rv = snprintf( *line2, slen2, "%s==0==",  left_line2 );
02139         assert( rv < slen2 );
02140         rv = snprintf( *line3, slen3, "%s  %c  ", left_line3, ((exp->suppl.part.eval_00 == 1) ? ' ' : '*') );
02141         assert( rv < slen3 );
02142       }
02143       free_safe( left_line1, (strlen( left_line1 ) + 1) );
02144       free_safe( left_line2, (strlen( left_line2 ) + 1) );
02145       free_safe( left_line3, (strlen( left_line3 ) + 1) );
02146     }
02147 
02148   }
02149 
02150   PROFILE_END;
02151 
02152 }

static void combination_multi_vars ( char ***  info,
int *  info_size,
expression exp,
bool  show_excluded 
) [static]

Displays the missed combinational sequences for the specified expression to the specified output stream in tabular form.

Parameters:
info Pointer to character array containing coverage information to output
info_size Pointer to integer containing number of valid array entries in info
exp Pointer to top-level AND/OR expression to evaluate
show_excluded Set to TRUE to output expression if it is excluded

References combination_multi_expr_calc(), combination_multi_expr_output(), combination_multi_expr_output_length(), combination_multi_var_exprs(), db_gen_exclusion_id(), db_get_exclusion_id_size(), ESUPPL_EXCLUDED, EXP_OP_AND, EXP_OP_LAND, EXP_OP_LOR, EXP_OP_OR, FALSE, flag_output_exclusion_ids, free_safe, gen_char_string(), expression_s::id, malloc_safe, expression_s::op, PROFILE, PROFILE_END, strdup_safe, expression_s::suppl, and expression_s::ulid.

Referenced by combination_get_missed_expr().

02302   { PROFILE(COMBINATION_MULTI_VARS);
02303 
02304   int          ulid      = 1;
02305   unsigned int hit       = 0;
02306   unsigned int excluded  = 0;
02307   unsigned int total     = 0;
02308   char*        line1     = NULL;
02309   char*        line2     = NULL;
02310   char*        line3     = NULL;
02311   char         tmp[20];
02312   unsigned int line_size = 1;
02313 
02314   /* Only output this expression if we are missing coverage. */
02315   if( exp->ulid != -1 ) {
02316 
02317     /* Calculate hit and total values for this sub-expression */
02318     combination_multi_expr_calc( exp, &ulid, FALSE, FALSE, &hit, &excluded, &total );
02319 
02320     if( ((hit != total) && !ESUPPL_EXCLUDED( exp->suppl )) ||
02321         (ESUPPL_EXCLUDED( exp->suppl ) && show_excluded) ) {
02322 
02323       unsigned int rv;
02324       unsigned int slen1;
02325       unsigned int slen2;
02326       unsigned int slen3;
02327       unsigned int eid_size;
02328 
02329       if( flag_output_exclusion_ids ) {
02330         eid_size = db_get_exclusion_id_size();
02331       }
02332 
02333       /* Gather report output for this expression */
02334       combination_multi_var_exprs( &line1, &line2, &line3, exp );
02335 
02336       /* Get the lengths of the original string lengths -- these strings will be possibly altered by combination_multi_expr_output */
02337       slen1 = strlen( line1 ) + 1;
02338       slen2 = strlen( line2 ) + 1;
02339       slen3 = strlen( line3 ) + 1;
02340 
02341       /* Calculate the array needed to store the output information and allocate this memory */
02342       *info_size = combination_multi_expr_output_length( line1 ) + 2;
02343       *info      = (char**)malloc_safe( sizeof( char* ) * (*info_size) );
02344 
02345       /* Calculate needed line length */
02346       rv = snprintf( tmp, 20, "%u", hit );
02347       assert( rv < 20 );
02348       line_size += strlen( tmp );
02349       rv = snprintf( tmp, 20, "%u", total );
02350       assert( rv < 20 );
02351       line_size += strlen( tmp );
02352       rv = snprintf( tmp, 20, "%d", exp->ulid );
02353       assert( rv < 20 );
02354       line_size += strlen( tmp );
02355       line_size += 25;                   /* Number of additional characters in line below */
02356       if( flag_output_exclusion_ids ) {
02357         line_size += (eid_size - 1) + 4;
02358       }
02359       (*info)[0] = (char*)malloc_safe( line_size );
02360     
02361       if( flag_output_exclusion_ids ) {
02362         char* tmp;
02363         char  spaces[30];
02364         int   size;
02365         rv = snprintf( (*info)[0], line_size, "        (%s)  Expression %d   (%u/%u)", db_gen_exclusion_id( 'E', exp->id ), exp->ulid, hit, total );
02366         assert( rv < line_size );
02367         switch( exp->op ) {
02368           case EXP_OP_AND  :  tmp = strdup_safe( "        ^^^^^^^^^^^^^ - &" );   break;
02369           case EXP_OP_OR   :  tmp = strdup_safe( "        ^^^^^^^^^^^^^ - |" );   break;
02370           case EXP_OP_LAND :  tmp = strdup_safe( "        ^^^^^^^^^^^^^ - &&" );  break;
02371           case EXP_OP_LOR  :  tmp = strdup_safe( "        ^^^^^^^^^^^^^ - ||" );  break;
02372           default          :  assert( 0 );  break;
02373         }
02374         size = strlen( tmp ) + (eid_size - 1) + 5;
02375         gen_char_string( spaces, ' ', (eid_size - 1) );
02376         (*info)[1] = (char*)malloc_safe( size );
02377         rv = snprintf( (*info)[1], size, "%s    %s", spaces, tmp );
02378         assert( rv < size );
02379         free_safe( tmp, (strlen( tmp ) + 1) );
02380       } else {
02381         rv = snprintf( (*info)[0], line_size, "        Expression %d   (%u/%u)", exp->ulid, hit, total );
02382         assert( rv < line_size );
02383         switch( exp->op ) {
02384           case EXP_OP_AND  :  (*info)[1] = strdup_safe( "        ^^^^^^^^^^^^^ - &" );   break;
02385           case EXP_OP_OR   :  (*info)[1] = strdup_safe( "        ^^^^^^^^^^^^^ - |" );   break;
02386           case EXP_OP_LAND :  (*info)[1] = strdup_safe( "        ^^^^^^^^^^^^^ - &&" );  break;
02387           case EXP_OP_LOR  :  (*info)[1] = strdup_safe( "        ^^^^^^^^^^^^^ - ||" );  break;
02388           default          :  assert( 0 );  break;
02389         }
02390       }
02391 
02392       /* Output the lines paying attention to the current line width */
02393       combination_multi_expr_output( *info, line1, line2, line3 );
02394 
02395       free_safe( line1, slen1 );
02396       free_safe( line2, slen2 );
02397       free_safe( line3, slen3 );
02398 
02399     }
02400 
02401   }
02402 
02403   PROFILE_END;
02404 
02405 }

static void combination_output_expr ( expression expr,
unsigned int  curr_depth,
int *  any_missed,
int *  any_measurable,
int *  any_excluded,
int *  all_excluded 
) [static]

Recursively traverses specified expression tree, returning TRUE if an expression is found that has not received 100% coverage for combinational logic.

Parameters:
expr Pointer to root of expression tree to search
curr_depth Specifies current depth of expression tree
any_missed Pointer to indicate if any subexpressions were missed in the specified expression
any_measurable Pointer to indicate if any subexpressions were measurable in the specified expression
any_excluded Pointer to indicate if any subexpressions were excluded
all_excluded Pointer to indicate if all subexpressions that can be excluded are

References esuppl_u::comb_cntd, combination_calc_depth(), ESUPPL_EXCLUDED, ESUPPL_WAS_COMB_COUNTED, EXPR_IS_MEASURABLE, expression_is_static_only(), FALSE, expression_s::left, esuppl_u::part, PROFILE, PROFILE_END, report_comb_depth, REPORT_DETAILED, REPORT_VERBOSE, expression_s::right, expression_s::suppl, TRUE, and expression_s::ulid.

Referenced by combination_collect(), and combination_display_verbose().

02537   { PROFILE(COMBINATION_OUTPUT_EXPR);
02538 
02539   if( (expr != NULL) && (ESUPPL_WAS_COMB_COUNTED( expr->suppl ) == 1) ) {
02540 
02541     expr->suppl.part.comb_cntd = 0;
02542 
02543     combination_output_expr( expr->right, combination_calc_depth( expr, curr_depth, FALSE ), any_missed, any_measurable, any_excluded, all_excluded );
02544     combination_output_expr( expr->left,  combination_calc_depth( expr, curr_depth, TRUE ),  any_missed, any_measurable, any_excluded, all_excluded );
02545 
02546     if( ((report_comb_depth == REPORT_DETAILED) && (curr_depth <= report_comb_depth)) ||
02547          (report_comb_depth == REPORT_VERBOSE) ) {
02548  
02549       if( expr->ulid != -1 ) {
02550         *any_missed = 1;
02551       }
02552       if( (EXPR_IS_MEASURABLE( expr ) == 1) && !expression_is_static_only( expr ) ) {
02553         if( ESUPPL_EXCLUDED( expr->suppl ) == 0 ) {
02554           *any_measurable = 1;
02555           if( expr->ulid != -1 ) {
02556             *all_excluded = 0;
02557           }
02558         } else {
02559           *any_excluded = 1;
02560           *all_excluded = 1;
02561         }
02562       }
02563 
02564     }
02565 
02566   }
02567 
02568   PROFILE_END;
02569 
02570 }

static void combination_parenthesize ( bool  parenthesis,
const char *  pre_code_format,
char **  new_code_format,
unsigned int *  code_format_size 
) [static]

Parenthesizes the code format and code format size variables.

References PROFILE, and PROFILE_END.

Referenced by combination_underline_tree().

00856   { PROFILE(COMBINATION_PARENTHESIZE);
00857 
00858   if( parenthesis ) {
00859 
00860     /* Create the new code format string with spacing for the parenthesis */
00861     unsigned int rv = snprintf( *new_code_format, 300, " %s ", pre_code_format );
00862     assert( rv < 300 );
00863 
00864     /* Update the code format size */
00865     *code_format_size += 2;
00866 
00867   } else {
00868 
00869     strcpy( *new_code_format, pre_code_format );
00870 
00871   }
00872 
00873   PROFILE_END;
00874 
00875 }

static char* combination_prep_line ( char *  line,
int  start,
int  len 
) [static]
Returns:
Returns a newly allocated string that contains the underline information for the current line. If there is no underline information to return, a value of NULL is returned.

Formats the specified underline line to line wrap according to the generated code. This function must be called after the underline lines have been calculated prior to being output to the ASCII report or the GUI.

Parameters:
line Line containing underlines that needs to be reformatted for line wrap
start Starting index in line to take underline information from
len Number of characters to use for the current line

References combination_draw_centered_line(), FALSE, free_safe, malloc_safe, PROFILE, PROFILE_END, realloc_safe, strdup_safe, and TRUE.

Referenced by combination_get_expression(), and combination_underline().

01392   { PROFILE(COMBINATION_PREP_LINE);
01393 
01394   char* str;                /* Prepared line to return */
01395   char* newstr;             /* Prepared line to return */
01396   int   str_size;           /* Allocated size of str */
01397   int   exp_id;             /* Expression ID of current line */
01398   int   chars_read;         /* Number of characters read from sscanf function */
01399   int   i;                  /* Loop iterator */
01400   int   curr_index;         /* Index current character in str to set */
01401   bool  line_ip   = FALSE;  /* Specifies if a line is currently in progress */
01402   bool  line_seen = FALSE;  /* Specifies that a line has been seen for this line */
01403   int   start_ul  = 0;      /* Index of starting underline */
01404 
01405   /* Allocate memory for string to return */
01406   str_size = len + 2;
01407   str      = (char*)malloc_safe( str_size );
01408 
01409   i          = 0;
01410   curr_index = 0;
01411 
01412   while( i < (start + len) ) {
01413    
01414     if( *(line + i) == '|' ) {
01415       if( i >= start ) {
01416         line_seen = TRUE;
01417       }
01418       if( !line_ip ) {
01419         line_ip  = TRUE;
01420         start_ul = i;
01421         if( sscanf( (line + i + 1), "%d%n", &exp_id, &chars_read ) != 1 ) {
01422           assert( 0 == 1 );
01423         } else {
01424           i += chars_read;
01425         }
01426       } else {
01427         line_ip = FALSE;
01428         if( i >= start ) {
01429           if( start_ul >= start ) {
01430             combination_draw_centered_line( (str + curr_index), ((i - start_ul) + 1), exp_id, TRUE,  TRUE );
01431             curr_index += (i - start_ul) + 1;
01432           } else {
01433             combination_draw_centered_line( (str + curr_index), ((i - start) + 1), exp_id, FALSE, TRUE );
01434             curr_index += (i - start) + 1;
01435           }
01436         }
01437       }
01438     } else {
01439       if( i >= start ) {
01440         if( *(line + i) == '-' ) {
01441           line_seen = TRUE;
01442         } else {
01443           str[curr_index] = *(line + i);
01444           curr_index++;
01445         }
01446       }
01447     }
01448 
01449     i++;
01450 
01451   }
01452 
01453   if( line_ip ) {
01454     /* If our pointer exceeded the allotted size, resize the str to fit */
01455     if( i > (start + len) ) {
01456       str      = (char*)realloc_safe( str, str_size, (len + 2 + (i - (start + len))) );
01457       str_size = (len + 2 + (i - (start + len)));
01458     }
01459     if( start_ul >= start ) {
01460       combination_draw_centered_line( (str + curr_index), ((i - start_ul) + 1), exp_id, TRUE,  FALSE );
01461       curr_index += (i - start_ul) + 1;
01462     } else {
01463       combination_draw_centered_line( (str + curr_index), ((i - start) + 1), exp_id, FALSE, FALSE );
01464       curr_index += (i - start) + 1;
01465     }
01466   }
01467 
01468   /* If we didn't see any underlines here, return NULL */
01469   if( !line_seen ) {
01470     newstr = NULL;
01471   } else {
01472     str[curr_index] = '\0';
01473     newstr = strdup_safe( str );
01474   }
01475 
01476   /* The str may be a bit oversized, so we copied it and now free it here (where we know its allocated size) */
01477   free_safe( str, str_size );
01478 
01479   PROFILE_END;
01480 
01481   return( newstr );
01482 
01483 }

void combination_report ( FILE *  ofile,
bool  verbose 
)

Generates report output for combinational logic coverage.

Exceptions:
anonymous combination_funit_verbose combination_instance_verbose

After the design is read into the functional unit hierarchy, parses the hierarchy by functional unit, reporting the combinational logic coverage for each functional unit encountered. The parent functional unit will specify its own combinational logic coverage along with a total combinational logic coverage including its children.

Parameters:
ofile Pointer to file to output results to
verbose Specifies whether or not to provide verbose information

References combination_display_funit_summary(), combination_display_instance_summary(), combination_funit_summary(), combination_funit_verbose(), combination_instance_summary(), combination_instance_verbose(), curr_db, FALSE, funit_head, inst_link_s::inst, db_s::inst_head, funit_inst_s::name_diff, inst_link_s::next, PROFILE, PROFILE_END, report_covered, report_exclusions, report_instance, and funit_inst_s::suppl.

Referenced by report_generate().

03051   { PROFILE(COMBINATION_REPORT);
03052 
03053   bool       missed_found = FALSE;  /* If set to TRUE, indicates combinations were missed */
03054   inst_link* instl;                 /* Pointer to current instance link */
03055   int        acc_hits     = 0;      /* Accumulated number of combinations hit */
03056   int        acc_total    = 0;      /* Accumulated number of combinations in design */
03057 
03058   fprintf( ofile, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
03059   fprintf( ofile, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   COMBINATIONAL LOGIC COVERAGE RESULTS   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
03060   fprintf( ofile, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" );
03061 
03062   if( report_instance ) {
03063 
03064     fprintf( ofile, "                                                                            Logic Combinations\n" );
03065     fprintf( ofile, "Instance                                                              Hit/Miss/Total    Percent hit\n" );
03066     fprintf( ofile, "---------------------------------------------------------------------------------------------------------------------\n" );
03067 
03068     instl = db_list[curr_db]->inst_head;
03069     while( instl != NULL ) {
03070       missed_found |= combination_instance_summary( ofile, instl->inst, (instl->inst->suppl.name_diff ? "<NA>" : "*"), &acc_hits, &acc_total );
03071       instl = instl->next;
03072     }
03073     fprintf( ofile, "---------------------------------------------------------------------------------------------------------------------\n" );
03074     (void)combination_display_instance_summary( ofile, "Accumulated", acc_hits, acc_total );
03075     
03076     if( verbose && (missed_found || report_covered || report_exclusions) ) {
03077       fprintf( ofile, "---------------------------------------------------------------------------------------------------------------------\n" );
03078       instl = db_list[curr_db]->inst_head;
03079       while( instl != NULL ) {
03080         combination_instance_verbose( ofile, instl->inst, (instl->inst->suppl.name_diff ? "<NA>" : "*") );
03081         instl = instl->next;
03082       }
03083     }
03084 
03085   } else {
03086 
03087     fprintf( ofile, "                                                                            Logic Combinations\n" );
03088     fprintf( ofile, "Module/Task/Function                Filename                          Hit/Miss/Total    Percent hit\n" );
03089     fprintf( ofile, "---------------------------------------------------------------------------------------------------------------------\n" );
03090 
03091     missed_found = combination_funit_summary( ofile, db_list[curr_db]->funit_head, &acc_hits, &acc_total );
03092     fprintf( ofile, "---------------------------------------------------------------------------------------------------------------------\n" );
03093     (void)combination_display_funit_summary( ofile, "Accumulated", "", acc_hits, acc_total );
03094 
03095     if( verbose && (missed_found || report_covered || report_exclusions) ) {
03096       fprintf( ofile, "---------------------------------------------------------------------------------------------------------------------\n" );
03097       combination_funit_verbose( ofile, db_list[curr_db]->funit_head );
03098     }
03099 
03100   }
03101 
03102   fprintf( ofile, "\n\n" );
03103 
03104   PROFILE_END;
03105 
03106 }

void combination_reset_counted_expr_tree ( expression exp  ) 

Resets combination counted bits in expression tree.

Recursively iterates through specified expression tree, clearing the combination counted bit in the supplemental field of each child expression. This functions needs to get called whenever the excluded bit of an expression is changed.

Parameters:
exp Pointer to expression tree to reset

References esuppl_u::comb_cntd, combination_reset_counted_expr_tree(), expression_s::left, esuppl_u::part, PROFILE, PROFILE_END, expression_s::right, and expression_s::suppl.

Referenced by combination_reset_counted_expr_tree(), exclude_expr_assign_and_recalc(), and rank_gather_comp_cdd_cov().

00509   { PROFILE(COMBINATION_RESET_COUNTED_EXPR_TREE);
00510 
00511   if( exp != NULL ) {
00512 
00513     exp->suppl.part.comb_cntd = 0;
00514 
00515     combination_reset_counted_expr_tree( exp->left );
00516     combination_reset_counted_expr_tree( exp->right );
00517 
00518   }
00519 
00520   PROFILE_END;
00521 
00522 }

static void combination_reset_counted_exprs ( func_unit funit  )  [static]

Iterates through specified expression list, setting the combination counted bit in the supplemental field of each expression. This function needs to get called whenever a new module is picked by the GUI.

Parameters:
funit Pointer to functional unit to reset

References esuppl_u::comb_cntd, exp_link_s::exp, func_unit_s::exp_head, funit_link_s::funit, funit_is_unnamed(), funit_link_s::next, exp_link_s::next, esuppl_u::part, PROFILE, PROFILE_END, expression_s::suppl, and func_unit_s::tf_head.

Referenced by combination_collect(), combination_funit_verbose(), and combination_instance_verbose().

00475   { PROFILE(COMBINATION_RESET_COUNTED_EXPRS);
00476 
00477   exp_link*   expl;   /* Pointer to current expression list */
00478   funit_link* child;  /* Pointer to current child functional unit */
00479 
00480   assert( funit != NULL );
00481 
00482   /* Reset the comb_cntd bit in all expressions for the current functional unit */
00483   expl = funit->exp_head;
00484   while( expl != NULL ) {
00485     expl->exp->suppl.part.comb_cntd = 1;
00486     expl = expl->next;
00487   }
00488 
00489   /* Do the same for all children functional units that are unnamed */
00490   child = funit->tf_head;
00491   while( child != NULL ) {
00492     if( funit_is_unnamed( child->funit ) ) {
00493       combination_reset_counted_exprs( child->funit );
00494     }
00495     child = child->next;
00496   }
00497 
00498   PROFILE_END;
00499 
00500 }

static void combination_two_vars ( char ***  info,
int *  info_size,
expression exp,
bool  show_excluded 
) [static]

Displays the missed combinational sequences for the specified expression to the specified output stream in tabular form.

Parameters:
info Pointer to array of strings that will contain the coverage information for this expression
info_size Pointer to integer containing number of elements in info array
exp Pointer to expression to evaluate
show_excluded If set to TRUE, displays the expression if it has been excluded

References AND_COMB, db_gen_exclusion_id(), db_get_exclusion_id_size(), ESUPPL_EXCLUDED, ESUPPL_WAS_FALSE, ESUPPL_WAS_TRUE, esuppl_u::eval_00, esuppl_u::eval_01, esuppl_u::eval_10, esuppl_u::eval_11, flag_output_exclusion_ids, gen_char_string(), expression_s::id, exp_info_s::is_comb, expression_s::left, malloc_safe, expression_s::op, exp_info_s::op_str, OR_COMB, esuppl_u::part, PROFILE, PROFILE_END, report_bitwise, expression_s::right, expression_s::suppl, exp_info_s::suppl, expression_s::ulid, expression_s::value, vector_get_eval_a(), vector_get_eval_abc_count(), vector_get_eval_abcd_count(), vector_get_eval_b(), vector_get_eval_c(), vector_get_eval_d(), and vector_s::width.

Referenced by combination_get_missed_expr().

01742   { PROFILE(COMBINATION_TWO_VARS);
01743 
01744   int          hit;                               /* Number of combinations hit for this expression */
01745   int          total;                             /* Total number of combinations for this expression */
01746   char         tmp[20];                           /* Temporary string used for calculating line width */
01747   unsigned int length;                            /* Specifies the length of the current line */
01748   char*        op = exp_op_info[exp->op].op_str;  /* Operation string */
01749   int          lines;                             /* Specifies the number of lines needed to output this vector */
01750   unsigned int rv;                                /* Return value from snprintf calls */
01751 
01752   assert( exp != NULL );
01753 
01754   /* Verify that left child expression is valid for this operation */
01755   assert( exp->left != NULL );
01756 
01757   /* Verify that right child expression is valid for this operation */
01758   assert( exp->right != NULL );
01759 
01760   /* Get hit information */
01761   if( exp_op_info[exp->op].suppl.is_comb == AND_COMB ) {
01762     if( report_bitwise && (exp->value->width > 1) ) {
01763       lines = exp->value->width + 2;
01764       total = (3 * exp->value->width);
01765       hit   = vector_get_eval_abc_count( exp->value );
01766     } else {
01767       lines = 1;
01768       total = 3;
01769       hit   = ESUPPL_WAS_FALSE( exp->left->suppl ) + ESUPPL_WAS_FALSE( exp->right->suppl ) + exp->suppl.part.eval_11;
01770     }
01771   } else if( exp_op_info[exp->op].suppl.is_comb == OR_COMB ) {
01772     if( report_bitwise && (exp->value->width > 1) ) {
01773       lines = exp->value->width + 2;
01774       total = (3 * exp->value->width);
01775       hit   = vector_get_eval_abc_count( exp->value );
01776     } else {
01777       lines = 1;
01778       total = 3;
01779       hit   = ESUPPL_WAS_TRUE( exp->left->suppl ) + ESUPPL_WAS_TRUE( exp->right->suppl ) + exp->suppl.part.eval_00;
01780     }
01781   } else {
01782     if( report_bitwise && (exp->value->width > 1) ) {
01783       lines = exp->value->width + 2;
01784       total = (4 * exp->value->width);
01785       hit   = vector_get_eval_abcd_count( exp->value );
01786     } else {
01787       lines = 1;
01788       total = 4;
01789       hit   = exp->suppl.part.eval_00 +
01790               exp->suppl.part.eval_01 +
01791               exp->suppl.part.eval_10 +
01792               exp->suppl.part.eval_11;
01793     }
01794   }
01795 
01796   if( ((hit != total) && !ESUPPL_EXCLUDED( exp->suppl )) ||
01797       (ESUPPL_EXCLUDED( exp->suppl ) && show_excluded) ) {
01798 
01799     char         spaces[30];
01800     unsigned int eid_size;
01801 
01802     if( flag_output_exclusion_ids ) {
01803       eid_size = db_get_exclusion_id_size();
01804     }
01805 
01806     spaces[0] = '\0';
01807 
01808     assert( exp->ulid != -1 );
01809 
01810     /* Allocate memory for info array */
01811     *info_size = 4 + lines;
01812     *info      = (char**)malloc_safe( sizeof( char* ) * (*info_size) );
01813 
01814     /* Allocate lines and assign values */ 
01815     length = 26;
01816     rv = snprintf( tmp, 20, "%d", exp->ulid );  assert( rv < 20 );  length += strlen( tmp );
01817     rv = snprintf( tmp, 20, "%d", hit );        assert( rv < 20 );  length += strlen( tmp );
01818     rv = snprintf( tmp, 20, "%d", total );      assert( rv < 20 );  length += strlen( tmp );
01819     if( flag_output_exclusion_ids ) {
01820       length += (eid_size - 1) + 4;
01821       gen_char_string( spaces, ' ', ((eid_size - 1) + 4) );
01822     }
01823     (*info)[0] = (char*)malloc_safe( length );
01824     if( flag_output_exclusion_ids ) {
01825       rv = snprintf( (*info)[0], length, "        (%s)  Expression %d   (%d/%d)", db_gen_exclusion_id( 'E', exp->id ), exp->ulid, hit, total );
01826     } else {
01827       rv = snprintf( (*info)[0], length, "        Expression %d   (%d/%d)", exp->ulid, hit, total );
01828     }
01829     assert( rv < length );
01830 
01831     length = 25 + strlen( op ) + strlen( spaces );
01832     (*info)[1] = (char*)malloc_safe( length );
01833     rv = snprintf( (*info)[1], length, "%s        ^^^^^^^^^^^^^ - %s", spaces, op );
01834     assert( rv < length );
01835 
01836     if( exp_op_info[exp->op].suppl.is_comb == AND_COMB ) {
01837 
01838       if( report_bitwise && (exp->value->width > 1) ) {
01839 
01840         unsigned int i;
01841  
01842         length = 30 + strlen( spaces );
01843         (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s          Bit | LR | LR | LR ", spaces );  assert( rv < length );
01844         (*info)[3] = (char*)malloc_safe( length );  rv = snprintf( (*info)[3], length, "%s        ======|=0-=|=-0=|=11=", spaces );  assert( rv < length );
01845         (*info)[5] = (char*)malloc_safe( length );  rv = snprintf( (*info)[5], length, "%s        ------|----|----|----", spaces );  assert( rv < length );
01846 
01847         length = 28 + strlen( spaces );
01848         (*info)[4] = (char*)malloc_safe( length );
01849         rv = snprintf( (*info)[4], length, "%s          All | %c    %c    %c", spaces,
01850                        (ESUPPL_WAS_FALSE( exp->left->suppl )  ? ' ' : '*'),
01851                        (ESUPPL_WAS_FALSE( exp->right->suppl ) ? ' ' : '*'),
01852                        ((exp->suppl.part.eval_11 > 0) ? ' ' : '*') );
01853         assert( rv < length );
01854         for( i=0; i<exp->value->width; i++ ) {
01855           (*info)[i+6] = (char*)malloc_safe( length );
01856           rv = snprintf( (*info)[i+6], length, "%s         %4u | %c    %c    %c", spaces, i,
01857                          ((vector_get_eval_a( exp->value, i ) == 1) ? ' ' : '*'),
01858                          ((vector_get_eval_b( exp->value, i ) == 1) ? ' ' : '*'),
01859                          ((vector_get_eval_c( exp->value, i ) == 1) ? ' ' : '*') );
01860           assert( rv < length );
01861         }
01862 
01863       } else {
01864 
01865         length = 23 + strlen( spaces );
01866         (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s         LR | LR | LR ", spaces );  assert( rv < length );
01867         (*info)[3] = (char*)malloc_safe( length );  rv = snprintf( (*info)[3], length, "%s        =0-=|=-0=|=11=", spaces );  assert( rv < length );
01868 
01869         length = 21 + strlen( spaces );
01870         (*info)[4] = (char*)malloc_safe( length );
01871         rv = snprintf( (*info)[4], length, "%s         %c    %c    %c", spaces,
01872                        (ESUPPL_WAS_FALSE( exp->left->suppl )  ? ' ' : '*'),
01873                        (ESUPPL_WAS_FALSE( exp->right->suppl ) ? ' ' : '*'),
01874                        ((exp->suppl.part.eval_11 > 0) ? ' ' : '*') );
01875         assert( rv < length );
01876 
01877       }
01878 
01879     } else if( exp_op_info[exp->op].suppl.is_comb == OR_COMB ) {
01880 
01881       if( report_bitwise && (exp->value->width > 1) ) {
01882 
01883         unsigned int i;
01884 
01885         length = 30 + strlen( spaces );
01886         (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s          Bit | LR | LR | LR ", spaces );  assert( rv < length );
01887         (*info)[3] = (char*)malloc_safe( length );  rv = snprintf( (*info)[3], length, "%s        ======|=1-=|=-1=|=00=", spaces );  assert( rv < length );
01888         (*info)[5] = (char*)malloc_safe( length );  rv = snprintf( (*info)[5], length, "%s        ------|----|----|----", spaces );  assert( rv < length );
01889 
01890         length = 28 + strlen( spaces );
01891         (*info)[4] = (char*)malloc_safe( length );
01892         rv = snprintf( (*info)[4], length, "%s          All | %c    %c    %c", spaces,
01893                        (ESUPPL_WAS_TRUE( exp->left->suppl )  ? ' ' : '*'),
01894                        (ESUPPL_WAS_TRUE( exp->right->suppl ) ? ' ' : '*'),
01895                        ((exp->suppl.part.eval_00 > 0) ? ' ' : '*') );
01896         assert( rv < length );
01897         for( i=0; i<exp->value->width; i++ ) {
01898           (*info)[i+6] = (char*)malloc_safe( length );
01899           rv = snprintf( (*info)[i+6], length, "%s         %4u | %c    %c    %c", spaces, i,
01900                          ((vector_get_eval_a( exp->value, i ) == 1) ? ' ' : '*'),
01901                          ((vector_get_eval_b( exp->value, i ) == 1) ? ' ' : '*'),
01902                          ((vector_get_eval_c( exp->value, i ) == 1) ? ' ' : '*') );
01903           assert( rv < length );
01904         }
01905 
01906       } else {
01907 
01908         length = 23 + strlen( spaces );
01909         (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s         LR | LR | LR ", spaces );  assert( rv < length );
01910         (*info)[3] = (char*)malloc_safe( length );  rv = snprintf( (*info)[3], length, "%s        =1-=|=-1=|=00=", spaces );  assert( rv < length );
01911 
01912         length = 21 + strlen( spaces );
01913         (*info)[4] = (char*)malloc_safe( length );
01914         rv = snprintf( (*info)[4], length, "%s         %c    %c    %c", spaces,
01915                        (ESUPPL_WAS_TRUE( exp->left->suppl )  ? ' ' : '*'),
01916                        (ESUPPL_WAS_TRUE( exp->right->suppl ) ? ' ' : '*'),
01917                        ((exp->suppl.part.eval_00 > 0) ? ' ' : '*') );
01918         assert( rv < length );
01919 
01920       }
01921 
01922     } else {
01923 
01924       if( report_bitwise && (exp->value->width > 1) ) {
01925 
01926         unsigned int i;
01927 
01928         length = 35 + strlen( spaces );
01929         (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s          Bit | LR | LR | LR | LR ", spaces );  assert( rv < length );
01930         (*info)[3] = (char*)malloc_safe( length );  rv = snprintf( (*info)[3], length, "%s        ======|=00=|=01=|=10=|=11=", spaces );  assert( rv < length );
01931         (*info)[5] = (char*)malloc_safe( length );  rv = snprintf( (*info)[5], length, "%s        ------|----|----|----|----", spaces );  assert( rv < length );
01932 
01933         length = 33 + strlen( spaces );
01934         (*info)[4] = (char*)malloc_safe( length );
01935         rv = snprintf( (*info)[4], length, "%s          All | %c    %c    %c    %c", spaces,
01936                        ((exp->suppl.part.eval_00 == 1) ? ' ' : '*'),
01937                        ((exp->suppl.part.eval_01 == 1) ? ' ' : '*'),
01938                        ((exp->suppl.part.eval_10 == 1) ? ' ' : '*'),
01939                        ((exp->suppl.part.eval_11 == 1) ? ' ' : '*') );
01940         assert( rv < length );
01941         for( i=0; i<exp->value->width; i++ ) {
01942           (*info)[i+6] = (char*)malloc_safe( length );
01943           rv = snprintf( (*info)[i+6], length, "%s         %4u | %c    %c    %c    %c", spaces, i,
01944                          ((vector_get_eval_a( exp->value, i ) == 1) ? ' ' : '*'),
01945                          ((vector_get_eval_b( exp->value, i ) == 1) ? ' ' : '*'),
01946                          ((vector_get_eval_c( exp->value, i ) == 1) ? ' ' : '*'),
01947                          ((vector_get_eval_d( exp->value, i ) == 1) ? ' ' : '*') );
01948           assert( rv < length );
01949         }
01950 
01951       } else {
01952 
01953         length = 28 + strlen( spaces );
01954         (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s         LR | LR | LR | LR ", spaces );  assert( rv < length );
01955         (*info)[3] = (char*)malloc_safe( length );  rv = snprintf( (*info)[3], length, "%s        =00=|=01=|=10=|=11=", spaces );  assert( rv < length );
01956   
01957         length = 26 + strlen( spaces );
01958         (*info)[4] = (char*)malloc_safe( length );
01959         rv = snprintf( (*info)[4], length, "%s         %c    %c    %c    %c", spaces,
01960                        ((exp->suppl.part.eval_00 == 1) ? ' ' : '*'),
01961                        ((exp->suppl.part.eval_01 == 1) ? ' ' : '*'),
01962                        ((exp->suppl.part.eval_10 == 1) ? ' ' : '*'),
01963                        ((exp->suppl.part.eval_11 == 1) ? ' ' : '*') );
01964         assert( rv < length );
01965 
01966       }
01967 
01968     }
01969 
01970   }
01971 
01972   PROFILE_END;
01973 
01974 }

static void combination_unary ( char ***  info,
int *  info_size,
expression exp,
bool  show_excluded 
) [static]

Displays the missed unary combination(s) that keep the combination coverage for the specified expression from achieving 100% coverage.

Parameters:
info Pointer to array of strings that will contain the coverage information for this expression
info_size Pointer to integer containing number of elements in info array
exp Pointer to expression to evaluate
show_excluded Set to TRUE to output expression if it is excluded

References db_gen_exclusion_id(), db_get_exclusion_id_size(), ESUPPL_EXCLUDED, ESUPPL_WAS_FALSE, ESUPPL_WAS_TRUE, flag_output_exclusion_ids, gen_char_string(), expression_s::id, malloc_safe, expression_s::op, exp_info_s::op_str, PROFILE, PROFILE_END, report_bitwise, expression_s::suppl, expression_s::ulid, expression_s::value, vector_get_eval_a(), vector_get_eval_ab_count(), vector_get_eval_b(), and vector_s::width.

Referenced by combination_get_missed_expr().

01565   { PROFILE(COMBINATION_UNARY);
01566 
01567   int          hit = 0;                           /* Number of combinations hit for this expression */
01568   int          tot;                               /* Total number of coverage points possible */
01569   char         tmp[20];                           /* Temporary string used for sizing lines for numbers */
01570   unsigned int length;                            /* Length of the current line to allocate */
01571   char*        op = exp_op_info[exp->op].op_str;  /* Operations string */
01572   int          lines;                             /* Specifies the number of lines to allocate memory for */
01573   unsigned int rv;                                /* Return value from snprintf calls */
01574 
01575   assert( exp != NULL );
01576 
01577   /* Get hit information */
01578   if( report_bitwise && (exp->value->width > 1) ) {
01579     hit   = vector_get_eval_ab_count( exp->value );
01580     lines = exp->value->width + 2;
01581     tot   = (2 * exp->value->width);
01582   } else {
01583     lines = 1;
01584     tot   = 2;
01585     hit   = ESUPPL_WAS_FALSE( exp->suppl ) + ESUPPL_WAS_TRUE( exp->suppl );
01586   }
01587 
01588   if( ((hit != tot) && !ESUPPL_EXCLUDED( exp->suppl )) ||
01589       (ESUPPL_EXCLUDED( exp->suppl ) && show_excluded) ) {
01590 
01591     char         spaces[30];
01592     unsigned int eid_size;
01593 
01594     if( flag_output_exclusion_ids ) {
01595       eid_size = db_get_exclusion_id_size();
01596     }
01597 
01598     spaces[0] = '\0';
01599 
01600     assert( exp->ulid != -1 );
01601 
01602     /* Allocate memory for info array */
01603     *info_size = 4 + lines;
01604     *info      = (char**)malloc_safe( sizeof( char* ) * (*info_size) );
01605 
01606     /* Allocate lines and assign values */ 
01607     length = 26;
01608     rv = snprintf( tmp, 20, "%d", exp->ulid );  assert( rv < 20 );  length += strlen( tmp );
01609     rv = snprintf( tmp, 20, "%d", hit );        assert( rv < 20 );  length += strlen( tmp );
01610     rv = snprintf( tmp, 20, "%d", tot );        assert( rv < 20 );  length += strlen( tmp );
01611     if( flag_output_exclusion_ids ) {
01612       length += (eid_size - 1) + 4;
01613       gen_char_string( spaces, ' ', ((eid_size - 1) + 4) );
01614     }
01615     (*info)[0] = (char*)malloc_safe( length );
01616     if( flag_output_exclusion_ids ) {
01617       rv = snprintf( (*info)[0], length, "        (%s)  Expression %d   (%d/%d)", db_gen_exclusion_id( 'E', exp->id ), exp->ulid, hit, tot );
01618     } else {
01619       rv = snprintf( (*info)[0], length, "        Expression %d   (%d/%d)", exp->ulid, hit, tot );
01620     }
01621     assert( rv < length );
01622 
01623     length = 25 + strlen( op ) + strlen( spaces );  (*info)[1] = (char*)malloc_safe( length );
01624     rv = snprintf( (*info)[1], length, "%s        ^^^^^^^^^^^^^ - %s", spaces, op );
01625     assert( rv < length );
01626 
01627     if( report_bitwise && (exp->value->width > 1) ) {
01628 
01629       char*        tmp;
01630       unsigned int i;
01631    
01632       length = 23 + strlen( spaces );
01633       (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s          Bit | E | E ", spaces );  assert( rv < length );
01634       (*info)[3] = (char*)malloc_safe( length );  rv = snprintf( (*info)[3], length, "%s        ======|=0=|=1=", spaces );  assert( rv < length );
01635       (*info)[5] = (char*)malloc_safe( length );  rv = snprintf( (*info)[5], length, "%s        ------|---|---", spaces );  assert( rv < length );
01636 
01637       length = 22 + strlen( spaces );
01638       (*info)[4] = (char*)malloc_safe( length );
01639       rv = snprintf( (*info)[4], length, "%s          All | %c   %c", spaces,
01640                      ((ESUPPL_WAS_FALSE( exp->suppl ) == 1) ? ' ' : '*'),
01641                      ((ESUPPL_WAS_TRUE( exp->suppl )  == 1) ? ' ' : '*') );
01642       assert( rv < length );
01643       for( i=0; i<exp->value->width; i++ ) {
01644         (*info)[i+6] = (char*)malloc_safe( length );
01645         rv = snprintf( (*info)[i+6], length, "%s         %4u | %c   %c", spaces, i,
01646                        ((vector_get_eval_a( exp->value, i ) == 1) ? ' ' : '*'),
01647                        ((vector_get_eval_b( exp->value, i ) == 1) ? ' ' : '*') );
01648         assert( rv < length );
01649       }
01650 
01651     } else {
01652 
01653       length = 16 + strlen( spaces );
01654       (*info)[2] = (char*)malloc_safe( length );  rv = snprintf( (*info)[2], length, "%s         E | E ", spaces );  assert( rv < length );
01655       (*info)[3] = (char*)malloc_safe( length );  rv = snprintf( (*info)[3], length, "%s        =0=|=1=", spaces );  assert( rv < length );
01656 
01657       length = 15 + strlen( spaces );
01658       (*info)[4] = (char*)malloc_safe( length );
01659       rv = snprintf( (*info)[4], length, "%s         %c   %c", spaces,
01660                      ((ESUPPL_WAS_FALSE( exp->suppl ) == 1) ? ' ' : '*'),
01661                      ((ESUPPL_WAS_TRUE( exp->suppl )  == 1) ? ' ' : '*') );
01662       assert( rv < length );
01663 
01664     }
01665 
01666   }
01667 
01668   PROFILE_END;
01669 
01670 }

static void combination_underline ( FILE *  ofile,
char **  code,
unsigned int  code_depth,
expression exp,
func_unit funit 
) [static]
Exceptions:
anonymous combination_underline_tree

Traverses through the expression tree that is on the same line as the parent, creating underline strings. An underline is created for each expression that does not have complete combination logic coverage. Each underline (children to parent creates an inverted tree) and contains a number for the specified expression.

Parameters:
ofile Pointer output stream to display underlines to
code Array of strings containing code to output
code_depth Number of entries in code array
exp Pointer to parent expression to create underline for
funit Pointer to the functional unit containing the expression to underline

References combination_prep_line(), combination_underline_tree(), free_safe, expression_s::line, expression_s::op, PROFILE, and PROFILE_END.

Referenced by combination_display_verbose().

01499   { PROFILE(COMBINATION_UNDERLINE);
01500 
01501   char**       lines;      /* Pointer to a stack of lines */
01502   unsigned int depth;      /* Depth of underline stack */
01503   unsigned int size;       /* Width of stack in characters */
01504   unsigned int i;          /* Loop iterator */
01505   unsigned int j;          /* Loop iterator */
01506   char*        tmpstr;     /* Temporary string variable */
01507   unsigned int start = 0;  /* Starting index */
01508 
01509   combination_underline_tree( exp, 0, &lines, &depth, &size, exp->op, (code_depth == 1), funit );
01510 
01511   for( j=0; j<code_depth; j++ ) {
01512 
01513     assert( code[j] != NULL );
01514 
01515     if( j == 0 ) {
01516       fprintf( ofile, "        %7d:    %s\n", exp->line, code[j] );
01517     } else {
01518       fprintf( ofile, "                    %s\n", code[j] );
01519     }
01520 
01521     if( code_depth == 1 ) {
01522       for( i=0; i<depth; i++ ) {
01523         fprintf( ofile, "                    %s\n", lines[i] );
01524       }
01525     } else {
01526       for( i=0; i<depth; i++ ) {
01527         if( (tmpstr = combination_prep_line( lines[i], start, strlen( code[j] ) )) != NULL ) {
01528           fprintf( ofile, "                    %s\n", tmpstr );
01529           free_safe( tmpstr, (strlen( tmpstr ) + 1) );
01530         }
01531       }
01532     }
01533 
01534     start += strlen( code[j] );
01535 
01536     free_safe( code[j], (strlen( code[j] ) + 1) );
01537 
01538   }
01539 
01540   for( i=0; i<depth; i++ ) {
01541     free_safe( lines[i], (strlen( lines[i] ) + 1) );
01542   }
01543 
01544   if( depth > 0 ) {
01545     free_safe( lines, (sizeof( char* ) * depth) );
01546   }
01547 
01548   if( code_depth > 0 ) {
01549     free_safe( code, (sizeof( char* ) * code_depth) );
01550   }
01551 
01552   PROFILE_END;
01553 
01554 }

static void combination_underline_tree ( expression exp,
unsigned int  curr_depth,
char ***  lines,
unsigned int *  depth,
unsigned int *  size,
exp_op_type  parent_op,
bool  center,
func_unit funit 
) [static]
Exceptions:
anonymous Throw Throw combination_underline_tree combination_underline_tree

Recursively parses specified expression tree, underlining and labeling each measurable expression.

Parameters:
exp Pointer to expression to create underline for
curr_depth Specifies current depth in expression tree
lines Stack of lines for left child
depth Pointer to top of left child stack
size Pointer to character width of this node
parent_op Expression operation of parent used for calculating parenthesis
center Specifies if expression IDs should be centered in underlines or at beginning
funit Pointer to current functional unit containing this expression

References Catch_anonymous, combination_calc_depth(), combination_draw_centered_line(), combination_draw_line(), combination_parenthesize(), vsuppl_u::data_type, DECIMAL, expression_s::elem, ESUPPL_IS_ROOT, ESUPPL_STATIC_BASE, EXP_OP_ADD, EXP_OP_ADD_A, EXP_OP_AEDGE, EXP_OP_ALS_A, EXP_OP_ALSHIFT, EXP_OP_ALWAYS_COMB, EXP_OP_ALWAYS_LATCH, EXP_OP_AND, EXP_OP_AND_A, EXP_OP_ARS_A, EXP_OP_ARSHIFT, EXP_OP_ASSIGN, EXP_OP_BASSIGN, EXP_OP_CASE, EXP_OP_CASEX, EXP_OP_CASEZ, EXP_OP_CEQ, EXP_OP_CNE, EXP_OP_CONCAT, EXP_OP_COND, EXP_OP_COND_SEL, EXP_OP_DASSIGN, EXP_OP_DELAY, EXP_OP_DIM, EXP_OP_DIV_A, EXP_OP_DIVIDE, EXP_OP_DLY_ASSIGN, EXP_OP_DLY_OP, EXP_OP_EOR, EXP_OP_EQ, EXP_OP_EXPAND, EXP_OP_EXPONENT, EXP_OP_FUNC_CALL, EXP_OP_GE, EXP_OP_GT, EXP_OP_IDEC, EXP_OP_IF, EXP_OP_IINC, EXP_OP_LAND, EXP_OP_LAST, EXP_OP_LE, EXP_OP_LIST, EXP_OP_LOR, EXP_OP_LS_A, EXP_OP_LSHIFT, EXP_OP_LT, EXP_OP_MBIT_NEG, EXP_OP_MBIT_POS, EXP_OP_MBIT_SEL, EXP_OP_MLT_A, EXP_OP_MOD, EXP_OP_MOD_A, EXP_OP_MULTIPLY, EXP_OP_NAND, EXP_OP_NASSIGN, EXP_OP_NB_CALL, EXP_OP_NE, EXP_OP_NEDGE, EXP_OP_NEGATE, EXP_OP_NOR, EXP_OP_NXOR, EXP_OP_OR, EXP_OP_OR_A, EXP_OP_PARAM, EXP_OP_PARAM_MBIT, EXP_OP_PARAM_MBIT_NEG, EXP_OP_PARAM_MBIT_POS, EXP_OP_PARAM_SBIT, EXP_OP_PASSIGN, EXP_OP_PDEC, EXP_OP_PEDGE, EXP_OP_PINC, EXP_OP_PLIST, EXP_OP_REPEAT, EXP_OP_RPT_DLY, EXP_OP_RS_A, EXP_OP_RSHIFT, EXP_OP_SASSIGN, EXP_OP_SB2R, EXP_OP_SB2SR, EXP_OP_SBIT_SEL, EXP_OP_SCLOG2, EXP_OP_SI2R, EXP_OP_SIG, EXP_OP_SLIST, EXP_OP_SR2B, EXP_OP_SR2I, EXP_OP_SRANDOM, EXP_OP_SSIGNED, EXP_OP_SSR2B, EXP_OP_SSRANDOM, EXP_OP_STATIC, EXP_OP_STESTARGS, EXP_OP_STIME, EXP_OP_SUB_A, EXP_OP_SUBTRACT, EXP_OP_SUNSIGNED, EXP_OP_SURAND_RANGE, EXP_OP_SURANDOM, EXP_OP_SVALARGS, EXP_OP_TASK_CALL, EXP_OP_TRIGGER, EXP_OP_UAND, EXP_OP_UINV, EXP_OP_UNAND, EXP_OP_UNOR, EXP_OP_UNOT, EXP_OP_UNXOR, EXP_OP_UOR, EXP_OP_UXOR, EXP_OP_WAIT, EXP_OP_WHILE, EXP_OP_XOR, EXP_OP_XOR_A, expr_stmt_u::expr, FALSE, FATAL, free_safe, expression_s::funit, gen_char_string(), expression_s::left, malloc_safe, func_unit_s::name, expression_s::name, expression_s::op, expression_s::parent, esuppl_u::parenthesis, esuppl_u::part, vsuppl_u::part, print_output(), PROFILE, PROFILE_END, QSTRING, vector_s::r32, vector_s::r64, report_comb_depth, REPORT_DETAILED, REPORT_VERBOSE, expression_s::right, scope_extract_back(), scope_gen_printable(), rv32_s::str, rv64_s::str, strdup_safe, expression_s::suppl, vector_s::suppl, Throw, TRUE, Try, expression_s::ulid, user_msg, USER_MSG_LENGTH, vector_s::value, expression_s::value, VDATA_R32, VDATA_R64, vector_to_int(), and vector_to_string().

Referenced by combination_get_expression(), and combination_underline().

00892   { PROFILE(COMBINATION_UNDERLINE_TREE);
00893 
00894   char**       l_lines;         /* Pointer to left underline stack */
00895   char**       r_lines;         /* Pointer to right underline stack */
00896   unsigned int l_depth = 0;     /* Index to top of left stack */
00897   unsigned int r_depth = 0;     /* Index to top of right stack */
00898   unsigned int l_size;          /* Number of characters for left expression */
00899   unsigned int r_size;          /* Number of characters for right expression */
00900   char*        exp_sp;          /* Space to take place of missing expression(s) */
00901   char*        code_fmt;        /* Contains format string for rest of stack */
00902   char*        tmpstr;          /* Temporary string value */
00903   unsigned int comb_missed;     /* If set to 1, current combination was missed */
00904   char*        tmpname = NULL;  /* Temporary pointer to current signal name */
00905   char*        pname;           /* Printable version of signal/function/task name */
00906   func_unit*   tfunit;          /* Temporary pointer to found functional unit */
00907   int          ulid;            /* Underline ID to use */
00908   unsigned int rv;              /* Return value from snprintf calls */
00909   
00910   *depth      = 0;
00911   *size       = 0;
00912   l_lines     = NULL;
00913   r_lines     = NULL;
00914   comb_missed = 0;
00915   code_fmt    = (char*)malloc_safe( 300 );
00916 
00917   if( exp != NULL ) {
00918 
00919     if( (exp->op == EXP_OP_LAST) || (exp->op == EXP_OP_NB_CALL) ) {
00920 
00921       *size = 0;
00922 
00923     } else if( exp->op == EXP_OP_STATIC ) {
00924 
00925       unsigned int data_type = exp->value->suppl.part.data_type;
00926 
00927       if( data_type == VDATA_R64 ) {
00928 
00929         *size = strlen( exp->value->value.r64->str );
00930 
00931       } else if( data_type == VDATA_R32 ) {
00932 
00933         *size = strlen( exp->value->value.r32->str );
00934 
00935       } else if( ESUPPL_STATIC_BASE( exp->suppl ) == DECIMAL ) {
00936 
00937         rv = snprintf( code_fmt, 300, "%d", vector_to_int( exp->value ) );
00938         assert( rv < 300 );
00939         *size = strlen( code_fmt );
00940 
00941         /*
00942          If the size of this decimal value is only 1 and its parent is a NEGATE op,
00943          make it two so that we don't have problems with negates and the like later.
00944         */
00945         if( (*size == 1) && (exp->parent->expr->op == EXP_OP_NEGATE) ) {
00946           *size = 2;
00947         }
00948       
00949       } else {
00950 
00951         tmpstr = vector_to_string( exp->value, ESUPPL_STATIC_BASE( exp->suppl ), FALSE, 0 );
00952         *size  = strlen( tmpstr );
00953         free_safe( tmpstr, (strlen( tmpstr ) + 1) );
00954 
00955         /* Adjust for quotation marks */
00956         if( ESUPPL_STATIC_BASE( exp->suppl ) == QSTRING ) {
00957           *size += 2;
00958         }
00959 
00960       }
00961 
00962     } else if( exp->op == EXP_OP_SLIST ) {
00963 
00964       *size = 2;
00965       strcpy( code_fmt, "@*" );
00966 
00967     } else if( exp->op == EXP_OP_ALWAYS_COMB ) {
00968 
00969       *size = 11;
00970       strcpy( code_fmt, "always_comb" );
00971 
00972     } else if( exp->op == EXP_OP_ALWAYS_LATCH ) {
00973    
00974       *size = 12;
00975       strcpy( code_fmt, "always_latch" );
00976 
00977     } else if( exp->op == EXP_OP_STIME ) {
00978 
00979       *size = 5;
00980       strcpy( code_fmt, "$time" );
00981 
00982     } else if( (exp->op == EXP_OP_SRANDOM) && (exp->left == NULL) ) {
00983 
00984       *size = 7;
00985       strcpy( code_fmt, "$random" );
00986 
00987     } else if( (exp->op == EXP_OP_SURANDOM) && (exp->left == NULL) ) {
00988 
00989       *size = 8;
00990       strcpy( code_fmt, "$urandom" );
00991 
00992     } else {
00993 
00994       Try {
00995 
00996         if( (exp->op == EXP_OP_SIG) || (exp->op == EXP_OP_PARAM) ) {
00997 
00998           tmpname = scope_gen_printable( exp->name );
00999           *size   = strlen( tmpname );
01000           switch( *size ) {
01001             case 0 :  assert( *size > 0 );                     break;
01002             case 1 :  *size = 3;  strcpy( code_fmt, " %s " );  break;
01003             case 2 :  *size = 3;  strcpy( code_fmt, " %s" );   break;
01004             default:  strcpy( code_fmt, "%s" );                break;
01005           }
01006 
01007           free_safe( tmpname, (strlen( tmpname ) + 1) );
01008         
01009         } else {
01010 
01011           bool paren = (exp->suppl.part.parenthesis == 1);
01012 
01013           combination_underline_tree( exp->left,  combination_calc_depth( exp, curr_depth, TRUE ),  &l_lines, &l_depth, &l_size, exp->op, center, funit );
01014           combination_underline_tree( exp->right, combination_calc_depth( exp, curr_depth, FALSE ), &r_lines, &r_depth, &r_size, exp->op, center, funit );
01015 
01016           switch( exp->op ) {
01017             case EXP_OP_XOR        :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01018             case EXP_OP_XOR_A      :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01019             case EXP_OP_MULTIPLY   :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01020             case EXP_OP_MLT_A      :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01021             case EXP_OP_DIVIDE     :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01022             case EXP_OP_DIV_A      :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01023             case EXP_OP_MOD        :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01024             case EXP_OP_MOD_A      :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01025             case EXP_OP_ADD        :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01026             case EXP_OP_ADD_A      :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01027             case EXP_OP_SUBTRACT   :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01028             case EXP_OP_SUB_A      :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01029             case EXP_OP_EXPONENT   :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01030             case EXP_OP_AND        :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01031             case EXP_OP_AND_A      :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01032             case EXP_OP_OR         :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01033             case EXP_OP_OR_A       :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01034             case EXP_OP_NAND       :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01035             case EXP_OP_NOR        :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01036             case EXP_OP_NXOR       :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01037             case EXP_OP_LT         :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01038             case EXP_OP_GT         :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01039             case EXP_OP_LSHIFT     :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01040             case EXP_OP_LS_A       :  *size = l_size + r_size + 5;  combination_parenthesize( paren, "%s     %s",  &code_fmt, size );  break;
01041             case EXP_OP_ALSHIFT    :  *size = l_size + r_size + 5;  combination_parenthesize( paren, "%s     %s",  &code_fmt, size );  break;
01042             case EXP_OP_ALS_A      :  *size = l_size + r_size + 6;  combination_parenthesize( paren, "%s      %s", &code_fmt, size );  break;
01043             case EXP_OP_RSHIFT     :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01044             case EXP_OP_RS_A       :  *size = l_size + r_size + 5;  combination_parenthesize( paren, "%s     %s",  &code_fmt, size );  break;
01045             case EXP_OP_ARSHIFT    :  *size = l_size + r_size + 5;  combination_parenthesize( paren, "%s     %s",  &code_fmt, size );  break;
01046             case EXP_OP_ARS_A      :  *size = l_size + r_size + 6;  combination_parenthesize( paren, "%s      %s", &code_fmt, size );  break;
01047             case EXP_OP_EQ         :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01048             case EXP_OP_CEQ        :  *size = l_size + r_size + 5;  combination_parenthesize( paren, "%s     %s",  &code_fmt, size );  break;
01049             case EXP_OP_LE         :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01050             case EXP_OP_GE         :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01051             case EXP_OP_NE         :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01052             case EXP_OP_CNE        :  *size = l_size + r_size + 5;  combination_parenthesize( paren, "%s     %s",  &code_fmt, size );  break;
01053             case EXP_OP_LOR        :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01054             case EXP_OP_LAND       :  *size = l_size + r_size + 4;  combination_parenthesize( paren, "%s    %s",   &code_fmt, size );  break;
01055             case EXP_OP_COND       :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01056             case EXP_OP_COND_SEL   :  *size = l_size + r_size + 3;  combination_parenthesize( paren, "%s   %s",    &code_fmt, size );  break;
01057             case EXP_OP_UINV       :  *size = l_size + r_size + 1;  combination_parenthesize( paren, " %s",        &code_fmt, size );  break;
01058             case EXP_OP_UAND       :  *size = l_size + r_size + 1;  combination_parenthesize( paren, " %s",        &code_fmt, size );  break;
01059             case EXP_OP_UNOT       :  *size = l_size + r_size + 1;  combination_parenthesize( paren, " %s",        &code_fmt, size );  break;
01060             case EXP_OP_UOR        :  *size = l_size + r_size + 1;  combination_parenthesize( paren, " %s",        &code_fmt, size );  break;
01061             case EXP_OP_UXOR       :  *size = l_size + r_size + 1;  combination_parenthesize( paren, " %s",        &code_fmt, size );  break;
01062             case EXP_OP_UNAND      :  *size = l_size + r_size + 2;  combination_parenthesize( paren, "  %s",       &code_fmt, size );  break;
01063             case EXP_OP_UNOR       :  *size = l_size + r_size + 2;  combination_parenthesize( paren, "  %s",       &code_fmt, size );  break;
01064             case EXP_OP_UNXOR      :  *size = l_size + r_size + 2;  combination_parenthesize( paren, "  %s",       &code_fmt, size );  break;
01065             case EXP_OP_PARAM_SBIT :
01066             case EXP_OP_SBIT_SEL   :  
01067               if( (ESUPPL_IS_ROOT( exp->suppl ) == 0) &&
01068                   (exp->parent->expr->op == EXP_OP_DIM) &&
01069                   (exp->parent->expr->right == exp) ) {
01070                 *size = l_size + r_size + 2;
01071                 code_fmt[0] = '\0';
01072               } else {
01073                 unsigned int i;
01074                 tmpname = scope_gen_printable( exp->name );
01075                 *size = l_size + r_size + strlen( tmpname ) + 2;
01076                 for( i=0; i<strlen( tmpname ); i++ ) {
01077                   code_fmt[i] = ' ';
01078                 }
01079                 code_fmt[i] = '\0';
01080               }
01081               strcat( code_fmt, " %s " );
01082               free_safe( tmpname, (strlen( tmpname ) + 1) );
01083               break;
01084             case EXP_OP_PARAM_MBIT :
01085             case EXP_OP_MBIT_SEL   :  
01086               if( (ESUPPL_IS_ROOT( exp->suppl ) == 0) &&
01087                   (exp->parent->expr->op == EXP_OP_DIM) &&
01088                   (exp->parent->expr->right == exp) ) {
01089                 *size = l_size + r_size + 3;
01090                 code_fmt[0] = '\0';
01091               } else {
01092                 unsigned int i;
01093                 tmpname = scope_gen_printable( exp->name );
01094                 *size = l_size + r_size + strlen( tmpname ) + 3;  
01095                 for( i=0; i<strlen( tmpname ); i++ ) {
01096                   code_fmt[i] = ' ';
01097                 }
01098                 code_fmt[i] = '\0';
01099               }
01100               strcat( code_fmt, " %s %s " );
01101               free_safe( tmpname, (strlen( tmpname ) + 1) );
01102               break;
01103             case EXP_OP_PARAM_MBIT_POS :
01104             case EXP_OP_PARAM_MBIT_NEG :
01105             case EXP_OP_MBIT_POS       :
01106             case EXP_OP_MBIT_NEG       :
01107               if( (ESUPPL_IS_ROOT( exp->suppl ) == 0) &&
01108                   (exp->parent->expr->op == EXP_OP_DIM) &&
01109                   (exp->parent->expr->right == exp) ) {
01110                 *size = l_size + r_size + 4;
01111                 code_fmt[0] = '\0';
01112               } else {
01113                 unsigned int i;
01114                 tmpname = scope_gen_printable( exp->name );
01115                 *size = l_size + r_size + strlen( tmpname ) + 4;
01116                 for( i=0; i<strlen( tmpname ); i++ ) {
01117                   code_fmt[i] = ' ';
01118                 }
01119                 code_fmt[i] = '\0';
01120               }
01121               strcat( code_fmt, " %s  %s " );
01122               free_safe( tmpname, (strlen( tmpname ) + 1) );
01123               break;
01124             case EXP_OP_TRIGGER  :
01125               {
01126                 unsigned int i;
01127                 tmpname = scope_gen_printable( exp->name );
01128                 *size = l_size + r_size + strlen( tmpname ) + 2;
01129                 for( i=0; i<strlen( tmpname ) + 2; i++ ) {
01130                   code_fmt[i] = ' ';
01131                 }
01132                 code_fmt[i] = '\0';
01133                 free_safe( tmpname, (strlen( tmpname ) + 1) );
01134               }
01135               break;
01136             case EXP_OP_EXPAND   :  *size = l_size + r_size + 4;  strcpy( code_fmt, " %s %s  "         );  break;
01137             case EXP_OP_CONCAT   :  *size = l_size + r_size + 2;  strcpy( code_fmt, " %s "             );  break;
01138             case EXP_OP_PLIST    :
01139             case EXP_OP_LIST     :  *size = l_size + r_size + 2;  strcpy( code_fmt, "%s  %s"           );  break;
01140             case EXP_OP_PEDGE    :
01141               if( (ESUPPL_IS_ROOT( exp->suppl ) == 1)       ||
01142                   (exp->parent->expr->op == EXP_OP_RPT_DLY) ||
01143                   (exp->parent->expr->op == EXP_OP_DLY_OP) ) {
01144                 *size = l_size + r_size + 11;  strcpy( code_fmt, "          %s " );
01145               } else {
01146                 *size = l_size + r_size + 8;   strcpy( code_fmt, "        %s" );
01147               }
01148               break;
01149             case EXP_OP_NEDGE    :
01150               if( (ESUPPL_IS_ROOT( exp->suppl ) == 1)       ||
01151                   (exp->parent->expr->op == EXP_OP_RPT_DLY) ||
01152                   (exp->parent->expr->op == EXP_OP_DLY_OP) ) {
01153                 *size = l_size + r_size + 11;  strcpy( code_fmt, "          %s " );
01154               } else {
01155                 *size = l_size + r_size + 8;   strcpy( code_fmt, "        %s" );
01156               }
01157               break;
01158             case EXP_OP_AEDGE    :
01159               if( (ESUPPL_IS_ROOT( exp->suppl ) == 1)       ||
01160                   (exp->parent->expr->op == EXP_OP_RPT_DLY) ||
01161                   (exp->parent->expr->op == EXP_OP_DLY_OP) ) {
01162                 *size = l_size + r_size + 3;  strcpy( code_fmt, "  %s " );
01163               } else {
01164                 *size = l_size + r_size + 0;  strcpy( code_fmt, "%s" );
01165               }
01166               break;
01167             case EXP_OP_EOR      :
01168               if( (ESUPPL_IS_ROOT( exp->suppl ) == 1)       ||
01169                   (exp->parent->expr->op == EXP_OP_RPT_DLY) ||
01170                   (exp->parent->expr->op == EXP_OP_DLY_OP) ) {
01171                 *size = l_size + r_size + 7;  strcpy( code_fmt, "  %s    %s " );
01172               } else {
01173                 *size = l_size + r_size + 4;  strcpy( code_fmt, "%s    %s" );
01174               }
01175               break;
01176             case EXP_OP_CASE     :  *size = l_size + r_size + 11; strcpy( code_fmt, "      %s   %s  "  );  break;
01177             case EXP_OP_CASEX    :  *size = l_size + r_size + 12; strcpy( code_fmt, "       %s   %s  " );  break;
01178             case EXP_OP_CASEZ    :  *size = l_size + r_size + 12; strcpy( code_fmt, "       %s   %s  " );  break;
01179             case EXP_OP_DELAY    :  *size = r_size + 3;  strcpy( code_fmt, "  %s " );             break;
01180             case EXP_OP_ASSIGN   :  *size = l_size + r_size + 10; strcpy( code_fmt, "       %s   %s" );    break;
01181             case EXP_OP_DASSIGN  :
01182             case EXP_OP_DLY_ASSIGN :
01183             case EXP_OP_BASSIGN  :  *size = l_size + r_size + 3;  strcpy( code_fmt, "%s   %s" );           break;
01184             case EXP_OP_NASSIGN  :  *size = l_size + r_size + 4;  strcpy( code_fmt, "%s    %s" );          break;
01185             case EXP_OP_SASSIGN  :
01186             case EXP_OP_PASSIGN  :  *size = r_size;               strcpy( code_fmt, "%s" );                break;
01187             case EXP_OP_IF       :  *size = r_size + 6;           strcpy( code_fmt, "    %s  " );          break;
01188             case EXP_OP_REPEAT   :  *size = r_size + 10;          strcpy( code_fmt, "        %s  " );      break;
01189             case EXP_OP_WHILE    :  *size = r_size + 9;           strcpy( code_fmt, "       %s  " );       break;
01190             case EXP_OP_WAIT     :  *size = r_size + 8;           strcpy( code_fmt, "      %s  " );        break;
01191             case EXP_OP_DLY_OP   :
01192             case EXP_OP_RPT_DLY  :  *size = l_size + r_size + 1;  strcpy( code_fmt, "%s %s" );             break;
01193             case EXP_OP_TASK_CALL :
01194             case EXP_OP_FUNC_CALL :
01195               {
01196                 unsigned int i;
01197                 tfunit = exp->elem.funit;
01198                 tmpname = strdup_safe( tfunit->name );
01199                 scope_extract_back( tfunit->name, tmpname, user_msg );
01200                 pname = scope_gen_printable( tmpname );
01201                 *size = l_size + r_size + strlen( pname ) + 4;
01202                 for( i=0; i<strlen( pname ); i++ ) {
01203                   code_fmt[i] = ' ';
01204                 }
01205                 code_fmt[i] = '\0';
01206                 strcat( code_fmt, "  %s  " );
01207                 free_safe( tmpname, (strlen( tfunit->name ) + 1) );
01208                 free_safe( pname, (strlen( pname ) + 1) );
01209               }
01210               break;
01211             case EXP_OP_NEGATE       :  *size = l_size + r_size + 1;  strcpy( code_fmt, " %s"                    );  break;
01212             case EXP_OP_DIM          :  *size = l_size + r_size;      strcpy( code_fmt, "%s%s"                   );  break;
01213             case EXP_OP_IINC         :
01214             case EXP_OP_IDEC         :  *size = l_size + 2;           strcpy( code_fmt, "  %s"                   );  break;
01215             case EXP_OP_PINC         :
01216             case EXP_OP_PDEC         :  *size = l_size + 2;           strcpy( code_fmt, "%s  "                   );  break;
01217             case EXP_OP_SSIGNED      :  *size = l_size + 11;          strcpy( code_fmt, "         %s  "          );  break;
01218             case EXP_OP_SUNSIGNED    :  *size = l_size + 13;          strcpy( code_fmt, "           %s  "        );  break;
01219             case EXP_OP_SCLOG2       :  *size = l_size + 10;          strcpy( code_fmt, "        %s  "           );  break;
01220             case EXP_OP_SRANDOM      :  *size = l_size + 11;          strcpy( code_fmt, "         %s  "          );  break;
01221             case EXP_OP_SURANDOM     :  *size = l_size + 12;          strcpy( code_fmt, "          %s  "         );  break;
01222             case EXP_OP_SURAND_RANGE :  *size = l_size + 18;          strcpy( code_fmt, "                %s  "   );  break;
01223             case EXP_OP_SSRANDOM     :  *size = l_size + 12;          strcpy( code_fmt, "          %s  "         );  break;
01224             case EXP_OP_SR2B         :
01225             case EXP_OP_SB2R         :  *size = l_size + 15;          strcpy( code_fmt, "             %s  "      );  break;
01226             case EXP_OP_SI2R         :
01227             case EXP_OP_SR2I         :  *size = l_size + 9;           strcpy( code_fmt, "       %s  "            );  break;
01228             case EXP_OP_SSR2B        :
01229             case EXP_OP_SB2SR        :  *size = l_size + 20;          strcpy( code_fmt, "                  %s  " );  break;
01230             case EXP_OP_STESTARGS    :  *size = l_size + 18;          strcpy( code_fmt, "                %s  "   );  break;
01231             case EXP_OP_SVALARGS     :  *size = l_size + 19;          strcpy( code_fmt, "                 %s  "  );  break;
01232             default              :
01233               rv = snprintf( user_msg, USER_MSG_LENGTH, "Internal error:  Unknown expression type in combination_underline_tree (%d)", exp->op );
01234               assert( rv < USER_MSG_LENGTH );
01235               print_output( user_msg, FATAL, __FILE__, __LINE__ );
01236               Throw 0;
01237               /*@-unreachable@*/
01238               break;
01239               /*@=unreachable@*/
01240   
01241           }
01242 
01243         }
01244 
01245         /* Calculate ulid */
01246         ulid = exp->ulid;
01247 
01248         comb_missed = (((report_comb_depth == REPORT_DETAILED) && (curr_depth <= report_comb_depth)) ||
01249                         (report_comb_depth == REPORT_VERBOSE)) ? ((ulid != -1) ? 1 : 0) : 0;
01250 
01251         if( l_depth > r_depth ) {
01252           *depth = l_depth + comb_missed;
01253         } else {
01254           *depth = r_depth + comb_missed;
01255         }
01256       
01257         if( *depth > 0 ) {
01258 
01259           unsigned int i;
01260                 
01261           /* Allocate all memory for the stack */
01262           *lines = (char**)malloc_safe( sizeof( char* ) * (*depth) );
01263 
01264           /* Create underline or space */
01265           if( comb_missed == 1 ) {
01266 
01267             /* Allocate memory for this underline */
01268             (*lines)[(*depth)-1] = (char*)malloc_safe( *size + 1 );
01269 
01270             if( center ) {
01271               combination_draw_centered_line( (*lines)[(*depth)-1], *size, ulid, TRUE, TRUE );
01272             } else {
01273               combination_draw_line( (*lines)[(*depth)-1], *size, ulid );
01274             }
01275             /* printf( "Drawing line (%s), size: %d, depth: %d\n", (*lines)[(*depth)-1], *size, (*depth) ); */
01276           }
01277 
01278           /* Combine the left and right line stacks */
01279           for( i=0; i<(*depth - comb_missed); i++ ) {
01280 
01281             (*lines)[i] = (char*)malloc_safe( *size + 1 );
01282 
01283             if( (i < l_depth) && (i < r_depth) ) {
01284             
01285               /* Merge left and right lines */
01286               rv = snprintf( (*lines)[i], (*size + 1), code_fmt, l_lines[i], r_lines[i] );
01287               assert( rv < (*size + 1) );
01288             
01289               free_safe( l_lines[i], (strlen( l_lines[i] ) + 1) );
01290               free_safe( r_lines[i], (strlen( r_lines[i] ) + 1) );
01291 
01292             } else if( i < l_depth ) {
01293             
01294               /* Create spaces for right side */
01295               exp_sp = (char*)malloc_safe( r_size + 1 );
01296               gen_char_string( exp_sp, ' ', r_size );
01297 
01298               /* Merge left side only */
01299               rv = snprintf( (*lines)[i], (*size + 1), code_fmt, l_lines[i], exp_sp );
01300               assert( rv < (*size + 1) );
01301             
01302               free_safe( l_lines[i], (strlen( l_lines[i] ) + 1) );
01303               free_safe( exp_sp, (r_size + 1) );
01304 
01305             } else if( i < r_depth ) {
01306 
01307               if( l_size == 0 ) { 
01308 
01309                 rv = snprintf( (*lines)[i], (*size + 1), code_fmt, r_lines[i] );
01310                 assert( rv < (*size + 1) );
01311 
01312               } else {
01313 
01314                 /* Create spaces for left side */
01315                 exp_sp = (char*)malloc_safe( l_size + 1 );
01316                 gen_char_string( exp_sp, ' ', l_size );
01317 
01318                 /* Merge right side only */
01319                 rv = snprintf( (*lines)[i], (*size + 1), code_fmt, exp_sp, r_lines[i] );
01320                 assert( rv < (*size + 1) );
01321               
01322                 free_safe( exp_sp, (l_size + 1) );
01323           
01324               }
01325   
01326               free_safe( r_lines[i], (strlen( r_lines[i] ) + 1) );
01327    
01328             } else {
01329 
01330               print_output( "Internal error:  Reached entry without a left or right underline", FATAL, __FILE__, __LINE__ );
01331               Throw 0;
01332 
01333             }
01334 
01335           }
01336 
01337           /* Free left child stack */
01338           if( l_depth > 0 ) {
01339             free_safe( l_lines, (sizeof( char* ) * l_depth) );
01340           }
01341 
01342           /* Free right child stack */
01343           if( r_depth > 0 ) {
01344             free_safe( r_lines, (sizeof( char* ) * r_depth) );
01345           }
01346 
01347         }
01348 
01349       } Catch_anonymous {
01350         unsigned int i;
01351         for( i=0; i<(*depth - comb_missed); i++ ) {
01352           free_safe( (*lines)[i], (strlen( (*lines)[i] ) + 1) );
01353         }
01354         free_safe( *lines, (sizeof( char* ) * (*depth - comb_missed)) );
01355         *lines = NULL;
01356         *depth = 0;
01357         for( i=0; i<l_depth; i++ ) {
01358           free_safe( l_lines[i], (strlen( l_lines[i] ) + 1) );
01359         }
01360         free_safe( l_lines, (sizeof( char* ) * l_depth) );
01361         for( i=0; i<r_depth; i++ ) {
01362           free_safe( r_lines[i], (strlen( r_lines[i] ) + 1) );
01363         }
01364         free_safe( r_lines, (sizeof( char* ) * r_depth) );
01365         Throw 0;
01366       }
01367 
01368     }
01369 
01370   }
01371 
01372   /* Deallocate the code_fmt string */
01373   free_safe( code_fmt, 300 );
01374 
01375   PROFILE_END;
01376     
01377 }


Variable Documentation

Controls whether multi-expressions are used or not.

Referenced by combination_get_tree_stats(), and command_rank().

unsigned int curr_db

Index of current database in db_list array that is being handled.

Array of database pointers storing all currently loaded databases.

const exp_info exp_op_info[EXP_OP_NUM]

Array containing static information about expression operation types. NOTE: This structure MUST be updated if a new expression is added! The third argument is an initialization to the exp_info_s structure.

Informational line for the CDD file.

Specifies the number of characters wide that an expression will allowed to be output for if the flag_use_line_width value is set to TRUE.

If set to a boolean value of TRUE, displays all vector combinational logic on a bitwise basis.

Referenced by combination_get_tree_stats(), combination_two_vars(), combination_unary(), and report_parse_args().

unsigned int report_comb_depth

If set to a non-zero value, causes Covered to only generate combinational logic report information for depths up to the number specified.

Referenced by combination_calc_depth(), combination_get_missed_expr(), combination_get_tree_stats(), combination_output_expr(), combination_underline_tree(), report_generate(), report_parse_args(), and report_print_header().

If set to a boolean value of TRUE, displays covered logic for a particular CDD file. By default, Covered will display uncovered logic. Must be used in conjunction with the -d v|d (verbose output) option.

If set to a boolean value of TRUE, displays excluded coverage points for a particular CDD file. By default, Covered will not display excluded coverage points. This can be useful when used in conjunction with the -x option for including excluded coverage points. Must be used in conjunction with the -d v|d (verbose output) option.

If set to a boolean value of TRUE, provides a coverage information for individual functional unit instances. If set to a value of FALSE, reports coverage information on a functional unit basis, merging results from all instances of same functional unit.

char user_msg[USER_MSG_LENGTH]

Holds some output that will be displayed via the print_output command. This is created globally so that memory does not need to be reallocated for each function that wishes to use it.

Generated on Sun Nov 21 00:55:37 2010 for Covered by  doxygen 1.6.3